Beispiel #1
0
    def tempmute(self, event, user, duration=None, reason=None):
        if not duration and reason:
            duration = parse_duration(reason.split(' ')[0], safe=True)
            if duration:
                if ' ' in reason:
                    reason = reason.split(' ', 1)[-1]
                else:
                    reason = None
        elif duration:
            duration = parse_duration(duration)

        member = event.guild.get_member(user)
        if member:
            self.can_act_on(event, member.id)
            if not event.config.mute_role:
                raise CommandFail('mute is not setup on this server')

            if event.config.mute_role in member.roles:
                raise CommandFail(u'{} is already muted'.format(member.user))

            # If we have a duration set, this is a tempmute
            if duration:
                # Create the infraction
                Infraction.tempmute(self, event, member, reason, duration)
                self.queue_infractions()

                self.confirm_action(
                    event,
                    maybe_string(
                        reason,
                        u':ok_hand: {u} is now muted for {t} (`{o}`)',
                        u':ok_hand: {u} is now muted for {t}',
                        u=member.user,
                        t=humanize.naturaldelta(duration - datetime.utcnow()),
                    ))
                if event.config.notify_action_on and event.config.notify_action_on.mutes:
                    try:
                        event.guild.get_member(user.id).user.open_dm(
                        ).send_message(
                            'You have been **Muted** in the guild **{}**  for `{}`'
                            .format(event.guild.name, reason
                                    or 'no reason specified.'))
                    except:
                        pass
                else:
                    pass
            else:
                existed = False
                # If the user is already muted check if we can take this from a temp
                #  to perma mute.
                if event.config.mute_role in member.roles:
                    existed = Infraction.clear_active(
                        event, member.id, [Infraction.Types.TEMPMUTE])

                    # The user is 100% muted and not tempmuted at this point, so lets bail
                    if not existed:
                        raise CommandFail(u'{} is already muted'.format(
                            member.user))

                Infraction.mute(self, event, member, reason)

                existed = u' [was temp-muted]' if existed else ''

                self.confirm_action(
                    event,
                    maybe_string(
                        reason,
                        u':ok_hand: {u} is now muted (`{o}`)' + existed,
                        u':ok_hand: {u} is now muted' + existed,
                        u=member.user,
                    ))
                if event.config.notify_action_on and event.config.notify_action_on.mutes:
                    try:
                        event.guild.get_member(user.id).user.open_dm(
                        ).send_message(
                            'You have been **Temporarily Muted** in the guild **{}** for **{}** for `{}`'
                            .format(
                                event.guild.name,
                                humanize.naturaldelta(duration -
                                                      datetime.utcnow()),
                                reason or 'no reason specified.'))
                    except:
                        pass
                else:
                    pass

        else:
            raise CommandFail('invalid user')
Beispiel #2
0
    def stars_stats(self, event, user=None):
        if user:
            try:
                given_stars = list(
                    StarboardEntry.select(fn.COUNT('*'), ).join(Message).where(
                        (~(StarboardEntry.star_message_id >> None))
                        & (StarboardEntry.stars.contains(user.id))
                        & (Message.guild_id == event.guild.id)).tuples())[0][0]

                recieved_stars_posts, recieved_stars_total = list(
                    StarboardEntry.select(
                        fn.COUNT('*'),
                        fn.SUM(fn.array_length(StarboardEntry.stars, 1)),
                    ).join(Message).where(
                        (~(StarboardEntry.star_message_id >> None))
                        & (Message.author_id == user.id)
                        & (Message.guild_id == event.guild.id)).tuples())[0]
            except:
                raise CommandFail('Failed to crunch the numbers on that user')

            embed = MessageEmbed()
            embed.color = 0xffd700
            embed.title = user.username
            embed.set_thumbnail(url=user.avatar_url)
            embed.add_field(name='Total Stars Given',
                            value=str(given_stars),
                            inline=True)
            embed.add_field(name='Total Posts w/ Stars',
                            value=str(recieved_stars_posts),
                            inline=True)
            embed.add_field(name='Total Stars Recieved',
                            value=str(recieved_stars_total),
                            inline=True)
            # embed.add_field(name='Star Rank', value='#{}'.format(recieved_stars_rank), inline=True)
            return event.msg.reply('', embed=embed)

        total_starred_posts, total_stars = list(
            StarboardEntry.select(
                fn.COUNT('*'),
                fn.SUM(fn.array_length(StarboardEntry.stars, 1)),
            ).join(Message).where(
                (~(StarboardEntry.star_message_id >> None))
                & (StarboardEntry.blocked == 0)
                & (Message.guild_id == event.guild.id)).tuples())[0]

        top_users = list(
            StarboardEntry.select(
                fn.SUM(fn.array_length(StarboardEntry.stars, 1)),
                User.user_id).join(Message, ).join(
                    User,
                    on=(Message.author_id == User.user_id),
                ).where((~(StarboardEntry.star_message_id >> None))
                        & (fn.array_length(StarboardEntry.stars, 1) > 0)
                        & (StarboardEntry.blocked == 0)
                        & (Message.guild_id == event.guild.id)).group_by(User).
            order_by(fn.SUM(fn.array_length(StarboardEntry.stars,
                                            1)).desc()).limit(5).tuples())

        embed = MessageEmbed()
        embed.color = 0xffd700
        embed.title = 'Star Stats'
        embed.add_field(name='Total Stars Given',
                        value=total_stars,
                        inline=True)
        embed.add_field(name='Total Starred Posts',
                        value=total_starred_posts,
                        inline=True)
        embed.add_field(name='Top Star Recievers',
                        value='\n'.join(
                            '{}. <@{}> ({})'.format(idx + 1, row[1], row[0])
                            for idx, row in enumerate(top_users)))
        event.msg.reply('', embed=embed)
