class Mee6(discord.Client): """A modified discord.Client class This mod dispatched most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') if hasattr(self, 'shard_id'): msg = 'Chat Shard {}/{} restarted'.format(self.shard_id, self.shard_count) else: msg = 'Mee6 Chat restarted' self.stats.event(msg, 'Server count: {}'.format(len(self.servers))) await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message(message.channel, "shard {}/{}".format(self.shard_id+1, self.shard_count)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_server_role_create(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_create(server, role)) async def on_server_role_delete(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_delete(server, role)) async def on_server_role_update(self, before, after): server = None for s in self.servers: if after.id in map(lambda r:r.id, s.roles): server = s break if server is None: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_update(before, after)) async def on_voice_state_update(self, before, after): if after is None: server = before.server elif before is None: server = after.server else: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_voice_state_update(before, after)) async def on_member_ban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_ban(member)) async def on_member_unban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_unban(member)) async def on_typing(self, channel, user, when): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_typing(channel, user, when))
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) def run(self, *args): self.loop.run_until_complete(self.start(*args)) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') if hasattr(self, 'shard_id'): msg = 'Chat Shard {}/{} restarted'.format(self.shard_id, self.shard_count) else: msg = 'Mee6 Chat restarted' self.stats.event(msg, 'Server count: {}'.format(len(self.servers))) await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id + 1, self.shard_count)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_server_role_create(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_create(server, role)) async def on_server_role_delete(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_delete(server, role)) async def on_server_role_update(self, before, after): server = None for s in self.servers: if after.id in map(lambda r: r.id, s.roles): server = s break if server is None: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_update(before, after)) async def on_voice_state_update(self, before, after): if after is None and before is None: return elif after is None: server = before.server elif before is None: server = after.server else: server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_voice_state_update(before, after)) async def on_member_ban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_ban(member)) async def on_member_unban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_unban(member)) async def on_typing(self, channel, user, when): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_typing(channel, user, when))
class Mee6(discord.Client): def __init__(self, *args, **kwargs): discord.Client.__init__(self, *args, **kwargs) self.redis_url = kwargs.get('redis_url') self.db = Db(self.redis_url) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] async def on_ready(self): with open('welcome_ascii.txt') as f: print(f.read()) self.add_all_servers() discord.utils.create_task(self.heartbeat(5), loop=self.loop) discord.utils.create_task(self.update_stats(60), loop=self.loop) await self.change_status(game=discord.Game(name='http://mee6.xyz')) def add_all_servers(self): log.debug('Syncing servers and db') self.db.redis.delete('servers') for server in self.servers: log.debug('Adding server {}\'s id to db'.format(server.id)) self.db.redis.sadd('servers', server.id) @asyncio.coroutine def send_message(self, *args, **kwargs): dest = args[0] if hasattr(args[0], 'server'): dest = args[0].server if isinstance(args[0], discord.Member): dest = args[0] log.info('Mee6@{} >> {}'.format(dest.name, args[1].replace('\n', '~'))) yield from super().send_message(*args, **kwargs) @asyncio.coroutine def on_server_join(self, server): log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) self.db.redis.sadd('servers', server.id) self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: self.db.redis.set('server:{}:icon'.format(server.id), server.icon) @asyncio.coroutine def on_server_remove(self, server): log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) self.db.redis.srem('servers', server.id) @asyncio.coroutine def heartbeat(self, interval): while self.is_logged_in: self.db.redis.set('heartbeat', 1, ex=interval) yield from asyncio.sleep(0.9 * interval) @asyncio.coroutine def update_stats(self, interval): while self.is_logged_in: # Total members and online members members = list(self.get_all_members()) online_members = filter( lambda m: m.status is discord.Status.online, members) online_members = list(online_members) self.db.redis.set('mee6:stats:online_members', len(online_members)) self.db.redis.set('mee6:stats:members', len(members)) # Last messages for index, timestamp in enumerate(self.last_messages): if timestamp + interval < time(): self.last_messages.pop(index) self.db.redis.set('mee6:stats:last_messages', len(self.last_messages)) yield from asyncio.sleep(interval) @asyncio.coroutine def _run_plugin_event(self, plugin, event, *args, **kwargs): # A modified coro that is based on Client._run_event try: yield from getattr(plugin, event)(*args, **kwargs) except asyncio.CancelledError: pass except Exception: try: yield from self.on_error(event, *args, **kwargs) except asyncio.CancelledError: pass async def on_message(self, message): mee6_server_id = "159962941502783488" update_channel_id = "160784396679380992" if not hasattr(message, 'server'): return if (message.server.id, message.channel.id) == (mee6_server_id, update_channel_id): owners = set(server.owner for server in self.servers) for owner in owners: await self.send_message(owner, message.content) def dispatch(self, event, *args, **kwargs): # A list of events that are available from the plugins plugin_events = ('message', 'message_delete', 'message_edit', 'channel_delete', 'channel_create', 'channel_update', 'member_join', 'member_update', 'server_update', 'server_role_create', 'server_role_delete', 'server_role_update', 'voice_state_update', 'member_ban', 'member_unban', 'typing') log.debug('Dispatching event {}'.format(event)) method = 'on_' + event handler = 'handle_' + event # Total number of messages stats update if event == 'message': self.db.redis.incr('mee6:stats:messages') self.last_messages.append(time()) if hasattr(self, method): discord.utils.create_task(self._run_event(method, *args,\ **kwargs), loop=self.loop) if hasattr(self, handler): getattr(self, handler)(*args, **kwargs) if event in plugin_events: server_context = find_server(*args, **kwargs) if server_context is None: return # For each plugin that the server has enabled enabled_plugins = self.plugin_manager.get_all(server_context) for plugin in enabled_plugins: if hasattr(plugin, method): discord.utils.create_task(self._run_plugin_event(\ plugin, method, *args, **kwargs), loop=self.loop) else: if hasattr(self, method): discord.utils.create_task(self._run_event(method, *args,\ **kwargs), loop=self.loop) def run(self, token): self.token = token self.headers['authorization'] = token self._is_logged_in.set() try: self.loop.run_until_complete(self.connect()) except KeyboardInterrupt: self.loop.run_until_complete(self.logout()) pending = asyncio.Task.all_tasks() gathered = asyncio.gather(*pending) try: gathered.cancel() self.loop.run_forever() gathered.exception() except: pass finally: self.loop.close()
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) def run(self, *args): self.loop.run_until_complete(self.start(*args)) async def ping(self): PING_INTERVAL = 3 key = 'mee6.gateway.{}-{}'.format(self.shard_id, self.shard_count) while True: if self.is_logged_in: self.stats.check(key, 'OK') await self.db.redis.setex(key, PING_INTERVAL + 2, '1') else: self.stats.check(key, 'Critical') await asyncio.sleep(PING_INTERVAL) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) self.loop.create_task(self.ping()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set( 'server:{}:name'.format(server.id), server.name ) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format( server.owner.name, server.name )) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format( server.owner.name, server.name )) log.debug('Removing server {}\'s id from the db'.format( server.id )) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id+1, self.shard_count) ) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after))
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) self.voice_sessions_ids = dict() if self.shard_id is not None: self.shard = [self.shard_id, self.shard_count] else: self.shard = [0, 1] def run(self, *args): console_coro = self.loop.create_server(make_console(self), '127.0.0.1', 8000) self.loop.run_until_complete(console_coro) self.loop.run_until_complete(self.start(*args)) async def console(reader, writer): loop = asyncio.get_event_loop() data = await reader.read(100) message = data.decode() result = eval(message) writer.write(result) await writer.drain() writer.close() def send_monitoring_message(self, msg): self.loop.create_task(self._send_monitoring_message(msg)) async def _send_monitoring_message(self, msg): url = os.getenv('MONITORING_WH') if not url: return headers = {} headers['Content-Type'] = 'application/json' data = json.dumps({'content': msg}) async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=data) as d: pass async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return wh_key = 'channel.{}.last_message_whid'.format(message.channel.id) if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id, self.shard_count)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after))
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) def run(self, *args): self.loop.run_until_complete(self.start(*args)) async def ping(self): PING_INTERVAL = 3 key = 'mee6.gateway.{}-{}'.format(self.shard_id, self.shard_count) while True: if self.is_logged_in: self.stats.check(key, 'OK') await self.db.redis.setex(key, PING_INTERVAL + 2, '1') else: self.stats.check(key, 'Critical') await asyncio.sleep(PING_INTERVAL) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) self.loop.create_task(self.ping()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set( 'server:{}:name'.format(server.id), server.name ) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format( server.owner.name, server.name )) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format( server.owner.name, server.name )) log.debug('Removing server {}\'s id from the db'.format( server.id )) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id, self.shard_count) ) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after))
class ChatBot(discord.Client): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.__name__ = APP_NAME self.__version__ = APP_VERSION self.__author__ = APP_AUTHOR self.__copyright__ = "Copyright (c){} {}".format( '2016-2020', self.__author__) def run(self, *args): self.loop.run_until_complete(self.start(*args)) async def on_ready(self): for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, channel, *args, **kwargs): return await channel.send(*args, **kwargs) async def on_message(self, message): if isinstance(message.channel, discord.abc.PrivateChannel): return server = message.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if isinstance(before.channel, discord.abc.PrivateChannel): return server = after.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if isinstance(message.channel, discord.abc.PrivateChannel): return server = message.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if isinstance(channel, discord.abc.PrivateChannel): return server = channel.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if isinstance(before, discord.abc.PrivateChannel): return server = after.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if isinstance(channel, discord.abc.PrivateChannel): return server = channel.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_server_role_create(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_create(server, role)) async def on_server_role_delete(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_delete(server, role)) async def on_server_role_update(self, before, after): server = None for s in self.guilds: if after.id in map(lambda r: r.id, s.roles): server = s break if server is None: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_update(before, after)) async def on_voice_state_update(self, before, after): if after is None and before is None: return elif after is None: server = before.guild elif before is None: server = after.guild else: server = after.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_voice_state_update(before, after)) async def on_member_ban(self, member): server = member.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_ban(member)) async def on_member_unban(self, member): server = member.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_unban(member)) async def on_typing(self, channel, user, when): if isinstance(channel, discord.abc.PrivateChannel): return server = channel.guild enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_typing(channel, user, when))
class Mee6(discord.Client): def __init__(self, *args, **kwargs): discord.Client.__init__(self, *args, **kwargs) self.redis_url = kwargs.get('redis_url') self.db = Db(self.redis_url) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] async def on_ready(self): with open('welcome_ascii.txt') as f: print(f.read()) self.add_all_servers() discord.utils.create_task(self.heartbeat(5), loop=self.loop) discord.utils.create_task(self.update_stats(60), loop=self.loop) await self.change_status(game=discord.Game(name='http://mee6.xyz')) def add_all_servers(self): log.debug('Syncing servers and db') self.db.redis.delete('servers') for server in self.servers: log.debug('Adding server {}\'s id to db'.format(server.id)) self.db.redis.sadd('servers', server.id) @asyncio.coroutine def send_message(self, *args, **kwargs): dest = args[0] if hasattr(args[0], 'server'): dest = args[0].server if isinstance(args[0], discord.Member): dest = args[0] log.info('Mee6@{} >> {}'.format(dest.name,args[1].replace('\n', '~'))) yield from super().send_message(*args, **kwargs) @asyncio.coroutine def on_server_join(self, server): log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) self.db.redis.sadd('servers', server.id) self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: self.db.redis.set('server:{}:icon'.format(server.id), server.icon) @asyncio.coroutine def on_server_remove(self, server): log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) self.db.redis.srem('servers', server.id) @asyncio.coroutine def heartbeat(self, interval): while self.is_logged_in: self.db.redis.set('heartbeat', 1, ex=interval) yield from asyncio.sleep(0.9 * interval) @asyncio.coroutine def update_stats(self, interval): while self.is_logged_in: # Total members and online members members = list(self.get_all_members()) online_members = filter(lambda m: m.status is discord.Status.online, members) online_members = list(online_members) self.db.redis.set('mee6:stats:online_members', len(online_members)) self.db.redis.set('mee6:stats:members', len(members)) # Last messages for index, timestamp in enumerate(self.last_messages): if timestamp + interval < time(): self.last_messages.pop(index) self.db.redis.set('mee6:stats:last_messages', len(self.last_messages)) yield from asyncio.sleep(interval) @asyncio.coroutine def _run_plugin_event(self, plugin, event, *args, **kwargs): # A modified coro that is based on Client._run_event try: yield from getattr(plugin, event)(*args, **kwargs) except asyncio.CancelledError: pass except Exception: try: yield from self.on_error(event, *args, **kwargs) except asyncio.CancelledError: pass async def on_message(self, message): mee6_server_id = "159962941502783488" update_channel_id = "160784396679380992" if not hasattr(message, 'server'): return if (message.server.id, message.channel.id) == (mee6_server_id, update_channel_id): owners = set(server.owner for server in self.servers) for owner in owners: await self.send_message( owner, message.content ) def dispatch(self, event, *args, **kwargs): # A list of events that are available from the plugins plugin_events = ( 'message', 'message_delete', 'message_edit', 'channel_delete', 'channel_create', 'channel_update', 'member_join', 'member_update', 'server_update', 'server_role_create', 'server_role_delete', 'server_role_update', 'voice_state_update', 'member_ban', 'member_unban', 'typing' ) log.debug('Dispatching event {}'.format(event)) method = 'on_' + event handler = 'handle_' + event # Total number of messages stats update if event=='message': self.db.redis.incr('mee6:stats:messages') self.last_messages.append(time()) if hasattr(self, method): discord.utils.create_task(self._run_event(method, *args,\ **kwargs), loop=self.loop) if hasattr(self, handler): getattr(self, handler)(*args, **kwargs) if event in plugin_events: server_context = find_server(*args, **kwargs) if server_context is None: return # For each plugin that the server has enabled enabled_plugins = self.plugin_manager.get_all(server_context) for plugin in enabled_plugins: if hasattr(plugin, method): discord.utils.create_task(self._run_plugin_event(\ plugin, method, *args, **kwargs), loop=self.loop) else: if hasattr(self, method): discord.utils.create_task(self._run_event(method, *args,\ **kwargs), loop=self.loop) def run(self, token): self.token = token self.headers['authorization'] = token self._is_logged_in.set() try: self.loop.run_until_complete(self.connect()) except KeyboardInterrupt: self.loop.run_until_complete(self.logout()) pending = asyncio.Task.all_tasks() gathered = asyncio.gather(*pending) try: gathered.cancel() self.loop.run_forever() gathered.exception() except: pass finally: self.loop.close()
class Mee6(discord.Client): """A modified discord.Client class This mod dispatched most events to the different plugins. """ def __init__(self, *args, **kwargs): discord.Client.__init__(self, *args, **kwargs) self.redis_url = kwargs.get('redis_url') self.db = Db(self.redis_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] async def on_ready(self): """Called when the bot is ready. Launched heartbeat, update_stats cron jobs Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() discord.utils.create_task(self.heartbeat(5), loop=self.loop) for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') await self.db.redis.delete('servers') for server in self.servers: log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): """Called when joining a new server Adds the server to the db. Also adds its name and it's icon if it has one. """ log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def heartbeat(self, interval): """Sends a heartbeat to the db every interval seconds""" while self.is_logged_in: await self.db.redis.set('heartbeat', 1, expire=interval) await asyncio.sleep(0.9 * interval) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): counter = 0 msg = None while counter!=3: try: msg = await super().send_message(*args, **kwargs) counter=2 except discord.errors.HTTPException as e: if e.response.status==502: log.info('502 HTTP Exception, retrying...') else: log.info('{} HTTP Exception.'.format( e.response.status )) counter=2 counter+=1 return msg async def on_message(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_server_role_create(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_create(server, role)) async def on_server_role_delete(self, server, role): enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_delete(server, role)) async def on_server_role_update(self, before, after): server = None for s in self.servers: if after.id in map(lambda r:r.id, s.roles): server = s break if server is None: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_role_update(before, after)) async def on_voice_state_update(self, before, after): if after is None: server = before.server elif before is None: server = after.server else: return enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_voice_state_update(before, after)) async def on_member_ban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_ban(member)) async def on_member_unban(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_unban(member)) async def on_typing(self, channel, user, when): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_typing(channel, user, when))
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) self.voice_sessions_ids = dict() if self.shard_id is not None: self.shard = [self.shard_id, self.shard_count] else: self.shard = [0, 1] def run(self, *args): console_coro = self.loop.create_server(make_console(self), '127.0.0.1', 8000) self.loop.run_until_complete(console_coro) self.loop.create_task(self.connect_schwifty()) self.loop.run_until_complete(self.start(*args)) async def connect_schwifty(self): self.schwifty = await SchwiftyWebsocket.create(self.shard, self) while not self.is_closed: try: await self.schwifty.poll_event() except (ConnectionClosed, asyncio.TimeoutError) as e: await asyncio.sleep(1) self.schwifty = await SchwiftyWebsocket.create( self.shard, self) async def console(reader, writer): loop = asyncio.get_event_loop() data = await reader.read(100) message = data.decode() result = eval(message) writer.write(result) await writer.drain() writer.close() def send_monitoring_message(self, msg): self.loop.create_task(self._send_monitoring_message(msg)) async def _send_monitoring_message(self, msg): url = os.getenv('MONITORING_WH') if not url: return headers = {} headers['Content-Type'] = 'application/json' data = json.dumps({'content': msg}) async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=data) as d: pass async def on_socket_raw_receive(self, payload): tags = {'op': str(payload['op']), 't': payload.get('t') or "NONE"} self.stats.incr('discord.event', tags=tags) if not payload['op'] == 0: return if payload['t'] == 'VOICE_STATE_UPDATE': d = payload['d'] if str(d['user_id']) != self.user.id: return guild_id = d['guild_id'] self.voice_sessions_ids[guild_id] = d['session_id'] if payload['t'] == 'VOICE_SERVER_UPDATE': d = payload['d'] guild_id = d['guild_id'] d['session_id'] = self.voice_sessions_ids.get(guild_id) if d.get('endpoint'): await self.schwifty.voice_update(d) if payload['t'] == 'READY': if not hasattr(self, 'shard_id'): return msg = "**[READY]** shard {}/{}".format(self.shard_id, self.shard_count) self.send_monitoring_message(msg) if payload['t'] == 'RESUMED': if not hasattr(self, 'shard_id'): return msg = "**[RESUMED]** shard {}/{}".format(self.shard_id, self.shard_count) self.send_monitoring_message(msg) async def dispatch_schwifty_event(self, t, d): listener_name = 'on_schwifty_' + t.lower() listener = getattr(self, listener_name, None) if listener: await listener(**d) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return wh_key = 'channel.{}.last_message_whid'.format(message.channel.id) if message.webhook_id: self.db.redis.set(wh_key, message.webhook_id) else: self.db.redis.delete(wh_key) if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id, self.shard_count)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_schwifty_playing(self, guild_id, url): server = discord.Object(id=str(guild_id)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_schwifty_playing(guild_id, url)) async def on_schwifty_finished_playing(self, guild_id): server = discord.Object(id=str(guild_id)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task( plugin.on_schwifty_finished_playing(guild_id))
class Mee6(discord.Client): '''A modified discord.Client class This mod dispatches most events to the different plugins. ''' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) self.voice_sessions_ids = dict() if self.shard_id is not None: self.shard = [self.shard_id, self.shard_count] else: self.shard = [0, 1] def run(self, *args): console_coro = self.loop.create_server(make_console(self), '127.0.0.1', 8000) self.loop.run_until_complete(console_coro) # These are related to music player I think. Disabled currently since I couldn't get it working properly. #self.loop.create_task(self.connect_schwifty()) self.loop.run_until_complete(self.start(*args)) # These are related to music player I think. Disabled currently since I couldn't get it working properly. # async def connect_schwifty(self): # self.schwifty = await SchwiftyWebsocket.create( # self.shard, # self # ) # # while not self.is_closed: # try: # await self.schwifty.poll_event() # except (ConnectionClosed, asyncio.TimeoutError) as e: # await asyncio.sleep(1) # self.schwifty = await SchwiftyWebsocket.create( # self.shard, # self # ) async def console(reader, writer): loop = asyncio.get_event_loop() data = await reader.read(100) message = data.decode() result = eval(message) writer.write(result) await writer.drain() writer.close() #These two functions log the bots status to some discord servers webhook. TODO need to adjust that. def send_monitoring_message(self, msg): self.loop.create_task(self._send_monitoring_message(msg)) async def _send_monitoring_message(self, msg): url = os.getenv('MONITORING_WH') if not url: return headers = {} headers['Content-Type'] = 'application/json' data = json.dumps({'content': msg}) async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=data) as d: pass async def on_voice_state_update(self, member): #TODO stats? if str(member.id) != self.user.id: return guild_id = member.guild_id self.voice_sessions_ids[guild_id] = member.server.id #TODO This function's parameters have been changed on the new discord.py version. It is no longer sent as parsed. # async def on_socket_raw_receive(self, payload): # tags = {'op': str(payload['op']), # 't': payload.get('t') or "NONE"} # self.stats.incr('discord.event', tags=tags) # # if not payload['op'] == 0: # return # # # if payload['t'] == 'VOICE_SERVER_UPDATE': # d = payload['d'] # guild_id = d['guild_id'] # d['session_id'] = self.voice_sessions_ids.get(guild_id) # if d.get('endpoint'): # await self.schwifty.voice_update(d) # # if payload['t'] == 'READY': # if not hasattr(self, 'shard_id'): # return # # msg = "**[READY]** shard {}/{}".format( # self.shard_id, # self.shard_count # ) # self.send_monitoring_message(msg) # # if payload['t'] == 'RESUMED': # if not hasattr(self, 'shard_id'): # return # # msg = "**[RESUMED]** shard {}/{}".format(self.shard_id, # self.shard_count) # self.send_monitoring_message(msg) async def dispatch_schwifty_event(self, t, d): listener_name = 'on_schwifty_' + t.lower() listener = getattr(self, listener_name, None) if listener: await listener(**d) async def on_ready(self): ''' Called when the bot is ready.Connects to the database Dispatched all the ready events ''' log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): ''' Syncing all the servers to the DB ''' log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_join(self, server): ''' Called when joining a new server ''' self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format(server.owner.name, server.name)) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set('server:{}:icon'.format(server.id), server.icon) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): ''' Called when leaving or kicked from a server Removes the server from the db. ''' log.info('Leaving {} server : {} !'.format(server.owner.name, server.name)) log.debug('Removing server {}\'s id from the db'.format(server.id)) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return #Not sure about this discord.py docs doesn't list this among the variables passed with new messages so commented out for now. #This probably changed recently since webhook messages have a seperate event on the discord.py #wh_key = 'channel.{}.last_message_whid'.format(message.channel.id) #log.info(message) #if message.webhook_id: # self.db.redis.set(wh_key, message.webhook_id) #else: # self.db.redis.delete(wh_key) if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id, self.shard_count)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after))
class RickBot(discord.Client): def __init__(self, *args, **kwargs): self.redis_url = kwargs.get('redis_url') self.db = Db(self.redis_url) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] async def on_ready(self): with open('welcome_ascii.txt') as f: print(f.read()) self.add_all_servers() discord.utils.create_task(self.heartbeat(5), loop=self.loop) discord.utils.create_task(self.update_stats(60), loop=self.loop) async def add_all_servers(self): log.debug('Syncing servers and DB') self.db.redis.delete('servers') for server in self.servers: log.debug('Adding server {}\'s ID to DB'.format(server.id)) self.db.redis.sadd('servers', server.id) async def send_message(self, *args, **kwargs): log.info('RickBot >> {}'.format(args[1].replace('\n', '~'))) await super().send_message(*args, **kwargs) async def on_server_join(self, server): log.info('Joined {} server: {}!'.format(server.owner.name, server.name)) log.debug('Adding self {}\'s ID to DB'.format(server.id)) self.db.redis.sadd('servers', server.id) self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: self.db.redis.set('server:{}:icon'.format(server.id), server.icon) async def on_server_remove(self, server): log.info('Leaving {} server: {}'.format(server.owner.name, sever.name)) log.debug('Removing server {}\'s from DB'.format(server.id)) self.db.redis.srem('servers', server.id) async def heartbeat(self, interval): while self.is_logged_in: self.db.redis.set('heartbeat', 1, ex=interval) await asyncio.sleep(0.9 * interval) async def update_stats(self, interval): while self.is_logged_in: # Total members and online members members = list(self.get_all_members()) online_members = filter(lambda m: m.status is discord.Status.online, members) online_members = list(online_members) self.db.redis.set('rickbot:stats:online_members', len(online_members)) self.db.redis.set('rickbot:stats:members', len(members)) # Last messages for index, timestamp in enumerate(self.last_messages): if timestamp + interval < time(): self.last_messages.pop(index) self.db.redis.set('rickbot:stats:last_messages', len(self.last_messages)) await asyncio.sleep(interval) async def _run_plugin_event(self, plugin, event, *args, **kwargs): # A yummy modified coroutine that is based on Client._run_event try: await getattr(plugin, event)(*args, **kwargs) except asyncio.CancelledError: pass except Exception: try: await self.on_error(event, *args, **kwargs) except asyncio.CancelledError: pass def dispatch(self, event, *args, **kwargs): # A list of events that are avalible from the plugins. plugin_events = ( 'message', 'message_delete', 'message_edit', 'channel_delete', 'channel_create', 'channel_update', 'member_join', 'member_update', 'server_update', 'server_role_create', 'server_role_delete', 'server_role_update', 'voice_state_update', 'member_ban', 'member_unban', 'typing' ) # Total number of messages stats update if event == 'message': self.db.redis.incr('rickbot:stats:messages') self.last_messages.append(time()) log.debug('Dispatching event {}'.format(event)) method = 'on_' + event handler = 'handle_' + event if hasattr(self, handler): getattr(self, handler)(*args, **kwargs) if event in plugin_events: server_context = find_server(*args, **kwargs) if server_context is None: return # For each plugin that the server has enabled for plugin in enabled_plugins: if hasattr(plugin, method): discord.utils.create_task(self._run_plugin_event(\ plugin, method, *args, **kwargs), loop=self.loop) else: if hasattr(self, method): discord.utils.channel_create(self._run_event(method, *args, \ **kwargs), loop=self.loop) def run(self, token): self.token = token self.headers['authorization'] = token self._is_logged_in.set() try: self.loop.run_until_complete(self.connect()) except KeyboardInterrupt: self.loop.run_until_complete(self.logout()) pending = async.Task.all_tasks() gathered = asyncio.gather(*pending) try: gathered.cancel() self.loop.run_forever() gathered.exception() except: pass finally: self.loop.close()
class Mee6(discord.Client): """A modified discord.Client class This mod dispatches most events to the different plugins. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.redis_url = kwargs.get('redis_url') self.mongo_url = kwargs.get('mongo_url') self.dd_agent_url = kwargs.get('dd_agent_url') self.sentry_dsn = kwargs.get('sentry_dsn') self.db = Db(self.redis_url, self.mongo_url, self.loop) self.plugin_manager = PluginManager(self) self.plugin_manager.load_all() self.last_messages = [] self.stats = DDAgent(self.dd_agent_url) self.voice_sessions_ids = dict() if self.shard_id is not None: self.shard = [self.shard_id, self.shard_count] else: self.shard = [0, 1] def run(self, *args): console_coro = self.loop.create_server(make_console(self), '127.0.0.1', 8000) self.loop.run_until_complete(console_coro) self.loop.create_task(self.connect_schwifty()) self.loop.run_until_complete(self.start(*args)) async def connect_schwifty(self): self.schwifty = await SchwiftyWebsocket.create( self.shard, self ) while not self.is_closed: try: await self.schwifty.poll_event() except (ConnectionClosed, asyncio.TimeoutError) as e: await asyncio.sleep(1) self.schwifty = await SchwiftyWebsocket.create( self.shard, self ) async def console(reader, writer): loop = asyncio.get_event_loop() data = await reader.read(100) message = data.decode() result = eval(message) writer.write(result) await writer.drain() writer.close() def send_monitoring_message(self, msg): self.loop.create_task(self._send_monitoring_message(msg)) async def _send_monitoring_message(self, msg): url = os.getenv('MONITORING_WH') if not url: return headers = {} headers['Content-Type'] = 'application/json' data = json.dumps({'content': msg}) async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=data) as d: pass async def on_socket_raw_receive(self, payload): tags = {'op': str(payload['op']), 't': payload.get('t') or "NONE"} self.stats.incr('discord.event', tags=tags) if not payload['op'] == 0: return if payload['t'] == 'VOICE_STATE_UPDATE': d = payload['d'] if str(d['user_id']) != self.user.id: return guild_id = d['guild_id'] self.voice_sessions_ids[guild_id] = d['session_id'] if payload['t'] == 'VOICE_SERVER_UPDATE': d = payload['d'] guild_id = d['guild_id'] d['session_id'] = self.voice_sessions_ids.get(guild_id) if d.get('endpoint'): await self.schwifty.voice_update(d) if payload['t'] == 'READY': if not hasattr(self, 'shard_id'): return msg = "**[READY]** shard {}/{}".format( self.shard_id, self.shard_count ) self.send_monitoring_message(msg) if payload['t'] == 'RESUMED': if not hasattr(self, 'shard_id'): return msg = "**[RESUMED]** shard {}/{}".format(self.shard_id, self.shard_count) self.send_monitoring_message(msg) async def dispatch_schwifty_event(self, t, d): listener_name = 'on_schwifty_' + t.lower() listener = getattr(self, listener_name, None) if listener: await listener(**d) async def on_ready(self): """Called when the bot is ready. Connects to the database Dispatched all the ready events """ log.info('Connected to the database') await self.add_all_servers() for plugin in self.plugins: self.loop.create_task(plugin.on_ready()) async def add_all_servers(self): """Syncing all the servers to the DB""" log.debug('Syncing servers and db') for server in self.servers: self.stats.set('mee6.servers', server.id) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.sadd('servers', server.id) if server.name: await self.db.redis.set( 'server:{}:name'.format(server.id), server.name ) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) async def on_server_join(self, server): """Called when joining a new server""" self.stats.set('mee6.servers', server.id) self.stats.incr('mee6.server_join') await self.db.redis.sadd('servers', server.id) log.info('Joined {} server : {} !'.format( server.owner.name, server.name )) log.debug('Adding server {}\'s id to db'.format(server.id)) await self.db.redis.set('server:{}:name'.format(server.id), server.name) if server.icon: await self.db.redis.set( 'server:{}:icon'.format(server.id), server.icon ) # Dispatching to global plugins for plugin in self.plugins: if plugin.is_global: self.loop.create_task(plugin.on_server_join(server)) async def on_server_remove(self, server): """Called when leaving or kicked from a server Removes the server from the db. """ log.info('Leaving {} server : {} !'.format( server.owner.name, server.name )) log.debug('Removing server {}\'s id from the db'.format( server.id )) await self.db.redis.srem('servers', server.id) async def get_plugins(self, server): plugins = await self.plugin_manager.get_all(server) return plugins async def send_message(self, *args, **kwargs): self.stats.incr('mee6.sent_messages') return await super().send_message(*args, **kwargs) async def on_message(self, message): self.stats.incr('mee6.recv_messages') if message.channel.is_private: return wh_key = 'channel.{}.last_message_whid'.format(message.channel.id) if message.webhook_id: self.db.redis.set(wh_key, message.webhook_id) else: self.db.redis.delete(wh_key) if message.author.__class__ != discord.Member: return server = message.server if message.content == "!shard?": if hasattr(self, 'shard_id'): await self.send_message( message.channel, "shard {}/{}".format(self.shard_id, self.shard_count) ) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin._on_message(message)) async def on_message_edit(self, before, after): if before.channel.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_edit(before, after)) async def on_message_delete(self, message): if message.channel.is_private: return server = message.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_message_delete(message)) async def on_channel_create(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_create(channel)) async def on_channel_update(self, before, after): if before.is_private: return server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_update(before, after)) async def on_channel_delete(self, channel): if channel.is_private: return server = channel.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_channel_delete(channel)) async def on_member_join(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_join(member)) async def on_member_remove(self, member): server = member.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_remove(member)) async def on_member_update(self, before, after): server = after.server enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_member_update(before, after)) async def on_server_update(self, before, after): server = after enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_server_update(before, after)) async def on_schwifty_playing(self, guild_id, url): server = discord.Object(id=str(guild_id)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_schwifty_playing(guild_id, url)) async def on_schwifty_finished_playing(self, guild_id): server = discord.Object(id=str(guild_id)) enabled_plugins = await self.get_plugins(server) for plugin in enabled_plugins: self.loop.create_task(plugin.on_schwifty_finished_playing(guild_id))