Skip to content

Commit a985f78

Browse files
committed
Merge branch 'refs/heads/admin-verification-update'
2 parents d8a1775 + d19e0de commit a985f78

File tree

6 files changed

+84
-90
lines changed

6 files changed

+84
-90
lines changed

motobot/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from .decorators import hook, command, match, sink, request
55
from .priority import Priority
66
from .modifiers import Action, CTCP, Target, Command, Notice, Eat
7-
from .utilities import strip_control_codes, split_response, Context, BotError
7+
from .utilities import strip_control_codes, split_response, Context, BotError, hostmask_check
88

99

1010
__VERSION__ = '0.3'

motobot/core_plugins/ctcp.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ def ctcp_match(bot, context, message, match):
88
'VERSION': 'MotoBot Version ' + __VERSION__,
99
'FINGER': 'Oh you dirty man!',
1010
'TIME': strftime('%a %b %d %H:%M:%S UTC', gmtime()),
11-
'PING': message
11+
'PING': message.strip('\x01')
1212
}
1313
try:
14-
ctcp_req = match.group(1)
14+
ctcp_req = match.group(1).split(' ', 1)[0]
1515
reply = ctcp_response[ctcp_req]
16-
response = (reply, Notice(context.nick), Eat)
16+
response = ('\x01{}\x01'.format(reply), Notice(context.nick), Eat)
1717
except KeyError:
1818
response = None
1919
return response
Lines changed: 66 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,81 @@
1-
from motobot import hook, sink, request, Priority
2-
3-
4-
def get_master_lists(bot, session):
5-
confirmed, unconfirmed = session.get((set(), None))
6-
7-
if unconfirmed is None:
8-
unconfirmed = set(map(str.lower, bot.masters))
9-
session.set((confirmed, unconfirmed))
10-
11-
return confirmed, unconfirmed
1+
from motobot import hook, request, command, BotError, Notice, hostmask_check, Priority, IRCLevel, split_response
122

133

144
@request('IS_MASTER')
15-
def is_master_request(bot, context, nick):
16-
confirmed = get_master_lists(bot, context.session)[0]
17-
return nick.lower() in confirmed
18-
5+
def is_master_request(bot, context, nick, host=None):
6+
recognised = context.session.get(set())
7+
admin_masks = context.database.get([])
8+
return nick.lower() in recognised or \
9+
any(hostmask_check(nick, host, mask) for mask in admin_masks)
1910

20-
def check(bot, session, nick):
21-
""" Check a user by sending a WHOIS query. """
22-
confirmed, unconfirmed = get_master_lists(bot, session)
23-
24-
if nick.lower() in unconfirmed:
25-
bot.send('WHOIS ' + nick)
26-
27-
28-
def verify(bot, session, nick):
29-
""" Mark a master as verified in the bot. """
30-
nick = nick.lower()
31-
confirmed, unconfirmed = get_master_lists(bot, session)
3211

12+
@command('identify', hidden=True, priority=Priority.max)
13+
def identify_command(bot, context, message, args):
3314
try:
34-
unconfirmed.remove(nick)
35-
confirmed.add(nick)
36-
except KeyError:
37-
pass
15+
password = bot.admin_pass
16+
except AttributeError:
17+
raise BotError("Error: I've not been configured with a password.", Notice(context.nick))
3818

19+
input_pass = ' '.join(args[1:])
20+
if input_pass == password:
21+
recognise(context.session, context.nick)
22+
response = 'You are now recognised as a bot admin.'
23+
else:
24+
response = 'Error: Password incorrect.'
25+
return response, Notice(context.nick)
3926

40-
def unverify(bot, session, nick):
41-
""" Unmark a user as verified in the bot. """
42-
nick = nick.lower()
43-
confirmed, unconfirmed = get_master_lists(bot, session)
44-
45-
try:
46-
confirmed.remove(nick)
47-
unconfirmed.add(nick)
48-
except KeyError:
49-
pass
5027

28+
def recognise(session, nick):
29+
admins = session.get(set())
30+
admins.add(nick.lower())
31+
session.set(admins)
5132

52-
@hook('307')
53-
def registered_nick_confirm_rizon(bot, context, message):
54-
""" Hooks the user is registered reply from a WHOIS query and verifies user. """
55-
verify(bot, context.session, message.params[1])
5633