Beispiel #3
0
    def role_add(self, event, user, role, reason=None, mode=None):
        role_obj = None

        if role.isdigit() and int(role) in event.guild.roles.keys():
            role_obj = event.guild.roles[int(role)]
        else:
            # First try exact match
            exact_matches = [
                i for i in event.guild.roles.values()
                if i.name.lower().replace(' ', '') == role.lower()
            ]
            if len(exact_matches) == 1:
                role_obj = exact_matches[0]
            else:
                # Otherwise we fuzz it up
                rated = sorted(
                    [(fuzz.partial_ratio(role, r.name.replace(' ', '')), r)
                     for r in event.guild.roles.values()],
                    key=lambda i: i[0],
                    reverse=True)

                if rated[0][0] > 40:
                    if len(rated) == 1:
                        role_obj = rated[0][1]
                    elif rated[0][0] - rated[1][0] > 20:
                        role_obj = rated[0][1]

        if not role_obj:
            raise CommandFail(
                'too many matches for that role, try something more exact or the role ID'
            )

        author_member = event.guild.get_member(event.author)
        highest_role = sorted(
            [event.guild.roles.get(r) for r in author_member.roles],
            key=lambda i: i.position,
            reverse=True)
        if not author_member.owner and (
                not highest_role
                or highest_role[0].position < role_obj.position):
            raise CommandFail(
                'you can only {} roles that are ranked lower than your highest role'
                .format(mode))

        member = event.guild.get_member(user)
        if not member:
            raise CommandFail('invalid member')

        self.can_act_on(event, member.id)

        if mode == 'add' and role_obj.id in member.roles:
            raise CommandFail(u'{} already has the {} role'.format(
                member, role_obj.name))
        elif mode == 'remove' and role_obj.id not in member.roles:
            return CommandFail(u'{} doesn\'t have the {} role'.format(
                member, role_obj.name))

        self.bot.plugins.get('ModLogPlugin').create_debounce(
            event,
            member.user.id,
            mode + '_role',
            actor=event.author,
            reason=reason or 'no reason')

        if mode == 'add':
            member.add_role(role_obj.id)
        else:
            member.remove_role(role_obj.id)

        event.msg.reply(u':ok_hand: {} role {} to {}'.format(
            'added' if mode == 'add' else 'removed', role_obj.name, member))
Beispiel #4
0
    def messageinfo(self, event, mid):
        try:
            msg = Message.select(Message).where(
                    (Message.id == mid)
                ).get()
        except Message.DoesNotExist:
            raise CommandFail('the id specified does not exist in our message database.')
        message_content = msg.content
        author_id = msg.author.id
        guild_id = msg.guild_id
        channel_id = msg.channel_id
        deleted = msg.deleted
        num_edits = msg.num_edits
        if num_edits > 0:
            num_edits_bool = True
        else:
            num_edits_bool = False
        discrim = str(msg.author.discriminator)
        # if len(str(cached_name[1])) != 4:
        #     while len(str(temp_str)) < 4:
        #         temp_str = '0' + str(temp_str)
        cached_name = str(msg.author.username) + '#' + str(discrim)
        avatar_name = msg.author.avatar 
        content = []
        embed = MessageEmbed()
        member = event.guild.get_member(author_id)
        
        if not avatar_name:
            if member:
                avatar = default_color(str(member.user.default_avatar))
            else:
                avatar = None   
        elif avatar_name.startswith('a_'):
            avatar = u'https://cdn.discordapp.com/avatars/{}/{}.gif'.format(author_id, avatar_name)
        else:
            avatar = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(author_id, avatar_name)
        if member:
            embed.set_author(name='{} ({})'.format(member.user, member.id), icon_url=avatar)
            embed.set_thumbnail(url=avatar)
        else:
            if avatar:
                embed.set_author(name='{} ({})'.format(cached_name, author_id), icon_url=avatar)
                embed.set_thumbnail(url=avatar)
            else:
                embed.set_author(name='{} ({})'.format(cached_name, author_id))

        # embed.title = "Message Content:"
        content.append(u'**\u276F Message Information:**')
        content.append(u'In channel: <#{}>'.format(channel_id))
        content.append(u'Edited: **{}**'.format(num_edits_bool))
        if deleted:
            content.append(u'Deleted: **{}**'.format(deleted))
        content.append(u'Content: ```{}```'.format(message_content))
        if member:
            content.append(u'\n**\u276F Member Information**')

            if member.nick:
                content.append(u'Nickname: {}'.format(member.nick))

            content.append('Joined: {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() - member.joined_at),
                member.joined_at.isoformat(),
            ))

            if member.roles:
                roles = []
                for r in member.roles:
                    roles.append(member.guild.roles.get(r))
                roles = sorted(roles, key=lambda r: r.position, reverse=True)
                total = len(member.roles)
                roles = roles[:20]
                content.append(u'Roles ({}): {}{}'.format(
                    total, ' '.join(r.mention for r in roles),
                    ' (+{})'.format(total-20) if total > 20 else ''
                ))
                
        embed.description = '\n'.join(content)
        # embed.url = 'https://discordapp.com/channels/{}/{}/{}'.format(guild_id, channel_id, mid)
        embed.timestamp = datetime.utcnow().isoformat()
        if not event.author.avatar:
            auth_avatar = default_color(str(member.user.default_avatar))
        elif event.author.avatar.startswith('a_'):
            auth_avatar = u'https://cdn.discordapp.com/avatars/{}/{}.gif'.format(event.author.id, event.author.avatar)
        else:
            auth_avatar = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(event.author.id, event.author.avatar)
        embed.set_footer(text='Requested by {}#{} ({})'.format(event.author.username, event.author.discriminator, event.author.id), icon_url=auth_avatar)
        try:
            embed.color = get_dominant_colors_user(member.user, avatar)
        except:
            embed.color = '00000000'
        event.msg.reply('', embed=embed)
