Esempio n. 1
0
 def ping(self, event):
     pre = time.time()
     post = (time.mktime(to_datetime(event.msg.id).timetuple()) -
             pre) / 1000
     msg = event.msg.reply(":eyes:")
     ping = (time.time() - pre) * 1000
     msg.edit(":eyes: `BOT: {}ms` `API: {}ms`".format(int(post), int(ping)))
Esempio n. 2
0
    def on_guild_member_add(self, event):
        created = humanize.naturaltime(datetime.utcnow() - to_datetime(event.user.id))
        new = (
            event.config.new_member_threshold and
            (time.time() - to_unix(event.user.id)) < event.config.new_member_threshold
        )

        self.log_action(Actions.GUILD_MEMBER_ADD, event, new=' :new:' if new else '', created=created)
Esempio n. 3
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')

        content = []
        content.append('**\u276F Server Information**')
        content.append('Owner: {} ({})'.format(guild.owner, guild.owner.id))

        created_at = to_datetime(guild.id)
        content.append('Created: {} ({})'.format(
            humanize.naturaltime(datetime.utcnow() - created_at),
            created_at.isoformat(),
        ))

        content.append('Members: {:,}'.format(len(guild.members)))
        if guild.features:
            content.append('Features: {}'.format(', '.join(guild.features)))

        content.append('\n**\u276F Counts**')
        text_count = sum(1 for c in list(guild.channels.values())
                         if not c.is_voice)
        voice_count = len(guild.channels) - text_count
        content.append('Roles: {}'.format(len(guild.roles)))
        content.append('Text: {}'.format(text_count))
        content.append('Voice: {}'.format(voice_count))

        content.append('\n**\u276F Members**')
        status_counts = defaultdict(int)
        for member in list(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(list(status_counts.items()),
                                    key=lambda i: str(i[0]),
                                    reverse=True):
            content.append('<{}> - {}'.format(STATUS_EMOJI[status], count))

        embed = MessageEmbed()
        if guild.icon:
            embed.set_thumbnail(url=guild.icon_url)
            # TODO: Fix whatever caused me to need to do this
            try:
                embed.color = get_dominant_colors_guild(guild)
            except:
                embed.color = 0x7289DA
        embed.description = '\n'.join(content)
        event.msg.reply('', embed=embed)
Esempio n. 4
0
    def run(self):
        self.log.info('Starting recovery on channel %s (%s -> %s)', self.channel.id, self.start_dt, self.end_dt)

        msgs = self.channel.messages_iter(
            bulk=True,
            direction=MessageIterator.Direction.DOWN,
            after=str(from_datetime(self.start_dt))
        )

        for chunk in msgs:
            Message.from_disco_message_many(chunk, safe=True)

            if to_datetime(chunk[-1].id) > self.end_dt:
                break
Esempio n. 5
0
    def trigger_delay(self, event, length: int = None):
        length = length if length else 10

        msg = event.channel.send_message("Sending later...")

        def calc_timediff():
            return "Scheduled for {} after trigger, took {}".format(
                length, (datetime.now() - to_datetime(msg.id)))

        gevent.spawn_later(
            length, lambda: event.channel.send_message(
                "Scheduled for {} after trigger, took {}".format(
                    length, (datetime.now() - to_datetime(msg.id)) / timedelta(
                        seconds=1))))
Esempio n. 6
0
    def server(self, event, guild_id=None):
        guild: Guild = self.state.guilds.get(
            guild_id) if guild_id else event.guild
        if not guild:
            raise CommandFail('Invalid server')

        embed = MessageEmbed()
        embed.set_author(
            MessageEmbedAuthor(name=guild.name, icon_url=guild.icon_url()))

        # General Abouts
        about_field = MessageEmbedField()
        about_field.name = '**\u276F About**'
        about_text = 'Created by {} ({}) — <t:{}:R>'.format(
            guild.owner, guild.owner.id,
            int(to_datetime(guild.id).replace(tzinfo=pytz.UTC).timestamp()))
        about_text += '\nMembers: {:,}/{:,}'.format(
            guild.approximate_presence_count, guild.member_count)
        about_text += '\nRegion: {}'.format(guild.region)
        about_field.value = about_text
        embed.add_field(about_field)

        # General Counts
        counts_field = MessageEmbedField()
        counts_field.name = '\n**\u276F Counts**'
        text_count = sum(1 for c in list(guild.channels.values())
                         if not c.is_voice and not c.is_thread)
        voice_count = len(guild.channels) - text_count

        counts_field.value = 'Roles: {:,}\nText: {:,}\nVoice: {:,}'.format(
            len(guild.roles), text_count, voice_count)
        embed.add_field(counts_field)

        # Security
        security_field = MessageEmbedField()
        security_field.name = '\n**\u276F Security**'
        security_field.value = 'Verification: {}\nExplicit Content: {}'.format(
            guild.verification_level, guild.explicit_content_filter)
        embed.add_field(security_field)

        # Features
        features_field = MessageEmbedField()
        features_field.name = '\n**\u276F Features**'
        features_field.value = 'Features: {}'.format(', '.join(guild.features))
        embed.add_field(features_field)

        if guild.icon:
            embed.color = get_dominant_colors_guild(guild)
        event.msg.reply('', embed=embed)
Esempio n. 7
0
    def command_info(self, event, user):
        lines = []
        lines.append('**ID:** {}'.format(user.id))
        lines.append('**Username:** {}'.format(user.username))
        lines.append('**Discriminator:** {}'.format(user.discriminator))

        if event.guild:
            member = event.guild.get_member(user)
            if member:
                if member.nick:
                    lines.append('**Nickname:** {}'.format(member.nick))

                lines.append('**Joined At:** {}'.format(member.joined_at))

        lines.append('**Creation Date:** {}'.format(to_datetime(user.id)))
        event.msg.reply('\n'.join(lines))
Esempio n. 8
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')

        content = []
        content.append(u'**\u276F Server Information**')

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

        content.append(u'\n**\u276F Counts**')
        text_count = sum(1 for c in guild.channels.values() if not c.is_voice)
        voice_count = len(guild.channels) - text_count
        content.append(u'Roles: {}'.format(len(guild.roles)))
        content.append(u'Text: {}'.format(text_count))
        content.append(u'Voice: {}'.format(voice_count))

        content.append(u'\n**\u276F 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: str(i[0]), reverse=True):
            content.append(u'<{}> - {}'.format(
                STATUS_EMOJI[status], format(count, ',d')
            ))

        embed = MessageEmbed()
        if guild.icon:
            embed.set_thumbnail(url=guild.icon_url)
            embed.color = get_dominant_colors_guild(guild)
        embed.description = '\n'.join(content)
        event.msg.reply('', embed=embed)
Esempio n. 9
0
  def on_member_join(self, event):
    now = datetime.now().strftime("%H:%M:%S")
    
    with open(DATA_DIR.format(event.guild.id), 'r') as file:
      config = json.load(file)
    
    created = humanize.naturaltime(datetime.utcnow() - to_datetime(event.user.id))
    self.client.api.channels_messages_create(config['memberLog'], content='`[{}]` :inbox_tray: {}#{} (`{}`) joined ({})'.format(
      now, event.user.username, event.user.discriminator, event.user.id, created
    ))

    file = str(event.user.id) + '.json'

    if not file in listdir('data/guilds/{}/points'.format(event.guild.id)):
      with open(DEFAULT_POINTS, 'r') as points_file:
        points_data = json.load(points_file)

        with open(POINTS_DIR, 'w') as points_config:
          points_config.write(json.dumps(points_data))
Esempio n. 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
                    ))

        if user.public_flags and user.public_flags != 0:
            flags = []
            for flag, emoji in BADGE_EMOJI.items():
                if user.public_flags.check(flag):
                    flags.append('<{}>'.format(emoji))

            if len(flags) > 0:
                content.append('**Badges**: {}'.format(' '.join(flags)))

        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 reason
            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)