57-
58-
@hook('330')
59-
def registered_nick_confirm_freenode(bot, context, message):
60-
""" Hooks the user is registered reply from a WHOIS query and verifies user. """
61-
if message.params[1] == message.params[2]:
62-
verify(bot, context.session, message.params[2])
63-
64-
65-
@sink(priority=Priority.max)
66-
def master_verification_sink(bot, context, message):
67-
""" Checks a user that speaks in the channel. """
68-
check(bot, context.session, context.nick)
69-
70-
71-
@hook('353')
72-
def handle_names(bot, context, message):
73-
""" Check users whom are present in the channel upon joining. """
74-
names = message.params[-1].split(' ')
75-
for name in names:
76-
check(bot, context.session, name.lstrip('+%@&~'))
77-
78-
79-
@hook('JOIN')
80-
def handle_join(bot, context, message):
81-
""" Check a user that joins a channel. """
82-
check(bot, context.session, message.nick)
34+
@command('adminmask', level=IRCLevel.master)
35+
def adminmask_command(bot, context, message, args):
36+
try:
37+
arg = args[1].lower()
38+
if arg == 'add':
39+
response = add_mask(context.database, args[2])
40+
elif arg in ('del', 'rem'):
41+
response = del_mask(context.database, args[2])
42+
elif arg in ('show', 'list'):
43+
response = show_masks(context.database)
44+
else:
45+
response = 'Error: Invalid argument;'
46+
except IndexError:
47+
response = "Not enough arguments provided."
48+
return response, Notice(context.nick)
49+
50+
51+
def add_mask(database, mask):
52+
masks = database.get([])
53+
if mask not in masks:
54+
masks.append(mask)
55+
database.set(masks)
56+
response = "Mask added successfully."
57+
else:
58+
response = "Error: Mask already in masks list."
59+
return response
60+
61+
62+
def del_mask(database, mask):
63+
masks = database.get([])
64+
try:
65+
masks.remove(mask)
66+
database.set(masks)
67+
response = "Mask successfully deleted."
68+
except ValueError:
69+
response = "Error: Mask not in masks list."
70+
return response
8371

8472

85-
@hook('NICK')
86-
def handle_nick(bot, context, message):
87-
""" Unmark a user as verified in the bot and check new nick. """
88-
unverify(bot, context.session, message.nick)
89-
check(bot, context.session, message.params[0])
73+
def show_masks(database):
74+
masks = database.get([])
9075

76+
if masks:
77+
response = split_response(masks, "Admin masks: {};")
78+
else:
79+
response = "I don't have any admin masks."
9180

92-
@hook('QUIT')
93-
def handle_quit(bot, context, message):
94-
""" Unmark a user as verified in the bot upon quit. """
95-
unverify(bot, context.session, message.nick)
81+
return response

motobot/core_plugins/privmsg_handlers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def handle_command(plugin, bot, context, message):
134134
test = message.split(' ', 1)[0]
135135

136136
if trigger == test:
137-
alt = bot.request('USERLEVEL', context.channel, context.nick) < plugin.level
137+
alt = bot.request('USERLEVEL', context.channel, context.nick, context.host) < plugin.level
138138
func = plugin.func if not alt else plugin.alt
139139
if func is not None:
140140
args = message[len(bot.command_prefix):].split(' ')
@@ -144,14 +144,14 @@ def handle_command(plugin, bot, context, message):
144144
def handle_match(plugin, bot, context, message):
145145
match = plugin.arg.search(message)
146146
if match is not None:
147-
alt = bot.request('USERLEVEL', context.channel, context.nick) < plugin.level
147+
alt = bot.request('USERLEVEL', context.channel, context.nick, context.host) < plugin.level
148148
func = plugin.func if not alt else plugin.alt
149149
if func is not None:
150150
return func(bot, context, message, match)
151151

152152

153153
def handle_sink(plugin, bot, context, message):
154-
alt = bot.request('USERLEVEL', context.channel, context.nick) < plugin.level
154+
alt = bot.request('USERLEVEL', context.channel, context.nick, context.host) < plugin.level
155155
func = plugin.func if not alt else plugin.alt
156156
if func is not None:
157157
return func(bot, context, message)

motobot/core_plugins/userlist_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ def userlist_request(bot, context, channel):
2626

2727

2828
@request('USERLEVEL')
29-
def userlevel_request(bot, context, channel, nick):
29+
def userlevel_request(bot, context, channel, nick, host=None):
3030
userlevel_data = context.session.get({})
3131
level = IRCLevel.user
32-
if bot.request('IS_MASTER', nick):
32+
if bot.request('IS_MASTER', nick, host):
3333
level = IRCLevel.master
3434
elif channel.lower() == bot.nick.lower():
3535
level = IRCLevel.owner

motobot/utilities.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections import namedtuple
2-
from re import compile
2+
from re import compile, match, IGNORECASE
3+
from fnmatch import translate
34

45

56
Context = namedtuple('Context', 'nick channel host database session')
@@ -35,3 +36,10 @@ def strip_control_codes(input):
3536
""" Strip the control codes from the input. """
3637
output = pattern.sub('', input)
3738
return output
39+
40+
41+
def hostmask_check(nick, host, mask):
42+
""" Check a nick and host against a hostmask. """
43+
nickhost = "{}!{}".format(nick, host)
44+
mask_regex = translate(mask)
45+
return match(mask_regex, nickhost, IGNORECASE)

0 commit comments

Comments
 (0)