You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.7 KiB

import re
class BotConfig(object):
# Whether the bot must be mentioned to respond to a command
command_require_mention = True
# Rules about what mentions trigger the bot
command_mention_rules = {
# 'here': False,
'everyone': False,
'role': True,
'user': True,
}
# The prefix required for EVERY command
command_prefix = ''
# Whether an edited message can trigger a command
command_allow_edit = True
class Bot(object):
def __init__(self, client, config=None):
self.client = client
self.config = config or BotConfig()
self.plugins = {}
self.client.events.on('MessageCreate', self.on_message_create)
self.client.events.on('MessageUpdate', self.on_message_update)
# Stores the last message for every single channel
self.last_message_cache = {}
# Stores a giant regex matcher for all commands
self.command_matches_re = None
@property
def commands(self):
for plugin in self.plugins.values():
for command in plugin.commands:
yield command
def compute_command_matches_re(self):
re_str = '|'.join(command.regex for command in self.commands)
print re_str
if re_str:
self.command_matches_re = re.compile(re_str)
else:
self.command_matches_re = None
def handle_message(self, msg):
content = msg.content
if self.config.command_require_mention:
match = any((
self.config.command_mention_rules['user'] and msg.is_mentioned(self.client.state.me),
self.config.command_mention_rules['everyone'] and msg.mention_everyone,
self.config.command_mention_rules['role'] and any(map(msg.is_mentioned,
msg.guild.get_member(self.client.state.me).roles
))))
if not match:
return False
content = msg.without_mentions.strip()
if self.config.command_prefix and not content.startswith(self.config.command_prefix):
return False
if not self.command_matches_re or not self.command_matches_re.match(content):
return False
for command in self.commands:
match = command.compiled_regex.match(content)
if match:
command.execute(msg, match)
return False
def on_message_create(self, event):
if self.config.command_allow_edit:
self.last_message_cache[event.message.channel_id] = (event.message, False)
self.handle_message(event.message)
def on_message_update(self, event):
if self.config.command_allow_edit:
msg = self.last_message_cache.get(event.message.channel_id)
if msg and event.message.id == msg[0].id:
triggered = msg[1]
if not triggered:
triggered = self.handle_message(event.message)
self.last_message_cache[event.message.channel_id] = (event.message, triggered)
def add_plugin(self, cls):
if cls.__name__ in self.plugins:
raise Exception('Cannot add already added plugin: {}'.format(cls.__name__))
self.plugins[cls.__name__] = cls(self)
self.plugins[cls.__name__].load()
self.compute_command_matches_re()
def rmv_plugin(self, cls):
if cls.__name__ not in self.plugins:
raise Exception('Cannot remove non-existant plugin: {}'.format(cls.__name__))
self.plugins[cls.__name__].unload()
self.plugins[cls.__name__].destroy()
del self.plugins[cls.__name__]
self.compute_command_matches_re()
def run_forever(self):
self.client.run_forever()