Esempio n. 11
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(guild.member_count))
        if len(guild.features) > 0:
            content_server.append(u'**Features:** {}'.format(', '.join(guild.features) or 'none'))
        content_server.append(u'**Voice region:** {}'.format(guild.region))

        if not rdb.exists('gmm:{}'.format(guild.id)):
            self.state.guilds[guild.id].inplace_update(self.client.api.guilds_get(guild.id), ignored=[
                'channels',
                'members',
                'voice_states',
                'presences',
            ])
            rdb.set('gmp:{}'.format(guild.id), self.state.guilds[guild.id].max_presences)
            rdb.set('gmm:{}'.format(guild.id), self.state.guilds[guild.id].max_members)

        content_server.append(u'**Max presences:** {:,}'.format(int(rdb.get('gmp:{}'.format(guild.id)))))
        content_server.append(u'**Max members:** {:,}'.format(int(rdb.get('gmm:{}'.format(guild.id)))))

        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
        invite = guild.get_preview()

        status_online = None
        if invite:
            if not rdb.exists('apc:{}'.format(guild.id)):
                rdb.set('apc:{}'.format(guild.id), invite.approximate_presence_count, 900)
            status_online = int(rdb.get('apc:{}'.format(guild.id)))

            content_members = []
            content_members.append('<{}> {}'.format(STATUS_EMOJI[Status.ONLINE], status_online))
            content_members.append('<{}> {}'.format(STATUS_EMOJI[Status.OFFLINE], (guild.member_count - status_online)))

            # 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,
            # '({} members)'.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)