Beispiel #5
0
 def unlock_stars(self, event):
     if event.guild.id in self.locks:
         del self.locks[event.guild.id]
         raise CommandSuccess('Starboard has been unlocked')
         return
     raise CommandFail('Starboard is not locked')
Beispiel #6
0
 def can_act_on(self, event, victim_id, throw=True):
     if event.author.id == victim_id:
         if not throw:
             return False
         raise CommandFail('Cannot execute that action on yourself')
Beispiel #7
0
    def info(self, event, user=None):
        if user is None:
            user = event.author

        user_id = 0
        if isinstance(user, (int, long)):
            user_id = user
            user = self.state.users.get(user)

        if user and not user_id:
            user = self.state.users.get(user.id)

        if not user:
            if user_id:
                user = self.fetch_user(user_id)
                User.from_disco_user(user)
            else:
                raise CommandFail('unknown user')

        content = []
        content.append(u'**\u276F User Information**')
        content.append(u'ID: {}'.format(user.id))
        content.append(u'Profile: <@{}>'.format(user.id))

        if user.presence:
            emoji, status = get_status_emoji(user.presence)
            content.append('Status: {} <{}>'.format(status, emoji))

            game = user.presence.game
            if game and game.name:
                activity = ['Playing', 'Stream'][int(game.type)] if game.type < 2 else None
                if not game.type:
                    if game.name == 'Spotify':
                        activity = 'Listening to'
                    else:
                        activity = None
                if activity:
                    content.append(u'{}: {}'.format(activity,
                        u'[{}]({})'.format(game.name, game.url) if game.url else game.name
                    ))


        created_dt = to_datetime(user.id)
        content.append('Created: {} ago ({})'.format(
            humanize.naturaldelta(datetime.utcnow() - created_dt),
            created_dt.isoformat()
        ))

        for i in self.server_owners:
            if i == str(user.id):
                content.append('Server Ownership: {}'.format(self.server_owners[i]))
        
        for i in self.server_managers:
            if i == str(user.id):
                content.append('Community Manager: {}'.format(self.server_managers[i]))

        if user.id == self.state.me.id:
            content.append('Documentation: https://aetherya.stream/')
        elif rdb.sismember('global_admins', user.id):
            content.append('Airplane Staff: Global Administrator')
        elif rdb.sismember('server_managers', user.id):
            content.append('Server Manager')
        elif rdb.sismember('server_owner', user.id):
            content.append('Server Owner')

        member = event.guild.get_member(user.id) if event.guild else None
        if member:
            content.append(u'\n**\u276F Member Information**')

            if member.nick:
                content.append(u'Nickname: {}'.format(member.nick))

            content.append('Joined: {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() - member.joined_at),
                member.joined_at.isoformat(),
            ))

            if member.roles:
                roles = []
                for r in member.roles:
                    roles.append(member.guild.roles.get(r))
                roles = sorted(roles, key=lambda r: r.position, reverse=True)
                total = len(member.roles)
                roles = roles[:20]
                content.append(u'Roles ({}): {}{}'.format(
                    total, ' '.join(r.mention for r in roles),
                    ' (+{})'.format(total-20) if total > 20 else ''
                ))

        # Execute a bunch of queries async
        newest_msg = Message.select(Message.timestamp).where(
            (Message.author_id == user.id) &
            (Message.guild_id == event.guild.id)
        ).order_by(Message.timestamp.desc()).limit(1).async()

        # oldest_msg = Message.select(Message.timestamp).where(
        #     (Message.author_id == user.id) &
        #     (Message.guild_id == event.guild.id)
        # ).order_by(Message.timestamp.asc()).limit(1).async()

        infractions = Infraction.select(
            Infraction.guild_id,
            fn.COUNT('*')
        ).where(
            (Infraction.user_id == user.id) &
            (Infraction.type_ != 6) & # Unban
            (~(Infraction.reason ** '[NOTE]%'))
        ).group_by(Infraction.guild_id).tuples().async()

        voice = GuildVoiceSession.select(
            GuildVoiceSession.user_id,
            fn.COUNT('*'),
            fn.SUM(GuildVoiceSession.ended_at - GuildVoiceSession.started_at)
        ).where(
            (GuildVoiceSession.user_id == user.id) &
            (~(GuildVoiceSession.ended_at >> None))
        ).group_by(GuildVoiceSession.user_id).tuples().async()

        # Wait for them all to complete (we're still going to be as slow as the
        #  slowest query, so no need to be smart about this.)
        try:
            wait_many(newest_msg, infractions, voice, timeout=3)
        except gevent.Timeout:
            pass
        tags = to_tags(guild_id=event.msg.guild.id)
            
        if newest_msg.value:
            content.append(u'\n **\u276F Activity**')
            statsd.timing('sql.duration.newest_msg', newest_msg.value._query_time, tags=tags)
            newest_msg = newest_msg.value.get()
            content.append('Last Message: {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() - newest_msg.timestamp),
                newest_msg.timestamp.isoformat(),
            ))

        # if oldest_msg.value:
        #     statsd.timing('sql.duration.oldest_msg', oldest_msg.value._query_time, tags=tags)
        #     oldest_msg = oldest_msg.value.get()
        #     content.append('First Message: {} ago ({})'.format(
        #         humanize.naturaldelta(datetime.utcnow() - oldest_msg.timestamp),
        #         oldest_msg.timestamp.isoformat(),
        #     ))

        if infractions.value:
            statsd.timing('sql.duration.infractions', infractions.value._query_time, tags=tags)
            infractions = list(infractions.value)
            total = sum(i[1] for i in infractions)
            content.append(u'\n**\u276F Infractions**')
            content.append('Total Infractions: {}'.format(total))
            content.append('Unique Servers: {}'.format(len(infractions)))

        if voice.value:
            statsd.timing('plugin.utilities.info.sql.voice', voice.value._query_time, tags=tags)
            voice = list(voice.value)
            content.append(u'\n**\u276F Voice**')
            content.append(u'Sessions: {}'.format(voice[0][1]))
            content.append(u'Time: {}'.format(humanize.naturaldelta(
                voice[0][2]
            )))

        embed = MessageEmbed()

        avatar = user.avatar
        if avatar:
            avatar = u'https://cdn.discordapp.com/avatars/{}/{}.{}'.format(
                user.id, avatar, u'gif' if avatar.startswith('a_') else u'png'
            )
        else:
            avatar = u'https://cdn.discordapp.com/embed/avatars/{}.png'.format(
                int(user.discriminator) % 5
            )

        embed.set_author(name=u'{}#{}'.format(
            user.username,
            user.discriminator,
        ), icon_url=avatar)

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        try:
            embed.color = get_dominant_colors_user(user, avatar)
        except:
            pass
        event.msg.reply('', embed=embed)
