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)))
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)
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)
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
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))))
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)
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))
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)
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))
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)
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)
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)
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)
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)
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)
def calc_timediff(): return "Scheduled for {} after trigger, took {}".format( length, (datetime.now() - to_datetime(msg.id)))
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)
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)
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)