Esempio n. 12
0
    def info(self, event, user):
        if isinstance(user, (int, long)):
            try:
                r = self.bot.client.api.http(Routes.USERS_GET, dict(user=user)) # hacky method cause this old version of Disco doesn't have a method for this and we're too lazy to update
                data = r.json()
                User = namedtuple('User', [
                    'avatar',
                    'discriminator',
                    'id',
                    'username',
                    'presence'
                ])
                user = User(
                    avatar=data["avatar"],
                    discriminator=data["discriminator"],
                    id=int(data["id"]),
                    username=data["username"],
                    presence=None
                )
            except APIException as e:
                raise CommandFail('invalid 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))
            if user.presence.game and user.presence.game.name:
                if user.presence.game.type == GameType.DEFAULT:
                    content.append(u'Game: {}'.format(user.presence.game.name))
                else:
                    content.append(u'Stream: [{}]({})'.format(user.presence.game.name, user.presence.game.url))

        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).name for r in member.roles))
                ))

        # 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_duration(datetime.utcnow() - newest_msg.timestamp),
                newest_msg.timestamp.isoformat(),
            ))
            content.append('First Message: {} ago ({})'.format(
                humanize_duration(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 = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(
            user.id,
            user.avatar,
        )

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

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(user, avatar)
        event.msg.reply('', embed=embed)
Esempio n. 13
0
    def info(self, event, 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))
            if user.presence.game and user.presence.game.name:
                if user.presence.game.type == GameType.DEFAULT:
                    content.append(u'Game: {}'.format(user.presence.game.name))
                else:
                    content.append(u'Stream: [{}]({})'.format(
                        user.presence.game.name, user.presence.game.url))

        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).name for r in member.roles))))

        # Execute a bunch of queries async
        infractions = Infraction.select(
            Infraction.guild_id, fn.COUNT('*')).where(
                (Infraction.user_id == user.id)).group_by(
                    Infraction.guild_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(infractions, timeout=10)
        tags = to_tags(guild_id=event.msg.guild.id)

        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)))

        embed = MessageEmbed()

        avatar = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(
            user.id,
            user.avatar,
        )

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

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(user, avatar)
        event.msg.reply('', embed=embed)