Beispiel #8
0
 def plugin_disable(self, event, plugin):
     plugin = self.bot.plugins.get(plugin)
     if not plugin:
         raise CommandFail('It appears that plugin doesn\'t exist')
     self.bot.rmv_plugin(plugin.__class__)
     raise CommandSuccess('Ok, that plugin has been disabled and unloaded')
Beispiel #9
0
    def reactions_clean(self, event, user, count=10, emoji=None):
        if isinstance(user, DiscoUser):
            user = user.id

        if count > 50:
            raise CommandFail('cannot clean more than 50 reactions')

        lock = rdb.lock('clean-reactions-{}'.format(user))
        if not lock.acquire(blocking=False):
            raise CommandFail('already running a clean on user')

        query = [
            (Reaction.user_id == user),
            (Message.guild_id == event.guild.id),
            (Message.deleted == 0),
        ]

        if emoji:
            emoji_id = EMOJI_RE.findall(emoji)
            if emoji_id:
                query.append((Reaction.emoji_id == emoji_id[0]))
            else:
                # TODO: validation?
                query.append((Reaction.emoji_name == emoji))

        try:
            reactions = list(Reaction.select(
                Reaction.message_id,
                Reaction.emoji_id,
                Reaction.emoji_name,
                Message.channel_id,
            ).join(
                Message,
                on=(Message.id == Reaction.message_id),
            ).where(
                reduce(operator.and_, query)
            ).order_by(Reaction.message_id.desc()).limit(count).tuples())

            if not reactions:
                raise CommandFail('no reactions to purge')

            msg = event.msg.reply('Hold on while I clean {} reactions'.format(
                len(reactions)
            ))

            for message_id, emoji_id, emoji_name, channel_id in reactions:
                if emoji_id:
                    emoji = '{}:{}'.format(emoji_name, emoji_id)
                else:
                    emoji = emoji_name

                self.client.api.channels_messages_reactions_delete(
                    channel_id,
                    message_id,
                    emoji,
                    user)

            msg.edit('Ok, I cleaned {} reactions'.format(
                len(reactions),
            ))
        finally:
            lock.release()
