示例#1
0
    def on_commands_info(self, event, mid):
        cmd = Command.select(Command, Message, Channel).join(
            Message,
            on=(Command.message_id == Message.id).alias('message')).join(
                Channel,
                on=(Channel.channel_id == Message.channel_id).alias('channel')
            ).join(
                User,
                on=(User.user_id == Message.author_id).alias('author')).where(
                    Command.message_id == mid).order_by(
                        Message.timestamp.desc(), ).get()

        embed = MessageEmbed()
        embed.title = '{}.{} ({})'.format(cmd.plugin, cmd.command,
                                          cmd.message.id)
        embed.set_author(name=str(cmd.message.author),
                         icon_url=cmd.message.author.get_avatar_url())
        embed.color = 0x77dd77 if cmd.success else 0xff6961

        if not cmd.success:
            embed.description = '```{}```'.format(cmd.traceback)

        embed.add_field(name='Message', value=cmd.message.content)
        embed.add_field(name='Channel',
                        value='{} `{}`'.format(cmd.message.channel.name,
                                               cmd.message.channel.channel_id))
        embed.add_field(name='Guild', value=str(cmd.message.guild_id))
        event.msg.reply(embed=embed)
示例#2
0
    def on_commands_stats(self, event, name):
        if '.' in name:
            plugin, command = name.split('.', 1)
            q = (
                (Command.plugin == plugin) &
                (Command.command == command)
            )
        else:
            q = (Command.command == name)

        result = list(Command.select(
            fn.COUNT('*'),
            Command.success,
        ).where(q).group_by(Command.success).order_by(fn.COUNT('*').desc()).tuples())

        success, error = 0, 0
        for count, check in result:
            if check:
                success = count
            else:
                error = count

        event.msg.reply('Command `{}` was used a total of {} times, {} of those had errors'.format(
            name,
            success + error,
            error
        ))
示例#3
0
    def on_commands_errors(self, event):
        q = Command.select().join(Message,
                                  on=(Command.message_id == Message.id)).where(
                                      Command.success == 0).order_by(
                                          Message.timestamp.desc()).limit(10)

        tbl = MessageTable()
        tbl.set_header('ID', 'Command', 'Error')

        for err in q:
            tbl.add(err.message_id, '{}.{}'.format(err.plugin, err.command),
                    err.traceback.split('\n')[-2])

        event.msg.reply(tbl.compile())
示例#4
0
    def on_commands_usage(self, event):
        q = Command.select(
            fn.COUNT('*'),
            Command.plugin,
            Command.command,
        ).group_by(Command.plugin,
                   Command.command).order_by(fn.COUNT('*').desc()).limit(25)

        tbl = MessageTable()
        tbl.set_header('Plugin', 'Command', 'Usage')

        for count, plugin, command in q.tuples():
            tbl.add(plugin, command, count)

        event.msg.reply(tbl.compile())