Esempio n. 14
0
    def info(self, event, user):
        content = []
        content.append(u'**\u276F User Information**')

        if user.presence:
            emoji, status = get_status_emoji(user.presence)
            content.append('Status: {} <{}>'.format(status, emoji))
            if user.presence.game and user.presence.game.name:
                if user.presence.game.type == GameType.DEFAULT:
                    content.append(u'Game: {}'.format(user.presence.game.name))
                else:
                    content.append(u'Stream: [{}]({})'.format(
                        user.presence.game.name, user.presence.game.url))

        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).name for r in member.roles))))

        try:
            newest_msg = Message.select(Message.timestamp).where(
                (Message.author_id == user.id)
                & (Message.guild_id == event.guild.id)).order_by(
                    Message.timestamp.desc()).get()

            oldest_msg = Message.select(Message.timestamp).where(
                (Message.author_id == user.id)
                & (Message.guild_id == event.guild.id)).order_by(
                    Message.timestamp.asc()).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(),
            ))
        except Message.DoesNotExist:
            pass

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

        if infractions:
            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)))

        voice = list(
            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())

        if voice:
            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 = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(
            user.id,
            user.avatar,
        )

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

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(user, avatar)
        event.msg.reply('', embed=embed)
Esempio n. 15
0
    def info(self, event, user: User = None):
        if not user:
            user = event.author
        else:
            if not isinstance(user, DiscoUser):
                try:
                    user = self.state.guilds[event.guild.id].members[user].user
                except KeyError:
                    try:
                        user = self.state.users[user]
                    except KeyError:
                        try:
                            user = self.bot.client.api.users_get(user)
                        except APIException:
                            return event.msg.reply(
                                ':eyes: User not found').after(3).delete()

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

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

        created_dt = to_datetime(user.id)
        content.append('Created: <t:{0}:R> (<t:{0}:f>)'.format(
            int(created_dt.replace(tzinfo=pytz.UTC).timestamp())))

        member = event.guild.get_member(user.id) if event.guild else None

        if user.public_flags:
            badges = ''
            user_badges = list(UserFlags(user.public_flags))
            for badge in user_badges:
                badges += '<{}> '.format(BADGE_EMOJI[badge])

            content.append('Badges: {}'.format(badges))

        if member:
            content.append('\n**\u276F Member Information**')

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

            content.append('Joined: <t:{0}:R> (<t:{0}:f>)'.format(
                int(member.joined_at.replace(tzinfo=pytz.UTC).timestamp())))

            content.append('Messages: {}'.format(
                int(
                    Message.select(fn.Count(
                        Message.id)).where((Message.author_id == user.id)
                                           & (Message.guild_id == event.guild.
                                              id)).tuples()[0][0])))

            if member.roles:
                content.append('Roles: {}'.format(', '.join(
                    ('<@&{}>'.format(r) for r in member.roles))))

        # Execute a bunch of queries
        newest_msg = Message.select(fn.MAX(Message.id)).where(
            (Message.author_id == user.id)
            & (Message.guild_id == event.guild.id)).tuples()[0][0]

        infractions = Infraction.select(Infraction.id).where(
            (Infraction.user_id == user.id)
            & (Infraction.guild_id == event.guild.id)).tuples()

        if newest_msg:
            content.append('\n **\u276F Activity**')
            content.append('Last Message: <t:{0}:R> (<t:{0}:f>)'.format(
                int((to_datetime(newest_msg).replace(
                    tzinfo=pytz.UTC)).timestamp())))
            # content.append('First Message: {} ({})'.format(
            #    humanize.naturaltime(datetime.utcnow() - to_datetime(oldest_msg)),
            #    to_datetime(oldest_msg).strftime("%b %d %Y %H:%M:%S"),
            # ))

        if len(infractions) > 0:
            content.append('\n**\u276F Infractions**')
            total = len(infractions)
            content.append('Total Infractions: **{:,}**'.format(total))

        embed = MessageEmbed()

        try:
            avatar = User.with_id(user.id).get_avatar_url()
        except APIException:
            avatar = user.get_avatar_url(
            )  # This fails if the user has never been seen by speedboat.

        embed.set_author(name='{} ({})'.format(
            str(user),
            user.id,
        ),
                         icon_url=avatar)

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(user, avatar)
        event.msg.reply('', embed=embed)
