async def unmute(self, ctx, member: discord.Member, *, reason=None): """Unmutes a user""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level(ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: await self.bot.unmute(ctx.guild.id, member.id, None, reason=reason) await ctx.send(self.bot.accept)
async def add(self, ctx: commands.Context, member: MemberOrID, *, note): """Add a note""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: guild_data = await self.bot.db.get_guild_config(ctx.guild.id) notes = guild_data.notes guild_config = await self.bot.db.get_guild_config(ctx.guild.id) current_date = ( ctx.message.created_at + timedelta(hours=guild_config.time_offset)).strftime('%Y-%m-%d') if len(notes) == 0: case_number = 1 else: case_number = notes[-1]['case_number'] + 1 push = { 'case_number': case_number, 'date': current_date, 'member_id': str(member.id), 'moderator_id': str(ctx.author.id), 'note': note } await self.bot.db.update_guild_config(ctx.guild.id, {'$push': { 'notes': push }}) await ctx.send(self.bot.accept)
async def mute(self, ctx, member: discord.Member, duration: int=None, *, reason=None): """Mutes a user""" if get_perm_level(member, await ctx.guild_info()) >= get_perm_level(ctx.author, await ctx.guild_info()): await ctx.send('User has insufficient permissions') else: await self.bot.mute(member, duration, reason=reason) await ctx.send(self.bot.accept)
async def mute( self, ctx: commands.Context, member: discord.Member, *, time: UserFriendlyTime(default='No reason', assume_reason=True) = None ) -> None: """Mutes a user""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: duration = None reason = None if not time: duration = None else: if time.dt: duration = time.dt - ctx.message.created_at if time.arg: reason = time.arg await self.bot.mute(member, duration, reason=reason) await ctx.send(self.bot.accept)
async def add(self, ctx, member: MemberOrID, *, note): """Add a note""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level( ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: notes = await self.bot.mongo.rainbot.guilds.find_one( {'guild_id': str(ctx.guild.id)}) or {} guild_notes = notes.get('notes', []) notes = list( filter(lambda w: w['member_id'] == str(member.id), guild_notes)) offset = (await ctx.guild_config()).get('time_offset', 0) current_date = (ctx.message.created_at + timedelta(hours=offset)).strftime('%Y-%m-%d') if len(guild_notes) == 0: case_number = 1 else: case_number = guild_notes[-1]['case_number'] + 1 push = { 'case_number': case_number, 'date': current_date, 'member_id': str(member.id), 'moderator_id': str(ctx.author.id), 'note': note } await self.bot.mongo.rainbot.guilds.find_one_and_update( {'guild_id': str(ctx.guild.id)}, {'$push': { 'notes': push }}, upsert=True) await ctx.send(self.bot.accept)
async def kick(self, ctx, member: discord.Member, *, reason=None): """Kicks a user""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level(ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: await member.kick(reason=reason) await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason)
async def ban(self, ctx, member: MemberOrID, *, reason=None): """Swings the banhammer""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level(ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: await ctx.guild.ban(member, reason=reason) await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason)
async def softban(self, ctx, member: discord.Member, *, reason=None): """Swings the banhammer""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level(ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: await member.ban(reason=reason) await asyncio.sleep(2) await member.unban(reason=reason) await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason)
async def softban(self, ctx, member: discord.Member, *, reason=None): """Bans then immediately unbans user (to purge messages)""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: await member.ban(reason=reason) await asyncio.sleep(2) await member.unban(reason=reason) await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason)
async def unmute(self, ctx: commands.Context, member: discord.Member, *, reason: str = 'No reason') -> None: """Unmutes a user""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: await self.bot.unmute(ctx.guild.id, member.id, None, reason=reason) await ctx.send(self.bot.accept)
async def on_message(self, m): if not m.guild or m.type != discord.MessageType.default or m.author.bot: return guild_config = await self.bot.mongo.config.guilds.find_one( {'guild_id': str(m.guild.id)}) or {} if get_perm_level(m.author, guild_config)[0] >= 5: return guild_config = guild_config.get('detections', {}) filtered_words = { i: i in m.content.lower() for i in guild_config.get('filters', []) } invite_links = ['discord.gg/', 'discordapp.com/invite/', 'discord.io/'] links = {i: i in m.content for i in invite_links} mentions = [] for i in m.mentions: if i not in mentions and i != m.author: # and not i.bot: mentions.append(i) if guild_config.get('mention_limit') and len( mentions) >= guild_config.get('mention_limit'): await m.delete() await self.bot.mute(m.author, 60 * 10, reason=f'Mass mentions ({len(m.mentions)})') elif any(filtered_words.values()): await m.delete() await self.bot.mute( m.author, 60 * 10, reason= f'Use of filtered words ({", ".join(i for i in filtered_words.keys() if filtered_words[i])})' ) elif guild_config.get('block_invite') and any(links.values()): await m.delete() await self.bot.mute( m.author, 60 * 10, reason= f'Advertising discord server ({len([i for i in links.keys() if links[i]])})' ) elif guild_config.get('spam_detection') and self.messages.get( str(m.author.id), 0) >= guild_config.get('spam_detection'): await m.delete() await self.bot.mute( m.author, 60 * 10, reason= f'Exceeding spam detection ({guild_config.get("spam_detection")} messages/5s)' ) self.messages[str(m.author.id)] += 1 await asyncio.sleep(5) self.messages[str(m.author.id)] -= 1
async def kick(self, ctx: commands.Context, member: discord.Member, *, reason: str = None) -> None: """Kicks a user""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: await member.kick(reason=reason) if ctx.author != ctx.guild.me: await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason)
async def on_message(self, m): if not m.guild or m.type != discord.MessageType.default or m.author.bot or self.bot.dev_mode: return guild_config = await self.bot.mongo.config.guilds.find_one({'guild_id': str(m.guild.id)}) or {} if get_perm_level(m.author, guild_config)[0] >= 5: return detection_config = guild_config.get('detections', {}) filtered_words = {i: i in m.content.lower() for i in detection_config.get('filters', [])} invite_regex = r'((http(s|):\/\/|)(discord)(\.(gg|io|me)\/|app\.com\/invite\/)([0-z]+))' invite_match = re.findall(invite_regex, m.content) mentions = [] for i in m.mentions: if i not in mentions and i != m.author: # and not i.bot: mentions.append(i) if detection_config.get('mention_limit') and len(mentions) >= detection_config.get('mention_limit'): await m.delete() await self.bot.mute(m.author, 60 * 10, reason=f'Mass mentions ({len(m.mentions)})') elif any(filtered_words.values()): await m.delete() elif detection_config.get('block_invite') and invite_match is not None: for i in invite_match: try: invite = await self.bot.get_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.get('whitelisted_guilds', [])): await m.delete() await self.bot.mute(m.author, 60 * 10, reason=f'Advertising discord server (<{invite.url}>)') elif detection_config.get('spam_detection') and len(self.messages.get(str(m.author.id), [])) >= detection_config.get('spam_detection'): await m.delete() for i in self.messages[str(m.author.id)]: try: msg = await m.channel.get_message(i) await msg.delete() except discord.NotFound: pass await self.bot.mute(m.author, 60 * 10, reason=f'Exceeding spam detection ({detection_config.get("spam_detection")} messages/5s)') self.messages[str(m.author.id)].append(m.id) await asyncio.sleep(5) self.messages[str(m.author.id)].remove(m.id)
async def mylevel(self, ctx): """Checks your permission level""" perm_level = get_perm_level(ctx.author, await ctx.guild_config()) await ctx.send(f'You are on level {perm_level[0]} ({perm_level[1]})')
async def on_message(self, m): if not m.guild or m.type != discord.MessageType.default or m.author.bot or self.bot.dev_mode: return guild_config = await self.bot.mongo.rainbot.guilds.find_one( {'guild_id': str(m.guild.id)}) or {} if get_perm_level(m.author, guild_config)[0] >= 5: return detection_config = guild_config.get('detections', {}) filtered_words = [ i for i in detection_config.get('filters', []) if i in m.content.lower() ] invite_match = self.INVITE_REGEX.findall(m.content) mentions = [] for i in m.mentions: if i not in mentions and i != m.author and not i.bot: mentions.append(i) warn_cmd = self.bot.get_command('warn add') ctx = await self.bot.get_context(m, cls=RainContext) ctx.author = m.guild.me ctx.command = warn_cmd if detection_config.get('mention_limit') and len( mentions) >= detection_config.get('mention_limit'): await m.delete() await ctx.invoke(warn_cmd, m.author, reason=f'Mass mentions ({len(m.mentions)})') await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Mass mentions ({len(m.mentions)})') elif len(filtered_words) != 0: await m.delete() elif detection_config.get('block_invite') and invite_match: for i in invite_match: try: invite = await self.bot.fetch_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.get( 'whitelisted_guilds', [])): await m.delete() await ctx.invoke( warn_cmd, m.author, reason= f'Advertising discord server (<{invite.url}>)') await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Advertising discord server (<{invite.url}>)') elif detection_config.get('spam_detection') and len( self.spam_detection.get( str(m.author.id), [])) >= detection_config.get('spam_detection'): await ctx.invoke( warn_cmd, m.author, reason= f'Exceeding spam detection ({detection_config.get("spam_detection")} messages/5s)' ) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Exceeding spam detection ({detection_config.get("spam_detection")} messages/5s)' ) await m.delete() for i in self.spam_detection[str(m.author.id)]: try: msg = await m.channel.fetch_message(i) await msg.delete() except discord.NotFound: pass elif detection_config.get( 'repetitive_message') and self.get_most_common_count( m.author.id) >= detection_config.get("repetitive_message"): await ctx.invoke( warn_cmd, m.author, reason= f'Repetitive message detection ({detection_config.get("repetitive_message")} identical messages/1m)' ) await ctx.invoke(self.bot.get_command('purge'), limit=self.get_most_common_count(m.author.id), member=m.author) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Repetitive message detection ({detection_config.get("repetitive_message")} identical messages/1m)' ) self.spam_detection[str(m.author.id)].append(m.id) await asyncio.sleep(5) self.spam_detection[str(m.author.id)].remove(m.id) if not self.spam_detection[str(m.author.id)]: del self.spam_detection[str(m.author.id)] self.repetitive_message[str(m.author.id)][m.content] += 1 await asyncio.sleep(60) self.repetitive_message[str(m.author.id)][m.content] -= 1 if not self.repetitive_message[str(m.author.id)].values(): del self.repetitive_message[str(m.author.id)]
async def add_(self, ctx: commands.Context, member: MemberOrID, *, reason: str) -> None: """Warn a user Can also be used as `warn <member> [reason]`""" if get_perm_level(member, await self.bot.db.get_guild_config( ctx.guild.id))[0] >= get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id ))[0]: await ctx.send('User has insufficient permissions') else: guild_config = await self.bot.db.get_guild_config(ctx.guild.id) guild_warns = guild_config.warns warn_punishments = guild_config.warn_punishments warn_punishment_limits = [i.warn_number for i in warn_punishments] warns = list( filter(lambda w: w['member_id'] == str(member.id), guild_warns)) cmd = None punish = False num_warns = len(warns) + 1 fmt = f'You have been warned in **{ctx.guild.name}**, reason: {reason}. This is warning #{num_warns}.' if warn_punishments: punishments = list( filter(lambda x: int(x) == num_warns, warn_punishment_limits)) if not punishments: punish = False above = list( filter(lambda x: int(x) > num_warns, warn_punishment_limits)) if above: closest = min(map(int, above)) cmd = warn_punishments.get_kv('warn_number', closest).punishment if cmd == 'ban': cmd = 'bann' fmt += f' You will be {cmd}ed on warning {closest}.' else: punish = True cmd = warn_punishments.get_kv( 'warn_number', max(map(int, punishments))).punishment if cmd == 'ban': cmd = 'bann' fmt += f' You have been {cmd}ed from the server.' try: await member.send(fmt) except discord.Forbidden: if ctx.author != ctx.guild.me: await ctx.send( 'The user has PMs disabled or blocked the bot.') finally: guild_config = await self.bot.db.get_guild_config(ctx.guild.id) current_date = (ctx.message.created_at + timedelta( hours=guild_config.time_offset)).strftime('%Y-%m-%d') if len(guild_warns) == 0: case_number = 1 else: case_number = guild_warns[-1]['case_number'] + 1 push = { 'case_number': case_number, 'date': current_date, 'member_id': str(member.id), 'moderator_id': str(ctx.author.id), 'reason': reason } await self.bot.db.update_guild_config( ctx.guild.id, {'$push': { 'warns': push }}) if ctx.author != ctx.guild.me: await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason, case_number) # apply punishment if punish: if cmd == 'bann': cmd = 'ban' ctx.command = self.bot.get_command(cmd) ctx.author = ctx.guild.me await ctx.invoke(ctx.command, member, reason=f'Hit warn limit {num_warns}')
async def add_(self, ctx, member: MemberOrID, *, reason): """Warn a user""" if get_perm_level(member, await ctx.guild_config())[0] >= get_perm_level( ctx.author, await ctx.guild_config())[0]: await ctx.send('User has insufficient permissions') else: guild_info = await self.bot.mongo.rainbot.guilds.find_one( {'guild_id': str(ctx.guild.id)}) or {} guild_warns = guild_info.get('warns', []) warn_punishments = guild_info.get('warn_punishments', {}) warns = list( filter(lambda w: w['member_id'] == str(member.id), guild_warns)) cmd = None punish = False try: num_warns = len(warns) + 1 fmt = f'You have been warned in **{ctx.guild.name}**, reason: {reason}. This is warning #{num_warns}.' if warn_punishments: punishments = list( filter(lambda x: int(x) == num_warns, warn_punishments.keys())) if not punishments: punish = False above = list( filter(lambda x: int(x) < num_warns, warn_punishments.keys())) if above: punish = True closest = max(map(int, above)) cmd = warn_punishments[str(closest)] if cmd == 'ban': cmd = 'bann' fmt += f' You will be {cmd}ed on warning {closest}.' else: punish = True cmd = warn_punishments[str(max(map(int, punishments)))] fmt += f' You have been {cmd}ed from the server.' await member.send(fmt) except discord.Forbidden: if ctx.author != ctx.guild.me: await ctx.send( 'The user has PMs disabled or blocked the bot.') finally: offset = (await ctx.guild_config()).get('time_offset', 0) current_date = (ctx.message.created_at + timedelta(hours=offset)).strftime('%Y-%m-%d') if len(guild_warns) == 0: case_number = 1 else: case_number = guild_warns[-1]['case_number'] + 1 push = { 'case_number': case_number, 'date': current_date, 'member_id': str(member.id), 'moderator_id': str(ctx.author.id), 'reason': reason } await self.bot.mongo.rainbot.guilds.find_one_and_update( {'guild_id': str(ctx.guild.id)}, {'$push': { 'warns': push }}, upsert=True) if ctx.author != ctx.guild.me: await ctx.send(self.bot.accept) await self.send_log(ctx, member, reason) # apply punishment if punish: if cmd == 'bann': cmd = 'ban' ctx.command = self.bot.get_command(cmd) ctx.author = ctx.guild.me await ctx.invoke(ctx.command, member, reason=f'Exceeded warn limit {num_warns}')
async def mylevel(self, ctx: commands.Context) -> None: """Checks your permission level""" perm_level = get_perm_level( ctx.author, await self.bot.db.get_guild_config(ctx.guild.id)) await ctx.send(f'You are on level {perm_level[0]} ({perm_level[1]})')
async def on_message(self, m): if not m.guild or m.type != discord.MessageType.default or m.author.bot or self.bot.dev_mode: return guild_config = await self.bot.db.get_guild_config(m.guild.id) if get_perm_level(m.author, guild_config)[0] >= 5: return detection_config = guild_config.detections ignored_channels = guild_config.ignored_channels filtered_words = [ i for i in detection_config.filters if i in m.content.lower() ] invite_match = self.INVITE_REGEX.findall(m.content) english_text = ''.join(self.ENGLISH_REGEX.findall(m.content)) mentions = [] for i in m.mentions: if i not in mentions and i != m.author and not i.bot: mentions.append(i) warn_cmd = self.bot.get_command('warn add') ctx = await self.bot.get_context(m) ctx.author = m.guild.me ctx.command = warn_cmd # images if guild_config.detections.sexually_explicit: for i in m.attachments: if i.filename.endswith('.png') or i.filename.endswith( '.jpg') or i.filename.endswith('.jpeg'): with NamedTemporaryFile(mode='wb+', delete=False) as fp: async with self.bot.session.get(i.url) as resp: fp.write(await resp.read()) await self.bot.loop.run_in_executor( None, functools.partial(self.get_nudenet_classifications, m, fp.name)) if detection_config.mention_limit and len( mentions) >= detection_config.mention_limit and str( m.channel.id) not in ignored_channels.mention_limit: await m.delete() await ctx.invoke(warn_cmd, m.author, reason=f'Mass mentions ({len(m.mentions)})') await self.bot.mute(m.author, timedelta(minutes=10), reason=f'Mass mentions ({len(m.mentions)})') elif len(filtered_words) != 0 and str( m.channel.id) not in ignored_channels.filter: await m.delete() elif detection_config.block_invite and invite_match and str( m.channel.id) not in ignored_channels.block_invite: for i in invite_match: try: invite = await self.bot.fetch_invite(i[-1]) except discord.NotFound: pass else: if not (invite.guild.id == m.guild.id or str(invite.guild.id) in guild_config.whitelisted_guilds): await m.delete() await ctx.invoke( warn_cmd, m.author, reason= f'Advertising discord server (<{invite.url}>)') await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Advertising discord server (<{invite.url}>)') elif detection_config.english_only and english_text != m.content and str( m.channel.id) not in ignored_channels.english_only: await m.delete() elif detection_config.spam_detection and len( self.spam_detection.get( str(m.author.id), [])) >= detection_config.spam_detection and str( m.channel.id) not in ignored_channels.spam_detection: await ctx.invoke( warn_cmd, m.author, reason= f'Exceeding spam detection ({detection_config.spam_detection} messages/5s)' ) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Exceeding spam detection ({detection_config.spam_detection} messages/5s)' ) await m.delete() for i in self.spam_detection[str(m.author.id)]: try: msg = await m.channel.fetch_message(i) await msg.delete() except discord.NotFound: pass elif detection_config.repetitive_message and self.get_most_common_count( m.author.id) >= detection_config.repetitive_message and str( m.channel.id) not in ignored_channels.repetitive_message: await ctx.invoke( warn_cmd, m.author, reason= f'Repetitive message detection ({detection_config.repetitive_message} identical messages/1m)' ) await ctx.invoke(self.bot.get_command('purge'), limit=self.get_most_common_count(m.author.id), member=m.author) await self.bot.mute( m.author, timedelta(minutes=10), reason= f'Repetitive message detection ({detection_config.repetitive_message} identical messages/1m)' ) if str(m.channel.id) not in ignored_channels.spam_detection: self.spam_detection[str(m.author.id)].append(m.id) await asyncio.sleep(5) self.spam_detection[str(m.author.id)].remove(m.id) if not self.spam_detection[str(m.author.id)]: del self.spam_detection[str(m.author.id)] if str(m.channel.id) not in ignored_channels.repetitive_message: self.repetitive_message[str(m.author.id)][m.content] += 1 await asyncio.sleep(60) self.repetitive_message[str(m.author.id)][m.content] -= 1 if not self.repetitive_message[str(m.author.id)].values(): del self.repetitive_message[str(m.author.id)]