示例#5
0
文件: core.py 项目: Eros/speedboat
    def on_message_create(self, event):
        """
        This monstrosity of a function handles the parsing and dispatching of
        commands.
        """
        # Ignore messages sent by bots
        if event.message.author.bot:
            return

        # If this is message for a guild, grab the guild object
        if hasattr(event, 'guild') and event.guild:
            guild_id = event.guild.id
        elif hasattr(event, 'guild_id') and event.guild_id:
            guild_id = event.guild_id
        else:
            guild_id = None

        guild = self.guilds.get(event.guild.id) if guild_id else None
        config = guild and guild.get_config()

        # If the guild has configuration, use that (otherwise use defaults)
        if config and config.commands:
            commands = list(
                self.bot.get_commands_for_message(config.commands.mention, {},
                                                  config.commands.prefix,
                                                  event.message))
        elif guild_id:
            # Otherwise, default to requiring mentions
            commands = list(
                self.bot.get_commands_for_message(True, {}, '', event.message))
        else:
            if ENV != 'prod':
                if not event.message.content.startswith(ENV + '!'):
                    return
                event.message.content = event.message.content[len(ENV) + 1:]

            # DM's just use the commands (no prefix/mention)
            commands = list(
                self.bot.get_commands_for_message(False, {}, '',
                                                  event.message))

        # If we didn't find any matching commands, return
        if not len(commands):
            return

        event.user_level = self.get_level(event.guild,
                                          event.author) if event.guild else 0

        # Grab whether this user is a global admin
        # TODO: cache this
        global_admin = rdb.sismember('global_admins', event.author.id)

        # Iterate over commands and find a match
        for command, match in commands:
            if command.level == -1 and not global_admin:
                continue

            level = command.level

            if guild and not config and command.triggers[0] != 'setup':
                continue
            elif config and config.commands and command.plugin != self:
                overrides = {}
                for obj in config.commands.get_command_override(command):
                    overrides.update(obj)

                if overrides.get('disabled'):
                    continue

                level = overrides.get('level', level)

            if not global_admin and event.user_level < level:
                continue

            with timed('rowboat.command.duration',
                       tags={
                           'plugin': command.plugin.name,
                           'command': command.name
                       }):
                try:
                    command_event = CommandEvent(command, event.message, match)
                    command_event.user_level = event.user_level
                    command.plugin.execute(command_event)
                except CommandResponse as e:
                    event.reply(e.response)
                except:
                    tracked = Command.track(event, command, exception=True)
                    self.log.exception('Command error:')

                    with self.send_control_message() as embed:
                        embed.title = u'Command Error: {}'.format(command.name)
                        embed.color = 0xff6961
                        embed.add_field(name='Author',
                                        value='({}) `{}`'.format(
                                            event.author, event.author.id),
                                        inline=True)
                        embed.add_field(name='Channel',
                                        value='({}) `{}`'.format(
                                            event.channel.name,
                                            event.channel.id),
                                        inline=True)
                        embed.description = '```{}```'.format(u'\n'.join(
                            tracked.traceback.split('\n')[-8:]))

                    return event.reply(
                        '<:{}> something went wrong, perhaps try again later'.
                        format(RED_TICK_EMOJI))

            Command.track(event, command)

            # Dispatch the command used modlog event
            if config:
                modlog_config = getattr(config.plugins, 'modlog', None)
                if not modlog_config:
                    return

                self._attach_local_event_data(event, 'modlog', event.guild.id)

                plugin = self.bot.plugins.get('ModLogPlugin')
                if plugin:
                    plugin.log_action(Actions.COMMAND_USED, event)

            return