Esempio n. 16
0
 def calc_timediff():
     return "Scheduled for {} after trigger, took {}".format(
         length, (datetime.now() - to_datetime(msg.id)))
Esempio n. 17
0
    def check_advanced(self, event, member, rule):
        scores = []
        marks = []

        def mark(amount, reason):
            scores.append(amount)
            marks.append(reason)

        # CHECK 1
        # Check if the user just exited their quiescent period from guild verification
        #  which means they may have been waiting to spam
        duration_before_talk = 0
        if event.guild.verification_level == VerificationLevel.MEDIUM:
            duration_before_talk = 60 * 5
        elif event.guild.verification_level == VerificationLevel.HIGH:
            duration_before_talk = 60 * 10

        if duration_before_talk:
            duration = (datetime.utcnow() - member.joined_at).seconds
            if duration >= duration_before_talk:
                if (duration - duration_before_talk) < 10:
                    mark(10, 'check1.talk_within_ten_seconds')
                elif (duration - duration_before_talk) < 60:
                    mark(5, 'check1.talk_within_sixty_seconds')
                elif (duration - duration_before_talk) < 120:
                    mark(3, 'check1.talk_within_two_minutes')
                elif (duration - duration_before_talk) < 300:
                    mark(1, 'check1.talk_within_five_minutes')

        # CHECK 2
        # Check if the users account was created recently, which means they may
        #  have made it just to spam.
        account_age = (datetime.utcnow() -
                       to_datetime(event.author.id)).seconds
        if account_age < 15 * 60:
            mark(5, 'check2.account_age_less_than_fifteen_minutes')
        elif account_age < 30 * 60:
            mark(3, 'check2.account_age_less_than_thirty_minutes')
        elif account_age < 60 * 60:
            mark(1, 'check2.account_age_less_than_one_hour')

        # CHECK 3
        # Check if this is the first message sent by the user, perhaps signaling
        #  they just joined to spam
        sent_messages = Message.select().where(
            (Message.guild_id == event.guild.id)
            & (Message.author_id == event.author.id)).count()

        if sent_messages == 0:
            mark(10, 'check3.first_message_in_server')
        elif sent_messages < 10:
            mark(3, 'check3.first_ten_messages_in_server')

        # CHECK 4
        # For every user mentioned in their message, determine how "important"
        #  or likely to be spammed they are.
        for mention in event.mentions.values():
            member = event.guild.get_member(mention)

            # If the user is an admin of the server, they are likely to be a victim
            if member.owner:
                mark(7, 'check4.mentions_owner')
            if member.permissions.administrator or member.permissions.manage_guild:
                mark(5, 'check4.mentions_administrator')
            elif member.permissions.ban_members or member.permissions.kick_members:
                mark(1, 'check4.mentions_moderator')

            # If the user is hoisted, they are likely to be a victim
            if any(i.hoist for i in map(event.guild.roles.get, member.roles)):
                mark(7, 'check4.mentions_hoisted_user')

        # CHECK 5
        # Check how many bad words are in the message, generally low-effort spammers
        #  just shove "shock" value content in their message.
        num_bad_words = sum(1 for word in event.content.split(' ')
                            if word in BAD_WORDS)
        if num_bad_words:
            mark(num_bad_words, 'check5.has_bad_words_%s' % num_bad_words)

        TempSpamScore.track(event.id, sum(scores), marks)