Beispiel #10
0
    def info(self, event, user=None):
        if user is None:
            user = event.author

        user_id = 0
        if isinstance(user, (int, long)):
            user_id = user
            user = self.state.users.get(user)

        if user and not user_id:
            user = self.state.users.get(user.id)

        if not user:
            if user_id:
                try:
                    user = self.client.api.users_get(user_id)
                except APIException:
                    raise CommandFail('unknown user')
                User.from_disco_user(user)
            else:
                raise CommandFail('unknown user')

        self.client.api.channels_typing(event.channel.id)

        content = []
        content.append(u'**\u276F User Information**')
        content.append(u'**ID:** {}'.format(user.id))
        content.append(u'**Profile:** <@{}>'.format(user.id))

        if user.presence:
            emoji, status = get_status_emoji(user.presence)
            content.append('**Status:** {} <{}>'.format(status, emoji))

            game = user.presence.game
            if game and game.name:
                activity = [
                    'Playing', 'Stream', 'Listening to', 'Watching',
                    'Custom Status'
                ][int(game.type or 0)]
                if not game.type:
                    activity = None
                if activity:
                    game_name = game.state if game.type == GameType.CUSTOM_STATUS else game.name
                    content.append(u'**{}:** {}'.format(
                        activity, u'[{}]({})'.format(game_name, game.url)
                        if game.url else game_name))

        created_dt = to_datetime(user.id)
        content.append('**Created:** {} ago ({})'.format(
            humanize.naturaldelta(datetime.utcnow() - created_dt),
            created_dt.isoformat()))

        member = event.guild.get_member(user.id) if event.guild else None
        if member:
            content.append(u'\n**\u276F Member Information**')

            if member.nick:
                content.append(u'**Nickname:** {}'.format(member.nick))

            content.append('**Joined:** {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() - member.joined_at),
                member.joined_at.isoformat(),
            ))

            if member.roles:
                content.append(u'**Roles:** {}'.format(', '.join(
                    (member.guild.roles.get(r).mention for r in sorted(
                        member.roles,
                        key=lambda r: member.guild.roles.get(r).position,
                        reverse=True)))))

            # "is not None" does not work with Unset types for some rason
            if bool(member.premium_since):
                content.append('**Boosting since:** {} ago ({})'.format(
                    humanize.naturaldelta(datetime.utcnow() -
                                          member.premium_since),
                    member.premium_since.isoformat(),
                ))

        # Execute a bunch of queries async
        newest_msg = Message.select(Message.timestamp).where(
            (Message.author_id == user.id)
            & (Message.guild_id == event.guild.id)).limit(1).order_by(
                Message.timestamp.desc()). async ()

        oldest_msg = Message.select(Message.timestamp).where(
            (Message.author_id == user.id)
            & (Message.guild_id == event.guild.id)).limit(1).order_by(
                Message.timestamp.asc()). async ()

        infractions = Infraction.select(
            Infraction.guild_id, fn.COUNT('*')).where(
                (Infraction.user_id == user.id)).group_by(
                    Infraction.guild_id).tuples(). async ()

        voice = GuildVoiceSession.select(
            GuildVoiceSession.user_id, fn.COUNT('*'),
            fn.SUM(GuildVoiceSession.ended_at -
                   GuildVoiceSession.started_at)).where(
                       (GuildVoiceSession.user_id == user.id)
                       & (~(GuildVoiceSession.ended_at >> None))).group_by(
                           GuildVoiceSession.user_id).tuples(). async ()

        # Wait for them all to complete (we're still going to be as slow as the
        #  slowest query, so no need to be smart about this.)
        wait_many(newest_msg, oldest_msg, infractions, voice, timeout=10)
        tags = to_tags(guild_id=event.msg.guild.id)

        if newest_msg.value and oldest_msg.value:
            statsd.timing('sql.duration.newest_msg',
                          newest_msg.value._query_time,
                          tags=tags)
            statsd.timing('sql.duration.oldest_msg',
                          oldest_msg.value._query_time,
                          tags=tags)
            newest_msg = newest_msg.value.get()
            oldest_msg = oldest_msg.value.get()

            content.append(u'\n **\u276F Activity**')
            content.append('**Last Message:** {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() -
                                      newest_msg.timestamp),
                newest_msg.timestamp.isoformat(),
            ))
            content.append('**First Message:** {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() -
                                      oldest_msg.timestamp),
                oldest_msg.timestamp.isoformat(),
            ))

        if infractions.value:
            statsd.timing('sql.duration.infractions',
                          infractions.value._query_time,
                          tags=tags)
            infractions = list(infractions.value)
            total = sum(i[1] for i in infractions)
            content.append(u'\n**\u276F Infractions**')
            content.append('**Total Infractions:** {:,}'.format(total))
            content.append('**Unique Servers:** {}'.format(len(infractions)))

        if voice.value:
            statsd.timing('plugin.utilities.info.sql.voice',
                          voice.value._query_time,
                          tags=tags)
            voice = list(voice.value)
            content.append(u'\n**\u276F Voice**')
            content.append(u'**Sessions:** {:,}'.format(voice[0][1]))
            content.append(u'**Time:** {}'.format(
                humanize.naturaldelta(voice[0][2])))

        embed = MessageEmbed()

        avatar = user.avatar
        if avatar:
            avatar = user.avatar_url
        else:
            avatar = u'https://cdn.discordapp.com/embed/avatars/{}.png'.format(
                int(user.discriminator) % 5)

        embed.set_author(name=u'{}#{}'.format(
            user.username,
            user.discriminator,
        ),
                         icon_url=avatar)

        embed.set_thumbnail(url=user.avatar_url if user.avatar else avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(
            user,
            user.get_avatar_url('png') if user.avatar else avatar)
        event.msg.reply('', embed=embed)
Beispiel #11
0
    def clean(self, event, user=None, size=25, typ=None, mode='all'):
        """
        Removes messages
        """
        if 0 > size >= 10000:
            raise CommandFail('too many messages must be between 1-10000')

        if event.channel.id in self.cleans:
            raise CommandFail('a clean is already running on this channel')

        query = Message.select(Message.id).where(
            (Message.deleted >> False)
            & (Message.channel_id == event.channel.id)
            & (Message.timestamp >
               (datetime.utcnow() - timedelta(days=13)))).join(User).order_by(
                   Message.timestamp.desc()).limit(size)

        if mode == 'bots':
            query = query.where((User.bot >> True))
        elif mode == 'user':
            query = query.where((User.user_id == user.id))

        messages = [i[0] for i in query.tuples()]

        if len(messages) > 100:
            msg = event.msg.reply(
                'Woah there, that will delete a total of {} messages, please confirm.'
                .format(len(messages)))

            msg.chain(False).\
                add_reaction(GREEN_TICK_EMOJI).\
                add_reaction(RED_TICK_EMOJI)

            try:
                mra_event = self.wait_for_event(
                    'MessageReactionAdd',
                    message_id=msg.id,
                    conditional=lambda e:
                    (e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and
                     e.user_id == event.author.id)).get(timeout=10)
            except gevent.Timeout:
                return
            finally:
                msg.delete()

            if mra_event.emoji.id != GREEN_TICK_EMOJI_ID:
                return

            event.msg.reply(
                ':wastebasket: Ok please hold on while I delete those messages...'
            ).after(5).delete()

        event.msg.reply('<a:clean:535924986733395969>').after(3).delete()

        def run_clean():
            for chunk in chunks(messages, 100):
                self.client.api.channels_messages_delete_bulk(
                    event.channel.id, chunk)

        self.cleans[event.channel.id] = gevent.spawn(run_clean)
        self.cleans[event.channel.id].join()
        del self.cleans[event.channel.id]
Beispiel #12
0
    def server(self, event, guild_id=None):
        guild = self.state.guilds.get(guild_id) if guild_id else event.guild
        if not guild:
            raise CommandFail('invalid server')

        self.client.api.channels_typing(event.channel.id)

        embed = MessageEmbed()

        # Server Information
        content_server = []

        created_at = to_datetime(guild.id)
        content_server.append(u'**Created:** {} ago ({})'.format(
            humanize.naturaldelta(datetime.utcnow() - created_at),
            created_at.isoformat(),
        ))
        content_server.append(u'**Members:** {:,}'.format(len(guild.members)))
        content_server.append(u'**Features:** {}'.format(
            ', '.join(guild.features) or 'none'))
        content_server.append(u'**Voice region:** {}'.format(guild.region))

        if not bool(guild.max_members):
            self.state.guilds[guild.id].inplace_update(
                self.client.api.guilds_get(guild.id),
                ignored=[
                    'channels',
                    'members',
                    'voice_states',
                    'presences',
                ])

        content_server.append(u'**Max presences:** {:,}'.format(
            self.state.guilds[guild.id].max_presences))
        content_server.append(u'**Max members:** {:,}'.format(
            self.state.guilds[guild.id].max_members))

        embed.add_field(name=u'\u276F Server Information',
                        value='\n'.join(content_server),
                        inline=False)

        # Counts
        content_counts = []
        count = {}
        for c in guild.channels.values():
            if not c.type:
                continue
            ctype = c.type.name.split('_')[1]
            count[ctype] = count.get(ctype, 0) + 1
        content_counts.append(u'<{}> {} channel categories'.format(
            CHANNEL_CATEGORY_EMOJI, count.get('category', 0)))
        content_counts.append(u'<{}> {} text channels'.format(
            TEXT_CHANNEL_EMOJI, count.get('text', 0)))
        content_counts.append(u'<{}> {} voice channels'.format(
            VOICE_CHANNEL_EMOJI, count.get('voice', 0)))
        embed.add_field(name=u'\u276F Counts',
                        value='\n'.join(content_counts),
                        inline=True)

        content_counts2 = []
        content_counts2.append(u'<{}> {} roles'.format(ROLE_EMOJI,
                                                       len(guild.roles)))
        static_emojis = len(
            filter(lambda e: not guild.emojis.get(e).animated, guild.emojis))
        animated_emojis = len(
            filter(lambda e: guild.emojis.get(e).animated, guild.emojis))
        content_counts2.append(u'<{}> {}/{total} static emojis'.format(
            EMOJI_EMOJI, static_emojis, total=self.get_max_emoji_slots(guild)))
        content_counts2.append(u'<{}> {}/{total} animated emojis'.format(
            EMOJI_EMOJI,
            animated_emojis,
            total=self.get_max_emoji_slots(guild)))
        embed.add_field(name=u'\u200B',
                        value='\n'.join(content_counts2),
                        inline=True)

        # Members
        content_members = []
        status_counts = defaultdict(int)
        for member in guild.members.values():
            if not member.user.presence:
                status = Status.OFFLINE
            else:
                status = member.user.presence.status
            status_counts[status] += 1

        for status, count in sorted(status_counts.items(),
                                    key=lambda i: Status[i[0]]):
            content_members.append(u'<{}> - {}'.format(STATUS_EMOJI[status],
                                                       count))

        embed.add_field(name=u'\u276F Members',
                        value='\n'.join(content_members),
                        inline=True)

        # Boosts
        content_boosts = []
        content_boosts.append(u'<{}> Level {}'.format(
            PREMIUM_GUILD_TIER_EMOJI[guild.premium_tier],
            int(guild.premium_tier)))
        real_boost_count = len(
            filter(lambda y: guild.members.get(y).premium_since,
                   guild.members))
        content_boosts.append(u'<{}> {} boosts {}'.format(
            PREMIUM_GUILD_ICON_EMOJI, guild.premium_subscription_count,
            '({})'.format(real_boost_count)
            if real_boost_count < guild.premium_subscription_count else ''))
        embed.add_field(name=u'\u276F Server Boost',
                        value='\n'.join(content_boosts),
                        inline=True)

        if guild.icon:
            embed.set_thumbnail(url=guild.icon_url)
            embed.color = get_dominant_colors_guild(guild,
                                                    guild.get_icon_url('png'))
        event.msg.reply('', embed=embed)
Beispiel #13
0
    def jumbo(self, event, emojis):
        emojis = emojis.split(' ')
        if len(emojis) == 1:
            url = ext = ''
            emoji = emojis[0]
            if EMOJI_RE.match(emoji):
                _, eid = EMOJI_RE.findall(emoji)[0]
                ext = 'gif' if emoji.startswith('<a:') else 'png'
                url = 'https://cdn.discordapp.com/emojis/{}.{}?v=1'.format(
                    eid, ext)
            else:
                ext = 'png'
                url = self.get_emoji_url(emoji)

            if not url:
                raise CommandFail('provided emoji is invalid')

            r = requests.get(url)
            try:
                r.raise_for_status()
            except requests.HTTPError:
                raise CommandFail('provided emoji is invalid')
            return event.msg.reply('',
                                   attachments=[('emoji.' + ext, r.content)])

        else:
            urls = []
            for emoji in emojis[:5]:
                if EMOJI_RE.match(emoji):
                    _, eid = EMOJI_RE.findall(emoji)[0]
                    urls.append(
                        'https://cdn.discordapp.com/emojis/{}.png?v=1'.format(
                            eid))
                else:
                    url = self.get_emoji_url(emoji)
                    urls.append(url) if url else None

            width, height, images = 0, 0, []

            for r in Pool(6).imap(requests.get, urls):
                try:
                    r.raise_for_status()
                except requests.HTTPError:
                    continue

                img = Image.open(BytesIO(r.content))
                height = img.height if img.height > height else height
                width += img.width + 10
                images.append(img)

            if not images:
                raise CommandFail('provided emojis are invalid')

            image = Image.new('RGBA', (width, height))
            width_offset = 0
            for img in images:
                image.paste(img, (width_offset, 0))
                width_offset += img.width + 10

            combined = BytesIO()
            image.save(combined, 'png', quality=55)
            combined.seek(0)
            return event.msg.reply('', attachments=[('emoji.png', combined)])
Beispiel #14
0
 def rps(self, event, user=None):
     p_1 = []
     p_1.append(event.author)
     p_2 = []
     
     if not user:
         p_2.append(event.guild.get_member(351097525928853506)) # Airplane :D
         prompt = event.msg.reply('{}, Rock, Paper, Scissors says shoot! (Please react to one of the following).'.format(p_1[0].mention))
         prompt.chain(False).\
             add_reaction(game_emotes_rps['rock']['default']['emote']).\
             add_reaction(game_emotes_rps['paper']['default']['emote']).\
             add_reaction(game_emotes_rps['scissors']['default']['emote'])
         try:
             mra_event = self.wait_for_event(
                 'MessageReactionAdd',
                 message_id = prompt.id,
                 conditional = lambda e: (
                     e.emoji.id in (game_emotes_rps['rock']['default']['id'], game_emotes_rps['paper']['default']['id'], game_emotes_rps['scissors']['default']['id']) and
                     e.user_id == event.author.id
                 )).get(timeout=15)
         except gevent.Timeout:
             prompt.delete()
             event.msg.reply('{}, you failed to make your choice.'.format(p_1[0].mention)).after(5).delete()
             return
         if mra_event.emoji.id == game_emotes_rps['rock']['default']['id']:
             p_1.append('rock')
         elif mra_event.emoji.id == game_emotes_rps['paper']['default']['id']:
             p_1.append('paper')
         elif mra_event.emoji.id == game_emotes_rps['scissors']['default']['id']:
             p_1.append('scissors')
         else:
             raise CommandFail('invalid emoji selected.')
         prompt.delete()
         rand_options = ['rock', 'paper', 'scissors']
         p_2.append(choice(rand_options))
         outcome = winner_rps(p_1[1], p_2[1])
         p_1.append(outcome[0])
         p_2.append(outcome[1])
         output = '**Results:**\n{0}: <:{2}> `{1}`\n{3}: <:{5}> `{4}`. \n' + outcome[2]
         event.msg.reply(output.format(p_1[0].mention, p_1[1], game_emotes_rps[p_1[1]][p_1[2]]['emote'], p_2[0].mention, p_2[1], game_emotes_rps[p_2[1]][p_2[2]]['emote']))
     
     else:
         p_2.append(event.guild.get_member(user))
         if p_1[0].id == p_2[0].id:
             event.msg.reply('You cannot play against yourself.').after(5).delete()
             return
         msg = event.msg.reply('{1}, {0} has challenged you to play rock paper scissors. Do you accept?'.format(p_1[0].mention, p_2[0].mention))
         msg.chain(False).\
             add_reaction(GREEN_TICK_EMOJI).\
             add_reaction(RED_TICK_EMOJI)
 
         try:
             mra_event = self.wait_for_event(
                 'MessageReactionAdd',
                 message_id=msg.id,
                 conditional=lambda e: (
                     e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and
                     e.user_id == p_2[0].id
                 )).get(timeout=20)
         except gevent.Timeout:
             event.msg.reply('{}, your challenge timed out.'.format(p_1[0].mention)).after(5).delete()
             return
         finally:
             msg.delete()
 
         if str(mra_event.emoji.id) != str(GREEN_TICK_EMOJI_ID):
             event.msg.reply('{}, your partner has declined the challenge.'.format(p_1[0].mention)).after(5).delete()
             return
         else:
             try: # Send dm to the first user
                 prompt_p1 = p_1[0].open_dm().send_message('{}, Rock, Paper, Scissors says shoot! (Please react to one of the following).'.format(p_1[0].mention))
             except:
                 event.msg.reply('{0}, your DMs are disabled, therefore you are unable to challenge another user. Please open your DMs and try again.'.format(p_1[0].mention)).after(5).delete()
                 return
             temp = event.msg.reply('{} is selecting their choice, please wait.'.format(unicode(p_1[0].username)))
             prompt_p1.chain(False).\
                 add_reaction(game_emotes_rps['rock']['default']['emote']).\
                 add_reaction(game_emotes_rps['paper']['default']['emote']).\
                 add_reaction(game_emotes_rps['scissors']['default']['emote'])
             try:
                 mra_event = self.wait_for_event(
                     'MessageReactionAdd',
                     message_id = prompt_p1.id,
                     conditional = lambda e: (
                         e.emoji.id in (game_emotes_rps['rock']['default']['id'], game_emotes_rps['paper']['default']['id'], game_emotes_rps['scissors']['default']['id']) and
                         e.user_id == p_1[0].id
                     )).get(timeout=15)
             except gevent.Timeout:
                 prompt_p1.delete()
                 temp.delete()
                 event.msg.reply('Game canceled, {} failed to make their choice.'.format(p_1[0].mention)).after(5).delete()
                 return
             if mra_event.emoji.id == game_emotes_rps['rock']['default']['id']:
                 p_1.append('rock')
             elif mra_event.emoji.id == game_emotes_rps['paper']['default']['id']:
                 p_1.append('paper')
             elif mra_event.emoji.id == game_emotes_rps['scissors']['default']['id']:
                 p_1.append('scissors')
             temp.delete()
             prompt_p1.delete()
             try: # Send dm to second user
                 prompt_p2 = p_2[0].user.open_dm().send_message('{}, Rock, Paper, Scissors says shoot! (Please react to one of the following).'.format(p_2[0].mention))
             except:
                 event.msg.reply('{0}, your DMs are disabled, therefore you are unable play other users. Please open your DMs and try again.'.format(p_2[0].mention)).after(5).delete()
                 return
             temp = event.msg.reply('{} is selecting their choice, please wait.'.format(unicode(p_2[0].user.username)))
             prompt_p2.chain(False).\
                 add_reaction(game_emotes_rps['rock']['default']['emote']).\
                 add_reaction(game_emotes_rps['paper']['default']['emote']).\
                 add_reaction(game_emotes_rps['scissors']['default']['emote'])
             try:
                 mra_event = self.wait_for_event(
                     'MessageReactionAdd',
                     message_id = prompt_p2.id,
                     conditional = lambda e: (
                         e.emoji.id in (game_emotes_rps['rock']['default']['id'], game_emotes_rps['paper']['default']['id'], game_emotes_rps['scissors']['default']['id']) and
                         e.user_id == p_2[0].id
                     )).get(timeout=15)
             except gevent.Timeout:
                 prompt_p2.delete()
                 temp.delete()
                 event.msg.reply('Game canceled, {} failed to make their choice.'.format(p_2[0].mention)).after(5).delete()
                 return
             if mra_event.emoji.id == game_emotes_rps['rock']['default']['id']:
                 p_2.append('rock')
             elif mra_event.emoji.id == game_emotes_rps['paper']['default']['id']:
                 p_2.append('paper')
             elif mra_event.emoji.id == game_emotes_rps['scissors']['default']['id']:
                 p_2.append('scissors')
             prompt_p2.delete()
             temp.delete()
             outcome = winner_rps(p_1[1], p_2[1])
             p_1.append(outcome[0])
             p_2.append(outcome[1])
             output = '**Results:**\n{0}: <:{2}> `{1}`\n{3}: <:{5}> `{4}`. \n' + outcome[2]
             return event.msg.reply(output.format(p_1[0].mention, p_1[1], game_emotes_rps[p_1[1]][p_1[2]]['emote'], p_2[0].mention, p_2[1], game_emotes_rps[p_2[1]][p_2[2]]['emote']))               
Beispiel #15
0
 def restore(self, event, user):
     member = event.guild.get_member(user)
     if member:
         self.restore_user(event, member)
     else:
         raise CommandFail('invalid user')
Beispiel #16
0
    def lock_stars(self, event):
        if event.guild.id in self.locks:
            raise CommandFail('Starboard is already locked')

        self.locks[event.guild.id] = True
        raise CommandSuccess('Starboard has been locked')
Beispiel #17
0
    def clean_cacnel(self, event):
        if event.channel.id not in self.cleans:
            raise CommandFail('no clean is running in this channel')

        self.cleans[event.channel.id].kill()
        event.msg.reply('Ok, the running clean was cancelled')
Beispiel #18
0
    def xp_edit(self, event, user, amount=None, action=None):
        member = event.guild.get_member(user)

        if not member:
            raise CommandFail('Invalid member')

        if not isinstance(amount, int) and action != "reset":
            raise CommandFail('Invalid amount')

        # self.can_act_on(event, member.id)

        if action == 'give':
            try:
                user = GuildMemberLevel.select().where(
                    (GuildMemberLevel.user_id == member.id)
                    & (GuildMemberLevel.guild_id == member.guild_id)).get()
            except GuildMemberLevel.DoesNotExist:
                user = GuildMemberLevel.create_new(member)

            user.add_xp(member.guild_id, member.id, amount)

            raise CommandSuccess('{} is now Level {} ({} XP)'.format(
                member.user, self.level_from_xp(user.xp + amount),
                (user.xp + amount)))
        elif action == 'take':
            try:
                user = GuildMemberLevel.select().where(
                    (GuildMemberLevel.user_id == member.id)
                    & (GuildMemberLevel.guild_id == member.guild_id)).get()
            except GuildMemberLevel.DoesNotExist:
                user = GuildMemberLevel.create_new(member)
                event.channel.send_message('You\'re a monster. Negative XP?')

            user.rmv_xp(member.guild_id, member.id, amount)

            raise CommandSuccess('{} is now Level {} ({} XP)'.format(
                member.user, self.level_from_xp(user.xp - amount),
                (user.xp - amount)))
        else:
            try:
                user = GuildMemberLevel.select().where(
                    (GuildMemberLevel.user_id == member.id)
                    & (GuildMemberLevel.guild_id == member.guild_id)).get()
            except GuildMemberLevel.DoesNotExist:
                raise CommandFail('This user cannot be reset.')

            msg = event.msg.reply('Really reset `{}`?'.format(member))

            msg.chain(False).\
                add_reaction(GREEN_TICK_EMOJI).\
                add_reaction(RED_TICK_EMOJI)

            try:
                mra_event = self.wait_for_event(
                    'MessageReactionAdd',
                    message_id=msg.id,
                    conditional=lambda e:
                    (e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and
                     e.user_id == event.author.id)).get(timeout=10)
            except gevent.Timeout:
                return
            finally:
                msg.delete()

            if mra_event.emoji.id != GREEN_TICK_EMOJI_ID:
                return

            user.reset_member(event.guild.id, member.id)
            raise CommandSuccess('{} has been reset.'.format(member))