示例#6
0
def guild_stats_self(guild):
    def serialize_user(gcc):
        for i in gcc:
            user_raw = '''
                SELECT username, discriminator
                FROM users
                WHERE
                    user_id=%s AND
                    bot=false;
            '''

            user = list(User.raw(user_raw, i[1]).tuples())

            if user:
                return {
                    'user': {
                        'username': user[0][0],
                        'discrim': str(user[0][1]),
                        'id': i[1]
                    },
                    'user_count': int(i[0]),
                }

        return {
            'user': '******',
            'user_count': 0,
        }

    def serialize_emoji(gcc):
        for i in gcc:
            emoji_raw = '''
                SELECT emoji_id
                FROM guild_emojis
                WHERE
                    emoji_id=%s AND
                    guild_id=%s;
            '''

            emoji = list(
                GuildEmoji.raw(emoji_raw, i[0], guild.guild_id).tuples())

            if emoji:
                return str(emoji[0][0])

        return '230870076126003200'

    data = json.loads(
        rdb.get('web:guild:{}:stats'.format(guild.guild_id)) or '{}')

    if not data:
        # Totals
        totals_messages = Message.select(Message.id).where(
            (Message.guild_id == guild.guild_id)).count()

        totals_infractions = Infraction.select(Infraction.id).where(
            (Infraction.guild_id == guild.guild_id)).count()

        # Peaks
        ## Messages
        peaks_messages_raw = '''
            SELECT count(id), author_id
            FROM
                messages
            WHERE
                guild_id=%s
            GROUP BY author_id
            ORDER BY count DESC
            LIMIT 5;
        '''

        peaks_messages = list(
            Message.raw(peaks_messages_raw, guild.guild_id).tuples())

        ## Infractions
        peaks_infractions_raw = '''
            SELECT count(id), user_id
            FROM
                infractions
            WHERE
                guild_id=%s
            GROUP BY user_id
            ORDER BY count DESC
            LIMIT 5;
        '''

        peaks_infractions = list(
            Infraction.raw(peaks_infractions_raw, guild.guild_id).tuples())

        ## Emoji
        peaks_emoji_raw = '''
            SELECT id, count(*)
            FROM (
                SELECT unnest(emojis) as id
                FROM messages
                WHERE guild_id=%s and
                cardinality(emojis) > 0
            ) q
            GROUP BY 1
            ORDER BY 2 DESC
            LIMIT 5
        '''

        peaks_emoji = list(
            Message.raw(peaks_emoji_raw, guild.guild_id).tuples())

        ## Command
        peaks_command_raw = '''
            SELECT count(c.command), c.command
            FROM
                commands c
            INNER JOIN messages m
            ON (c.message_id = m.id)
            WHERE
                m.guild_id=%s
            GROUP BY 2
            ORDER BY 1 DESC
            LIMIT 1;
        '''

        peaks_command = list(
            Command.raw(peaks_command_raw, guild.guild_id).tuples())

        if totals_messages:
            totals_messages = totals_messages
        else:
            totals_messages = 0

        if totals_infractions:
            totals_infractions = totals_infractions
        else:
            totals_infractions = 0

        if peaks_messages:
            pm = serialize_user(peaks_messages)
        else:
            pm = {
                'user': '******',
                'user_count': 0,
            }

        if peaks_infractions:
            pi = serialize_user(peaks_infractions)
        else:
            pi = {
                'user': '******',
                'user_count': 0,
            }

        if peaks_emoji:
            anim = False

            peaks_emoji_id = serialize_emoji(peaks_emoji)
            url = 'https://discordapp.com/api/emojis/{}.gif'.format(
                peaks_emoji_id)
            r = requests.get(url)
            try:
                r.raise_for_status()
                anim = True
            except requests.HTTPError:
                pass

            if anim:
                peaks_emoji_ext = 'gif'
            else:
                peaks_emoji_ext = 'png'
        else:
            peaks_emoji_id = '230870076126003200'
            peaks_emoji_ext = 'png'

        if peaks_command:
            peaks_command = '{1}'.format(*peaks_command[0])
        else:
            peaks_command = 'N/A'

        data = {
            'totals': {
                'messages': totals_messages,
                'infractions': totals_infractions,
            },
            'peaks': {
                'messages': pm,
                'infractions': pi,
                'emoji': {
                    'id': peaks_emoji_id,
                    'ext': peaks_emoji_ext,
                },
                'command': peaks_command,
            },
        }
        rdb.setex('web:guild:{}:stats'.format(guild.guild_id),
                  json.dumps(data), 600)

    return jsonify(data)
