# Path: bot/channels/models.py
# class Channel(models.Model):
#     discord_id = models.BigIntegerField(unique=True)
#     name = models.CharField(_('name'), max_length=50)
# 
#     allow_nsfw = models.BooleanField(default=False)
# 
#     objects = ChannelQuerySet.as_manager()
# 
#     def __str__(self):
#         return self.name
# 
# Path: bot/plugins/base.py
# class BasePlugin(metaclass=BasePluginMeta):
# 
#     has_blocking_io = False  # set to True to run events in an executor
#     commands = None
#     _callbacks = None
# 
#     def __init__(self, client, options):
#         self.client = client
#         self.options = options
# 
#     def _wrap(self, method):
#         handler = functools.partial(method, self)
#         handler.__name__ = method.__name__
#         handler._has_blocking_io = self.has_blocking_io
#         return handler
# 
#     def get_command(self, msg):
#         """
#         Get the command that matches with str:`msg`
#         """
#         for cmd, handler in self.commands.items():
#             if msg.lower().startswith(cmd.lower()):
# 
#                 # Simple command
#                 if handler._command.regex is None:
#                     # in this case, it must be the exact same command
#                     if msg.lower() != cmd.lower():
#                         continue
#                     command = commands.Command(handler._command)
#                     return handler, command
# 
#                 # Regex matching, cut of the command part
#                 str_to_test = msg[len(cmd):].strip()
#                 match = handler._command.regex.match(str_to_test)
#                 if not match:
#                     continue
# 
#                 command = commands.Command(handler._command, **match.groupdict())
#                 return handler, command
#         return None
# 
#     async def on_message(self, message):
#         result = self.get_command(message.content)
#         if result:
#             handler, command = result
#             command.for_message, command.client = message, self.client
#             stop = await command_resolved.dispatch(command=command, handler=handler)
#             if not stop:
#                 assert asyncio.iscoroutinefunction(handler)
#                 await handler(self, command)
# 
#     async def on_message_edit(self, before, after):
#         pass
# 
# Path: bot/plugins/commands.py
# class command(object):
# 
#     """
#     Decorator for command handlers in bot Plugins.
#     """
# 
#     def __init__(self, name=None, pattern=None, help=None):
#         assert not callable(name), 'You forgot the parentheses for the decorator'
# 
#         self.name = name
#         if isinstance(pattern, str):
#             pattern = re.compile(pattern)
#         self.regex = pattern
#         self.help = help
# 
#     def __call__(self, func):
#         """
#         Decorator
#         """
#         if self.name is None:
#             self.name = func.__name__.replace('_', ' ')
#         if self.help is None:
#             self.help = func.__doc__.strip().split('\n')[0] if func.__doc__ else None
#         func._command = self
#         return func
# 
#     def as_help(self):
#         cmd = "`{prefix}{name}{pattern}`".format(
#             prefix=PREFIX,
#             name=self.name,
#             pattern=' {}'.format(self.regex.pattern) if self.regex else ''
#         )
#         return "{cmd}{spacer}{help}".format(cmd=cmd, help=self.help or '', spacer=' - ' if self.help else '')
# 
# Path: bot/users/models.py
# class Member(models.Model):
#     discord_id = models.CharField(max_length=50, unique=True)
#     name = models.CharField(_('name'), max_length=255)
#     last_seen = models.DateTimeField(null=True, blank=True)
# 
#     is_bot = models.BooleanField(default=False)
#     can_admin_bot = models.BooleanField(default=False)
# 
#     objects = MemberQuerySet.as_manager()
# 
#     def __str__(self):
#         return '<@{} name={}>'.format(self.discord_id, self.name)
# 
# Path: bot/plugins/stats/models.py
# class LoggedMessage(models.Model):
# 
#     discord_id = models.BigIntegerField(unique=True)
#     server = models.BigIntegerField(_("server"))
# 
#     member = models.ForeignKey('users.Member', related_name='messages_authored', on_delete=models.PROTECT)
#     member_username = models.CharField(max_length=255)  # this can change, only the member.discord_id is a constant
# 
#     channel = models.ForeignKey('channels.Channel', on_delete=models.PROTECT)
# 
#     content = models.TextField()
#     num_lines = models.PositiveSmallIntegerField(default=1)
#     timestamp = models.DateTimeField(auto_now_add=True)
#     edited_timestamp = models.DateTimeField(null=True, blank=True)
# 
#     mentions = models.ManyToManyField('users.Member', related_name='messages_mentioned_in', blank=True)
# 
#     class Meta:
#         verbose_name = _('message')
#         verbose_name_plural = _('messages')
#         ordering = ['-timestamp']
# 
#     def __str__(self):
#         return self.discord_id


import logging
import re
from discord.channel import TextChannel
from discord.enums import Status
from django.db.models import Count, Q
from django.utils.timesince import timesince
from django.utils.timezone import make_aware, now, utc
from import_export.admin import DEFAULT_FORMATS
from tabulate import tabulate
from bot.channels.models import Channel
from bot.plugins.base import BasePlugin
from bot.plugins.commands import command
from bot.users.models import Member
from .models import LoggedMessage




logger = logging.getLogger(__name__)


EXPORT_FORMATS = {f().get_title(): f for f in DEFAULT_FORMATS if f().can_export()}


class Plugin(BasePlugin):

    has_blocking_io = True

    async def on_message(self, message):
        """
        Log the message in the db
        """
        await super().on_message(message)

        if not isinstance(message.channel, TextChannel):
            return

        member = Member.objects.from_message(message)