Esempio n. 18
0
    def info(self, event, user=None):

        if not user:
            user = event.author
        else:
            if not isinstance(user, DiscoUser):
                try:
                    user = self.state.guilds[event.guild.id].members[user].user
                except KeyError:
                    try:
                        user = self.state.users[user]
                    except KeyError:
                        try:
                            user = self.bot.client.api.users_get(user)
                        except APIException:
                            return event.msg.reply(
                                'User not found :eyes:').after(3).delete()

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

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

        created_dt = to_datetime(user.id)
        content.append('Created: {} ({})'.format(
            humanize.naturaltime(datetime.utcnow() - created_dt),
            created_dt.strftime("%b %d %Y %H:%M:%S")))

        member = event.guild.get_member(user.id) if event.guild else None

        if user.presence:  #I couldn't get this to work w/o it lol
            emoji, status = get_status_emoji(user.presence)
            content.append('Status: <{}> {}'.format(emoji, status))
            if user.presence.game and user.presence.game.name:
                if user.presence.game.type == ActivityTypes.DEFAULT:
                    content.append('{}'.format(user.presence.game.name))
                if user.presence.game.type == ActivityTypes.CUSTOM:
                    content.append('Custom Status: {}'.format(
                        user.presence.game.state))
                if user.presence.game.type == ActivityTypes.LISTENING:
                    content.append('Listening to {} on Spotify'.format(
                        user.presence.game.details)
                                   )  #In the embed, details is the songname.
                if user.presence.game.type == ActivityTypes.STREAMING:
                    content.append('Streaming: [{}]({})'.format(
                        user.presence.game.name, user.presence.game.url))

        if user.public_flags:
            badges = ''
            user_badges = list(UserFlags(user.public_flags))
            for badge in user_badges:
                badges += '<{}> '.format(BADGE_EMOJI[badge])

            content.append('Badges: {}'.format(badges))

        if member:
            content.append('\n**\u276F Member Information**')

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

            content.append('Joined: {} ago ({})'.format(
                humanize.naturaldelta(datetime.utcnow() - member.joined_at),
                member.joined_at.strftime("%b %d %Y %H:%M:%S"),
            ))

            if member.roles:
                content.append('Roles: {}'.format(', '.join(
                    ('<@&{}>'.format(member.guild.roles.get(r).id)
                     for r in member.roles))))

        # Execute a bunch of queries
        newest_msg = Message.select(fn.MAX(Message.id)).where(
            (Message.author_id == user.id)
            & (Message.guild_id == event.guild.id)).tuples()[0][0]

        oldest_msg = Message.select(fn.MIN(Message.id)).where(
            (Message.author_id == user.id)
            & (Message.guild_id == event.guild.id)).tuples()[0][0]  #Slow Query

        voice = GuildVoiceSession.select(
            fn.COUNT(GuildVoiceSession.user_id),
            fn.SUM(GuildVoiceSession.ended_at - GuildVoiceSession.started_at)
        ).where((GuildVoiceSession.user_id == user.id)
                & (~(GuildVoiceSession.ended_at >> None))
                & (GuildVoiceSession.guild_id == event.guild.id)).tuples()[0]

        infractions = Infraction.select(Infraction.id).where(
            (Infraction.user_id == user.id)
            & (Infraction.guild_id == event.guild.id)).tuples()

        if newest_msg and oldest_msg:
            content.append('\n **\u276F Activity**')
            content.append('Last Message: {} ({})'.format(
                humanize.naturaltime(datetime.utcnow() -
                                     to_datetime(newest_msg)),
                to_datetime(newest_msg).strftime("%b %d %Y %H:%M:%S"),
            ))
            content.append('First Message: {} ({})'.format(
                humanize.naturaltime(datetime.utcnow() -
                                     to_datetime(oldest_msg)),
                to_datetime(oldest_msg).strftime("%b %d %Y %H:%M:%S"),
            ))

        if len(infractions) > 0:
            content.append('\n**\u276F Infractions**')
            total = len(infractions)
            content.append('Total Infractions: **{:,}**'.format(total))

        if voice[0]:
            content.append('\n**\u276F Voice**')
            content.append('Sessions: `{:,}`'.format(voice[0]))
            content.append('Time: `{}`'.format(
                str(humanize.naturaldelta(voice[1])).title()))

        embed = MessageEmbed()

        try:
            avatar = User.with_id(user.id).get_avatar_url()
        except:
            avatar = user.get_avatar_url(
            )  # This fails if the user has never been seen by speedboat.

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

        embed.set_thumbnail(url=avatar)

        embed.description = '\n'.join(content)
        embed.color = get_dominant_colors_user(user, avatar)
        event.msg.reply('', embed=embed)
Esempio n. 19
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)