# Path: bot/plugins/base.py
# class MethodPool(dict):
# 
#     # Track which handlers come from which plugin
#     plugin_handlers = None
#     plugin_modules = None
# 
#     def __init__(self, *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.plugin_handlers = {}
#         self.plugin_modules = {}
# 
#     def register(self, plugin):
#         """
#         Take in the event handlers from a plugin and group them by event
#         """
#         for handler, method in plugin._callbacks.items():
#             wrapped = plugin._wrap(method)
#             self.add(handler, wrapped)
#             self.plugin_modules[plugin.__module__] = plugin
#             self.plugin_handlers[plugin] = wrapped
#             logger.debug('Registered %r from %r', method, plugin)
# 
#     def add(self, name, handler):
#         if name not in self:
#             self[name] = []
#         self[name].append(handler)
# 
#     def group(self, handlers):
#         """
#         Groups all handlers into one wrapping handler that distributes the event.
# 
#         This is where the 'magic' happens. A distinction is made between plugins
#         and/or handlers that perform blocking IO (such as the reddit API wrapper,
#         Django ORM, ...). Blocking handlers are executed in a loop executor (by
#         default a thread pool), while real coroutines are just executed as-is.
#         """
# 
#         async def grouped(*args, **kwargs):
#             coros = []
#             for handler in handlers:
#                 if handler._has_blocking_io:
#                     loop = self.client.loop
#                     future = loop.run_in_executor(None, functools.partial(handler, *args, **kwargs))
#                     coro = await future
#                     coros.append(coro)
#                 else:
#                     handler = handler(*args, **kwargs)  # real coroutine can be called
#                     coros.append(handler)
#             await asyncio.gather(*coros)
#         return grouped
# 
#     def bind_to(self, client):
#         """
#         Wraps all registered handlers in a function and binds it to the client.
#         """
#         self.client = client
#         client._method_pool = self
#         for event, handlers in self.items():
#             grouper = self.group(handlers)
#             grouper.__name__ = event
#             client.event(grouper)
# 
# Path: bot/plugins/events.py
# class EventPool:
# 
#     def register(self, plugin):
#         for event, handlers in plugin._event_handlers.items():
#             handlers = [partial(handler, plugin) for handler in handlers]
#             event.register(*handlers)


import logging
import discord
import django
from importlib import import_module
from django.conf import settings
from bot.plugins.base import MethodPool
from bot.plugins.events import EventPool
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Main entry point for the bot.

This module performs the start-up, login and reads out the settings to configure
the bot.
"""



logger = logging.getLogger('bot')

client = discord.Client()


@client.event
async def on_ready():
    logger.info('Logged in as %s, id: %s', client.user.name, client.user.id)


def main():
    django.setup()  # configures logging etc.
    logger.info('Starting up bot')


# Path: bot/plugins/base.py
# class MethodPool(dict):
# 
#     # Track which handlers come from which plugin
#     plugin_handlers = None
#     plugin_modules = None
# 
#     def __init__(self, *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.plugin_handlers = {}
#         self.plugin_modules = {}
# 
#     def register(self, plugin):
#         """
#         Take in the event handlers from a plugin and group them by event
#         """
#         for handler, method in plugin._callbacks.items():
#             wrapped = plugin._wrap(method)
#             self.add(handler, wrapped)
#             self.plugin_modules[plugin.__module__] = plugin
#             self.plugin_handlers[plugin] = wrapped
#             logger.debug('Registered %r from %r', method, plugin)
# 
#     def add(self, name, handler):
#         if name not in self:
#             self[name] = []
#         self[name].append(handler)
# 
#     def group(self, handlers):
#         """
#         Groups all handlers into one wrapping handler that distributes the event.
# 
#         This is where the 'magic' happens. A distinction is made between plugins
#         and/or handlers that perform blocking IO (such as the reddit API wrapper,
#         Django ORM, ...). Blocking handlers are executed in a loop executor (by
#         default a thread pool), while real coroutines are just executed as-is.
#         """
# 
#         async def grouped(*args, **kwargs):
#             coros = []
#             for handler in handlers:
#                 if handler._has_blocking_io:
#                     loop = self.client.loop
#                     future = loop.run_in_executor(None, functools.partial(handler, *args, **kwargs))
#                     coro = await future
#                     coros.append(coro)
#                 else:
#                     handler = handler(*args, **kwargs)  # real coroutine can be called
#                     coros.append(handler)
#             await asyncio.gather(*coros)
#         return grouped
# 
#     def bind_to(self, client):
#         """
#         Wraps all registered handlers in a function and binds it to the client.
#         """
#         self.client = client
#         client._method_pool = self
#         for event, handlers in self.items():
#             grouper = self.group(handlers)
#             grouper.__name__ = event
#             client.event(grouper)
# 
# Path: bot/plugins/events.py
# class EventPool:
# 
#     def register(self, plugin):
#         for event, handlers in plugin._event_handlers.items():
#             handlers = [partial(handler, plugin) for handler in handlers]
#             event.register(*handlers)


# Path: main.py
import logging
import discord
import django
from importlib import import_module
from django.conf import settings
from bot.plugins.base import MethodPool
from bot.plugins.events import EventPool

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Main entry point for the bot.

This module performs the start-up, login and reads out the settings to configure
the bot.
"""



logger = logging.getLogger('bot')

client = discord.Client()


@client.event
async def on_ready():
    logger.info('Logged in as %s, id: %s', client.user.name, client.user.id)


def main():
    django.setup()  # configures logging etc.
    logger.info('Starting up bot')


    pool = MethodPool()  # pool that holds all callbacks