# Path: bot/channels/models.py
# class Channel(models.Model):
#     discord_id = models.BigIntegerField(unique=True)
#     name = models.CharField(_('name'), max_length=50)
# 
#     allow_nsfw = models.BooleanField(default=False)
# 
#     objects = ChannelQuerySet.as_manager()
# 
#     def __str__(self):
#         return self.name
# 
# Path: bot/plugins/base.py
# class BasePlugin(metaclass=BasePluginMeta):
# 
#     has_blocking_io = False  # set to True to run events in an executor
#     commands = None
#     _callbacks = None
# 
#     def __init__(self, client, options):
#         self.client = client
#         self.options = options
# 
#     def _wrap(self, method):
#         handler = functools.partial(method, self)
#         handler.__name__ = method.__name__
#         handler._has_blocking_io = self.has_blocking_io
#         return handler
# 
#     def get_command(self, msg):
#         """
#         Get the command that matches with str:`msg`
#         """
#         for cmd, handler in self.commands.items():
#             if msg.lower().startswith(cmd.lower()):
# 
#                 # Simple command
#                 if handler._command.regex is None:
#                     # in this case, it must be the exact same command
#                     if msg.lower() != cmd.lower():
#                         continue
#                     command = commands.Command(handler._command)
#                     return handler, command
# 
#                 # Regex matching, cut of the command part
#                 str_to_test = msg[len(cmd):].strip()
#                 match = handler._command.regex.match(str_to_test)
#                 if not match:
#                     continue
# 
#                 command = commands.Command(handler._command, **match.groupdict())
#                 return handler, command
#         return None
# 
#     async def on_message(self, message):
#         result = self.get_command(message.content)
#         if result:
#             handler, command = result
#             command.for_message, command.client = message, self.client
#             stop = await command_resolved.dispatch(command=command, handler=handler)
#             if not stop:
#                 assert asyncio.iscoroutinefunction(handler)
#                 await handler(self, command)
# 
#     async def on_message_edit(self, before, after):
#         pass
# 
# Path: bot/plugins/commands.py
# class command(object):
# 
#     """
#     Decorator for command handlers in bot Plugins.
#     """
# 
#     def __init__(self, name=None, pattern=None, help=None):
#         assert not callable(name), 'You forgot the parentheses for the decorator'
# 
#         self.name = name
#         if isinstance(pattern, str):
#             pattern = re.compile(pattern)
#         self.regex = pattern
#         self.help = help
# 
#     def __call__(self, func):
#         """
#         Decorator
#         """
#         if self.name is None:
#             self.name = func.__name__.replace('_', ' ')
#         if self.help is None:
#             self.help = func.__doc__.strip().split('\n')[0] if func.__doc__ else None
#         func._command = self
#         return func
# 
#     def as_help(self):
#         cmd = "`{prefix}{name}{pattern}`".format(
#             prefix=PREFIX,
#             name=self.name,
#             pattern=' {}'.format(self.regex.pattern) if self.regex else ''
#         )
#         return "{cmd}{spacer}{help}".format(cmd=cmd, help=self.help or '', spacer=' - ' if self.help else '')
# 
# Path: bot/users/models.py
# class Member(models.Model):
#     discord_id = models.CharField(max_length=50, unique=True)
#     name = models.CharField(_('name'), max_length=255)
#     last_seen = models.DateTimeField(null=True, blank=True)
# 
#     is_bot = models.BooleanField(default=False)
#     can_admin_bot = models.BooleanField(default=False)
# 
#     objects = MemberQuerySet.as_manager()
# 
#     def __str__(self):
#         return '<@{} name={}>'.format(self.discord_id, self.name)
# 
# Path: bot/plugins/stats/models.py
# class LoggedMessage(models.Model):
# 
#     discord_id = models.BigIntegerField(unique=True)
#     server = models.BigIntegerField(_("server"))
# 
#     member = models.ForeignKey('users.Member', related_name='messages_authored', on_delete=models.PROTECT)
#     member_username = models.CharField(max_length=255)  # this can change, only the member.discord_id is a constant
# 
#     channel = models.ForeignKey('channels.Channel', on_delete=models.PROTECT)
# 
#     content = models.TextField()
#     num_lines = models.PositiveSmallIntegerField(default=1)
#     timestamp = models.DateTimeField(auto_now_add=True)
#     edited_timestamp = models.DateTimeField(null=True, blank=True)
# 
#     mentions = models.ManyToManyField('users.Member', related_name='messages_mentioned_in', blank=True)
# 
#     class Meta:
#         verbose_name = _('message')
#         verbose_name_plural = _('messages')
#         ordering = ['-timestamp']
# 
#     def __str__(self):
#         return self.discord_id


# Path: bot/plugins/stats/plugin.py
import logging
import re
from discord.channel import TextChannel
from discord.enums import Status
from django.db.models import Count, Q
from django.utils.timesince import timesince
from django.utils.timezone import make_aware, now, utc
from import_export.admin import DEFAULT_FORMATS
from tabulate import tabulate
from bot.channels.models import Channel
from bot.plugins.base import BasePlugin
from bot.plugins.commands import command
from bot.users.models import Member
from .models import LoggedMessage





logger = logging.getLogger(__name__)


EXPORT_FORMATS = {f().get_title(): f for f in DEFAULT_FORMATS if f().can_export()}


class Plugin(BasePlugin):

    has_blocking_io = True

    async def on_message(self, message):
        """
        Log the message in the db
        """
        await super().on_message(message)

        if not isinstance(message.channel, TextChannel):
            return

        member = Member.objects.from_message(message)

        channel = Channel.objects.from_message(message)