示例#7
0
    def on_message_create(self, event, is_tag=False):
        """
        This monstrosity of a function handles the parsing and dispatching of
        commands.
        """
        # Ignore messages sent by bots
        if event.message.author.bot or rdb.sismember('ignored_channels',
                                                     event.message.channel_id):
            return

        # If this is message for a guild, grab the guild object
        if hasattr(event, 'guild') and event.guild:
            guild_id = event.guild.id
        elif hasattr(event, 'guild_id') and event.guild_id:
            guild_id = event.guild_id
        else:
            guild_id = None

        guild = self.guilds.get(event.guild.id) if guild_id else None
        config = guild and guild.get_config()
        cc = config.commands if config else None

        # If the guild has configuration, use that (otherwise use defaults)
        if config and config.commands:
            commands = list(
                self.bot.get_commands_for_message(config.commands.mention, {},
                                                  config.commands.prefix,
                                                  event.message))
        elif guild_id:
            # Otherwise, default to requiring mentions
            commands = list(
                self.bot.get_commands_for_message(True, {}, '', event.message))
        else:
            # if ENV != 'prod':
            if ENV not in 'prod':
                if not event.message.content.startswith(ENV + '!'):
                    return
                event.message.content = event.message.content[len(ENV) + 1:]

            # DM's just use the commands (no prefix/mention)
            commands = list(
                self.bot.get_commands_for_message(False, {}, '',
                                                  event.message))

        # if no command, attempt to run as a tag
        if not commands:
            if is_tag:
                return

            if not event.guild or not self.bot.plugins.get('TagsPlugin'):
                return

            if not config or not config.plugins or not config.plugins.tags:
                return

            prefixes = []
            if cc.prefix:
                prefixes.append(cc.prefix)
            if cc.mention:
                prefixes.append('{} '.format(self.bot.client.state.me.mention))
            if not prefixes:
                return

            tag_re = re.compile('^({})(.+)'.format(
                re.escape('|'.join(prefixes))))
            m = tag_re.match(event.message.content)
            if not m:
                return

            sqlplugin = self.bot.plugins.get('SQLPlugin')
            if sqlplugin:
                sqlplugin.tag_messages.append(event.message.id)
            event.message.content = '{}tags show {}'.format(
                m.group(1), m.group(2))
            return self.on_message_create(event, True)

        event.user_level = self.get_level(event.guild,
                                          event.author) if event.guild else 0

        # Grab whether this user is a global admin
        # TODO: cache this
        ## this is technically already cached and runs fastest this way
        global_admin = rdb.sismember('global_admins', event.author.id)

        # Iterate over commands and find a match
        for command, match in commands:
            if command.level == -1 and not global_admin:
                continue

            level = command.level

            if guild and not config and command.triggers[0] != 'setup':
                continue
            elif config and config.commands and command.plugin != self:
                overrides = {}
                for obj in config.commands.get_command_override(command):
                    overrides.update(obj)

                if overrides.get('disabled'):
                    continue

                level = overrides.get('level', level)

            if not global_admin and event.user_level < level:
                continue

            try:
                command_event = CommandEvent(command, event.message, match)
                command_event.user_level = event.user_level
                command.plugin.execute(command_event)
            except CommandResponse as e:
                if is_tag:
                    return
                event.reply(e.response)
            except:
                tracked = Command.track(event, command, exception=True)
                self.log.exception('Command error:')

                with self.send_control_message() as embed:
                    embed.title = 'Command Error: {}'.format(command.name)
                    embed.color = 0xff6961
                    embed.add_field(name='Author',
                                    value='({}) `{}`'.format(
                                        event.author, event.author.id),
                                    inline=True)
                    embed.add_field(name='Channel',
                                    value='({}) `{}`'.format(
                                        event.channel.name, event.channel.id),
                                    inline=True)
                    embed.description = '```{}```'.format('\n'.join(
                        tracked.traceback.split('\n')[-8:]))

                return event.reply(
                    '<:{}> something went wrong, perhaps try again later'.
                    format(RED_TICK_EMOJI))

            Command.track(event, command)

            # Dispatch the command used modlog event
            if config:
                modlog_config = getattr(config.plugins, 'modlog', None)
                if not modlog_config:
                    return

                if is_tag:  # Yes, I know, this is ugly but I don't have better
                    event.content = event.content.replace('tags show ', '', 1)

                self._attach_local_event_data(event, 'modlog', event.guild.id)

                plugin = self.bot.plugins.get('ModLogPlugin')
                if plugin:
                    plugin.log_action(Actions.COMMAND_USED, event)

            return