def dash_index(): if g.user: if g.user.admin: stats = json.loads(rdb.get('web:dashboard:stats') or '{}') if not stats or 'refresh' in request.args: stats['messages'] = pretty_number(Message.select().count()) stats['guilds'] = pretty_number(Guild.select().count()) stats['users'] = pretty_number(User.select().count()) stats['channels'] = pretty_number(Channel.select().count()) rdb.setex('web:dashboard:stats', json.dumps(stats), 300) guilds = Guild.select().order_by(Guild.guild_id) else: stats = {} guilds = Guild.select( Guild, Guild.config['web'][str(g.user.user_id)].alias('role') ).where( (Guild.enabled == 1) & (~(Guild.config['web'][str(g.user.user_id)] >> None)) ) return render_template( 'dashboard.html', stats=stats, guilds=guilds, ) return render_template('login.html')
def violate(self, violation): key = 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event) last_violated = int(rdb.get(key) or 0) rdb.setex( 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event), int(time.time()), 60) if not last_violated > time.time() - 10: self.call('ModLogPlugin.log_action_ext', Actions.SPAM, violation.event.guild.id, v=violation) punishment = violation.check.punishment or violation.rule.punishment punishment_duration = violation.check.punishment_duration or violation.rule.punishment_duration if punishment == PunishmentType.MUTE: Infraction.mute( self, violation.event, violation.member, 'Spam Detected', ) elif punishment == PunishmentType.TEMPMUTE: Infraction.tempmute( self, violation.event, violation.member, 'Spam Detected', datetime.utcnow() + timedelta(seconds=punishment_duration)) elif punishment == PunishmentType.KICK: Infraction.kick(self, violation.event, violation.member, 'Spam Detected') elif punishment == PunishmentType.TEMPBAN: Infraction.tempban( self, violation.event, violation.member, 'Spam Detected', datetime.utcnow() + timedelta(seconds=punishment_duration)) elif punishment == PunishmentType.BAN: Infraction.ban(self, violation.event, violation.member, 'Spam Detected', violation.event.guild) # Clean messages if requested if punishment != PunishmentType.NONE and violation.rule.clean: msgs = Message.select(Message.id, Message.channel_id).where( (Message.guild_id == violation.event.guild.id) & (Message.author_id == violation.member.id) & (Message.timestamp > (datetime.utcnow() - timedelta( seconds=violation.rule.clean_duration)))).limit( violation.rule.clean_count).tuples() channels = defaultdict(list) for mid, chan in msgs: channels[chan].append(mid) for channel, messages in list(channels.items()): channel = self.state.channels.get(channel) if not channel: continue channel.delete_messages(messages)
def stats(): stats = json.loads(rdb.get('web:dashboard:stats') or '{}') if not stats or 'refresh' in request.args: # stats['messages'] = pretty_number(Message.select().count()) # stats['guilds'] = pretty_number(Guild.select().count()) # stats['users'] = pretty_number(User.select().count()) # stats['channels'] = pretty_number(Channel.select().count()) stats['messages'] = Message.select().count() stats['guilds'] = Guild.select().count() stats['users'] = User.select().count() stats['channels'] = Channel.select().count() rdb.setex('web:dashboard:stats', json.dumps(stats), 300) return jsonify(stats)
def get_invite_info(self, code): if rdb.exists('inv:{}'.format(code)): return json.loads(rdb.get('inv:{}'.format(code))) try: obj = self.client.api.invites_get(code) except: return obj = { 'id': obj.guild.id, 'name': obj.guild.name, 'icon': obj.guild.icon } # Cache for 12 hours rdb.setex('inv:{}'.format(code), json.dumps(obj), 43200) return obj
def check_streams(self): # TODO: batch this at some point guild_streams = [TWITCH_STREAMS_GUILD_KEY.format(i) for i in self.state.guilds.keys()] if not guild_streams: return streams = rdb.sunion(*guild_streams) if not streams: self.log.info('no streams to update') return mapping = {k: v for k, v in self.get_userid_for_usernames(streams).items() if v} self.log.info('Syncing stream infromation for: %s', mapping) to_check = mapping.values() with rdb.pipeline() as pipe: for channel_id in to_check: pipe.exists(TWITCH_STREAM_BACKOFF.format(channel_id)) result = pipe.execute() to_check = [ channel_id for idx, channel_id in enumerate(to_check) if not result[idx] ] statuses = self.get_channel_statuses(to_check) for channel_id, stream in statuses.iteritems(): if not stream: continue rdb.setex(TWITCH_STREAM_BACKOFF.format(channel_id), 1, STREAM_BACKOFF_DURATION) old_state = self.get_stream_state(channel_id) new_state = self.prepare_state(stream) if stream else None self.on_stream_update(channel_id, old_state, new_state) continue
def get_invite_info(self, code): if rdb.exists('inv:{}'.format(code)): return json.loads(rdb.get('inv:{}'.format(code))) try: obj = self.client.api.invites_get(code) except: return if obj.channel and obj.channel.type == ChannelType.GROUP_DM: obj = { 'id': obj.channel.id, 'name': obj.channel.name } else: obj = { 'id': obj.guild.id, 'name': obj.guild.name, 'icon': obj.guild.icon } # Cache for 12 hours rdb.setex('inv:{}'.format(code), 43200, json.dumps(obj)) return obj
def violate(self, violation): key = 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event) last_violated = int(rdb.get(key) or 0) rdb.setex( 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event), int(time.time()), 60) if not last_violated > time.time() - 10: self.bot.plugins.get('ModLogPlugin').log_action_ext( Actions.SPAM_DEBUG, violation.event, v=violation) with self.bot.plugins.get( 'CorePlugin').send_control_message() as embed: embed.title = '{} Violated'.format(violation.label) embed.color = 0xfdfd96 embed.description = violation.msg embed.add_field(name='Guild', value=violation.event.guild.name, inline=True) embed.add_field(name='Guild ID', value=violation.event.guild.id, inline=True) embed.add_field(name=ZERO_WIDTH_SPACE, value=ZERO_WIDTH_SPACE, inline=True) embed.add_field(name='User', value=unicode(violation.member), inline=True) embed.add_field(name='User ID', value=violation.event.member.id, inline=True) embed.add_field(name=ZERO_WIDTH_SPACE, value=ZERO_WIDTH_SPACE, inline=True) punishment = violation.check.punishment or violation.rule.punishment punishment_duration = violation.check.punishment_duration or violation.rule.punishment_duration if punishment == PunishmentType.MUTE: Infraction.mute(self, violation.event, violation.member, 'Spam Detected') elif punishment == PunishmentType.TEMPMUTE: Infraction.tempmute( self, violation.event, violation.member, 'Spam Detected', datetime.utcnow() + timedelta(seconds=punishment_duration)) elif punishment == PunishmentType.KICK: Infraction.kick(self, violation.event, violation.member, 'Spam Detected') elif punishment == PunishmentType.TEMPBAN: Infraction.tempban( self, violation.event, violation.member, 'Spam Detected', datetime.utcnow() + timedelta(seconds=punishment_duration)) elif punishment == PunishmentType.BAN: Infraction.ban(self, violation.event, violation.member, 'Spam Detected', violation.event.guild) # Clean messages if requested if punishment != PunishmentType.NONE and violation.rule.clean: msgs = Message.select(Message.id, Message.channel_id).where( (Message.guild_id == violation.event.guild.id) & (Message.author_id == violation.member.id) & (Message.timestamp > (datetime.utcnow() - timedelta( seconds=violation.rule.clean_duration)))).limit( violation.rule.clean_count).tuples() channels = defaultdict(list) for mid, chan in msgs: channels[chan].append(mid) for channel, messages in channels.items(): channel = self.state.channels.get(channel) if not channel: continue channel.delete_messages(messages)
def violate(self, violation): key = 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event) last_violated = int(rdb.get(key) or 0) rdb.setex( 'lv:{e.member.guild_id}:{e.member.id}'.format(e=violation.event), int(time.time()), 60) if not last_violated > time.time() - 10: self.call('ModLogPlugin.log_action_ext', Actions.SPAM_DEBUG, violation.event.guild.id, v=violation) with self.bot.plugins.get( 'CorePlugin').send_spam_control_message() as embed: embed.title = '{} Violated'.format(violation.label) embed.color = 0xfdfd96 embed.description = violation.msg embed.add_field(name='Guild', value=violation.event.guild.name, inline=True) embed.add_field(name='Guild ID', value=violation.event.guild.id, inline=True) embed.add_field(name=ZERO_WIDTH_SPACE, value=ZERO_WIDTH_SPACE, inline=True) embed.add_field(name='User', value=unicode(violation.member), inline=True) embed.add_field(name='User ID', value=violation.event.member.id, inline=True) embed.add_field(name=ZERO_WIDTH_SPACE, value=ZERO_WIDTH_SPACE, inline=True) punishment = violation.check.punishment or violation.rule.punishment punishment_duration = violation.check.punishment_duration or violation.rule.punishment_duration if punishment == PunishmentType.MUTE: if violation.rule.punishment_dms: try: infractions, embed = infraction_message( violation.event, violation.member.id, 'mute', violation.event.guild.name, str(self.state.me), 'Spam Detected', auto=True) dm = self.client.api.users_me_dms_create( violation.member.id) dm.send_message('You\'ve been {} in **{}**.'.format( 'muted', violation.event.guild.name), embed=embed) except APIException: pass Infraction.mute(self, violation.event, violation.member, 'Spam Detected') elif punishment == PunishmentType.TEMPMUTE: expiration_date = datetime.utcnow() + timedelta( seconds=punishment_duration) if violation.rule.punishment_dms: try: infractions, embed = infraction_message( violation.event, violation.member.id, 'tempmute', violation.event.guild.name, str(self.state.me), 'Spam Detected', expires=expiration_date, auto=True) dm = self.client.api.users_me_dms_create( violation.member.id) dm.send_message('You\'ve been {} in **{}**.'.format( 'temporarily muted', violation.event.guild.name), embed=embed) except APIException: pass Infraction.tempmute(self, violation.event, violation.member, 'Spam Detected', expiration_date) elif punishment == PunishmentType.KICK: if violation.rule.punishment_dms: try: infractions, embed = infraction_message( violation.event, violation.member.id, 'kick', violation.event.guild.name, str(self.state.me), 'Spam Detected', auto=True) dm = self.client.api.users_me_dms_create( violation.member.id) dm.send_message('You\'ve been {} from **{}**.'.format( 'kicked', violation.event.guild.name), embed=embed) except APIException: pass Infraction.kick(self, violation.event, violation.member, 'Spam Detected') elif punishment == PunishmentType.TEMPBAN: expiration_date = datetime.utcnow() + timedelta( seconds=punishment_duration) if violation.rule.punishment_dms: try: infractions, embed = infraction_message( violation.event, violation.member.id, 'tempban', violation.event.guild.name, str(self.state.me), 'Spam Detected', expires=expiration_date, auto=True) dm = self.client.api.users_me_dms_create( violation.member.id) dm.send_message('You\'ve been {} from **{}**.'.format( 'temporarily banned', violation.event.guild.name), embed=embed) except APIException: pass Infraction.tempban(self, violation.event, violation.member, 'Spam Detected', expiration_date) elif punishment == PunishmentType.BAN: if violation.rule.punishment_dms: try: infractions, embed = infraction_message( violation.event, violation.member.id, 'ban', violation.event.guild.name, str(self.state.me), 'Spam Detected', auto=True) dm = self.client.api.users_me_dms_create( violation.member.id) dm.send_message('You\'ve been {} from **{}**.'.format( 'banned', violation.event.guild.name), embed=embed) except APIException: pass Infraction.ban(self, violation.event, violation.member, 'Spam Detected', violation.event.guild) # Clean messages if requested if punishment != PunishmentType.NONE and violation.rule.clean: msgs = Message.select(Message.id, Message.channel_id).where( (Message.guild_id == violation.event.guild.id) & (Message.author_id == violation.member.id) & (Message.timestamp > (datetime.utcnow() - timedelta( seconds=violation.rule.clean_duration)))).limit( violation.rule.clean_count).tuples() channels = defaultdict(list) for mid, chan in msgs: channels[chan].append(mid) for channel, messages in channels.items(): channel = self.state.channels.get(channel) if not channel: continue channel.delete_messages(messages)
def guild_stats_self(guild): def serialize_user(gcc): for i in gcc: user_raw = ''' SELECT username, discriminator FROM users WHERE user_id=%s AND bot=false; ''' user = list(User.raw(user_raw, i[1]).tuples()) if user: return { 'user': { 'username': user[0][0], 'discrim': str(user[0][1]), 'id': i[1] }, 'user_count': int(i[0]), } return { 'user': '******', 'user_count': 0, } def serialize_emoji(gcc): for i in gcc: emoji_raw = ''' SELECT emoji_id FROM guild_emojis WHERE emoji_id=%s AND guild_id=%s; ''' emoji = list( GuildEmoji.raw(emoji_raw, i[0], guild.guild_id).tuples()) if emoji: return str(emoji[0][0]) return '230870076126003200' data = json.loads( rdb.get('web:guild:{}:stats'.format(guild.guild_id)) or '{}') if not data: # Totals totals_messages = Message.select(Message.id).where( (Message.guild_id == guild.guild_id)).count() totals_infractions = Infraction.select(Infraction.id).where( (Infraction.guild_id == guild.guild_id)).count() # Peaks ## Messages peaks_messages_raw = ''' SELECT count(id), author_id FROM messages WHERE guild_id=%s GROUP BY author_id ORDER BY count DESC LIMIT 5; ''' peaks_messages = list( Message.raw(peaks_messages_raw, guild.guild_id).tuples()) ## Infractions peaks_infractions_raw = ''' SELECT count(id), user_id FROM infractions WHERE guild_id=%s GROUP BY user_id ORDER BY count DESC LIMIT 5; ''' peaks_infractions = list( Infraction.raw(peaks_infractions_raw, guild.guild_id).tuples()) ## Emoji peaks_emoji_raw = ''' SELECT id, count(*) FROM ( SELECT unnest(emojis) as id FROM messages WHERE guild_id=%s and cardinality(emojis) > 0 ) q GROUP BY 1 ORDER BY 2 DESC LIMIT 5 ''' peaks_emoji = list( Message.raw(peaks_emoji_raw, guild.guild_id).tuples()) ## Command peaks_command_raw = ''' SELECT count(c.command), c.command FROM commands c INNER JOIN messages m ON (c.message_id = m.id) WHERE m.guild_id=%s GROUP BY 2 ORDER BY 1 DESC LIMIT 1; ''' peaks_command = list( Command.raw(peaks_command_raw, guild.guild_id).tuples()) if totals_messages: totals_messages = totals_messages else: totals_messages = 0 if totals_infractions: totals_infractions = totals_infractions else: totals_infractions = 0 if peaks_messages: pm = serialize_user(peaks_messages) else: pm = { 'user': '******', 'user_count': 0, } if peaks_infractions: pi = serialize_user(peaks_infractions) else: pi = { 'user': '******', 'user_count': 0, } if peaks_emoji: anim = False peaks_emoji_id = serialize_emoji(peaks_emoji) url = 'https://discordapp.com/api/emojis/{}.gif'.format( peaks_emoji_id) r = requests.get(url) try: r.raise_for_status() anim = True except requests.HTTPError: pass if anim: peaks_emoji_ext = 'gif' else: peaks_emoji_ext = 'png' else: peaks_emoji_id = '230870076126003200' peaks_emoji_ext = 'png' if peaks_command: peaks_command = '{1}'.format(*peaks_command[0]) else: peaks_command = 'N/A' data = { 'totals': { 'messages': totals_messages, 'infractions': totals_infractions, }, 'peaks': { 'messages': pm, 'infractions': pi, 'emoji': { 'id': peaks_emoji_id, 'ext': peaks_emoji_ext, }, 'command': peaks_command, }, } rdb.setex('web:guild:{}:stats'.format(guild.guild_id), json.dumps(data), 600) return jsonify(data)