async def chat_purgeuser(self, ctx, user: discord.Member, count: int): await ctx.message.delete() if not perms.check_command_priv("purgeuser", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **purgeuser** command." )) return if count > 100: await ctx.send(embed=interface.error_message( "Error", f"The **purgeuser** command can only delete up to 100 messages at a time. " "Messages older than 14 days cannot be deleted.", )) return msg_queue = list() async for msg in ctx.message.channel.history(): if msg.author == user: msg_queue.append(msg) if len(msg_queue) == count or len(msg_queue) == 100: break await ctx.message.channel.delete_messages(msg_queue) await ctx.send(embed=interface.success_message( "Purge", f"Purged {user}'s last {len(msg_queue)} message(s) from {ctx.message.channel}." ))
async def mod_warn(self, ctx, user: discord.Member, *, reason: str): """ Warn a user and record the warning in the log. <user> must be a Discord tag, ID number, or mention. <message> can be anything. """ await ctx.message.delete() if not perms.check_command_priv("warn", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **warn** command." )) return try: db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "warn", reason) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the warning you just attempted to issue.", )) else: await ctx.send(embed=interface.error_message( "Warning", f"{user.mention} has received a warning:\n\n**{reason}**", f"User ID: {user.id}")) await user.send(embed=interface.error_message( f"{ctx.message.guild} - Warning", f"You have received a warning:\n\n**{reason}**"))
async def roles_add_grant(self, ctx, granter: discord.Role, granted: discord.Role): """ Grant a role the ability to add a user to a different role. This allows anyone with the <granter> role to give the <granted> role to someone else. Specify each role by name (case-sensitive) or ID number. If specifying by name, and the name contains a space, enclose that role in quotation marks. """ await ctx.message.delete() if not perms.check_command_priv("addgrant", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **addgrant** command." )) return if db.add_role_granter(granter, granted): await ctx.send(embed=interface.success_message( "Role Grant Addition", f"**{granter}** may now grant the **{granted}** role.")) else: await ctx.send(embed=interface.error_message( "Error", "There was an error adding the grant permission."))
async def mod_unban(self, ctx, user: discord.User, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("unban", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **unban** command." )) return if reason: chanmsg = f"{user.mention} has been unbanned from the server.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been unbanned from the server." try: await ctx.send(embed=interface.success_message( "Unban", chanmsg, f"User ID: {user.id}")) db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "unban", reason) await ctx.author.guild.unban(user, reason=reason) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the unban you just attempted to issue.", ))
async def admin_staff_demote(self, ctx, user: discord.Member): """ Demote a user to the next-lowest staff rank. If the user is already at the lowest staff rank, remove them from staff. <user> must be a Discord tag, ID number, or mention. """ await ctx.message.delete() if not perms.check_command_priv("demote", ctx.message.author.roles): await ctx.send( embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **demote** command." ) ) return cur_level = perms.get_staff_rank(user) staff_roles_list = [ctx.guild.get_role(r) for r in defs.staff_role_ids] new_roles_list = [ctx.guild.get_role(r) for r in defs.staff_role_ids[0 : cur_level - 1]] if len(staff_roles_list) == len(new_roles_list) + 1 and not await self.bot.is_owner(ctx.author): await ctx.send(embed=interface.error_message("Error", "Only the owner can demote from that rank.")) return msg = await ctx.send(embed=interface.working_message("Staff Demotion", f"Demoting **{user}**...")) if cur_level == 1: try: await user.remove_roles(*staff_roles_list, atomic=True) except Exception as e: await msg.edit(embed=interface.error_message("Error", f"Error: {e}")) else: await msg.edit( embed=interface.success_message( "Staff Removal", f"{user.mention} has been removed from staff.", f"User ID: {user.id}" ) ) else: try: await user.remove_roles(*staff_roles_list, atomic=True) await user.add_roles(*new_roles_list, atomic=True) except Exception as e: await msg.edit(embed=interface.error_message("Error", f"Error: {e}")) else: await msg.edit( embed=interface.success_message( "Staff Demotion", "{} has been demoted to **{}**.".format(user.mention, new_roles_list[len(new_roles_list) - 1]), f"User ID: {user.id}", ) )
async def mod_unmute(self, ctx, user: discord.Member, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("unmute", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **unmute** command." )) return if user.id == ctx.message.author.id: await ctx.send(embed=interface.error_message( "Error", f"You can't unmute yourself.")) return if perms.get_staff_rank( ctx.message.author) <= perms.get_staff_rank(user): await ctx.send(embed=interface.error_message( "Error", f"You can't unmute someone of the same staff rank or higher.")) return if defs.mute_role_id not in [r.id for r in user.roles]: await ctx.send(embed=interface.error_message( "Error", f"{user} is not muted.", f"User ID: {user.id}")) return if reason: chanmsg = f"{user.mention} has been unmuted.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been unmuted." try: db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "unmute", reason) await self.do_unmute(db.get_mute_record(user)) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the unmute you just attempted.") ) else: await ctx.send(embed=interface.success_message( "Unmute", chanmsg, f"User ID: {user.id}"))
async def chat_unlock(self, ctx): await ctx.message.delete() if not perms.check_command_priv("unlock", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **unlock** command." )) return if ctx.message.channel.id not in self.lockdowns: await ctx.send(embed=interface.error_message( "Error", f"This channel is already unlocked.")) return await ctx.send(embed=interface.success_message( "Channel Locked", f"This channel is now unlocked.")) self.lockdowns.remove(ctx.message.channel.id)
async def chat_lock(self, ctx): await ctx.message.delete() if not perms.check_command_priv("lock", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **lock** command." )) return if ctx.message.channel.id in self.lockdowns: await ctx.send(embed=interface.error_message( "Error", f"This channel is already locked.")) return await ctx.send(embed=interface.error_message( "Channel Locked", f"This channel is now locked for non-staff members.")) self.lockdowns.append(ctx.message.channel.id)
async def roles_list_role_grants(self, ctx, user: discord.Member = None): await ctx.message.delete() if user is None: user = ctx.message.author else: my_staff_rank = perms.get_staff_rank(ctx.message.author) their_staff_rank = perms.get_staff_rank(user) if their_staff_rank > my_staff_rank: await ctx.send(embed=interface.error_message( "Access Denied", "You cannot check the access of someone of a higher staff rank." )) return giveable_role_ids = dict() for role in user.roles: role_ids = db.get_grantable_roles(role) if role_ids: giveable_role_ids[role.name] = role_ids if giveable_role_ids: giveable_roles = OrderedDict() for rname, rids in giveable_role_ids.items(): giveable_roles[rname] = list( set([ctx.author.guild.get_role(rid).name for rid in rids])) giveable_roles[rname].sort() rolelist = "" for granter, granted in reversed(giveable_roles.items()): rolelist += f"{granter} grants:\n" for rname in granted: rolelist += f":white_small_square: {rname}\n" rolelist += "\n" rolelist = rolelist.strip() await ctx.send(embed=interface.normal_message( "Role Grant List", f"**{user}** can give or take the following roles:\n\n{rolelist}", f"User ID: {user.id}", )) else: await ctx.send(embed=interface.normal_message( "Role Grant List", f"**{user}** cannot give or take any roles.", f"User ID: {user.id}"))
async def command_error(bot, ctx, error): if type(error) is commands.errors.MissingRequiredArgument: cmd = bot.get_command(ctx.message.content.split(" ")[0][1:]) await ctx.send(embed=interface.error_message( "Error", "You left out something that's required for the **{}** command." "\n\n{}\n\n{}".format( cmd.name, defs.cprefix + cmd.name + " " + cmd.signature, cmd.help), )) else: raise Exception(error)
async def cms_unload(self, ctx, cog: str): if cog == "cms": await ctx.send( embed=interface.error_message("Cog Management System", "I can't unload the cog management system.") ) return msg = await ctx.send( embed=interface.working_message("Cog Management System", f"Trying to unload the **{cog}** cog...") ) try: self.bot.unload_extension(f"cogs.{cog}") except Exception as e: await msg.edit( embed=interface.error_message("Cog Management System", f"Unable to unload **{cog}** cog.\nError: {e}") ) print(f"Error while unloading {cog} cog: {e}") else: await msg.edit(embed=interface.success_message("Cog Management System", f"**{cog.title()}** cog unloaded.")) finally: await ctx.message.delete()
async def mod_jail(self, ctx, user: discord.Member, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("jail", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **jail** command." )) return if user.id == ctx.message.author.id: await ctx.send(embed=interface.error_message( "Error", f"You can't jail yourself.")) return if perms.get_staff_rank( ctx.message.author) <= perms.get_staff_rank(user): await ctx.send(embed=interface.error_message( "Error", f"You can't jail someone of the same staff rank or higher.")) return if defs.jail_role_id in [r.id for r in user.roles]: await ctx.send(embed=interface.error_message( "Error", f"{user} is already jailed.", f"User ID: {user.id}")) return if reason: chanmsg = f"{user.mention} has been placed in jail.\n\nReason: **{reason}**" dmmsg = f"You have been placed in jail.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been placed in jail." dmmsg = f"You have been placed in jail." try: db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "jail", reason) db.add_jail(ctx.message.author, user, reason) await user.remove_roles(*user.roles[1:], atomic=True) await user.add_roles(user.guild.get_role(defs.jail_role_id), atomic=True) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the jail you just attempted to issue.", )) else: await ctx.send(embed=interface.error_message( "Jail", chanmsg, f"User ID: {user.id}")) await user.send(embed=interface.error_message( f"{ctx.message.guild} - Jail", dmmsg))
async def roles_take(self, ctx, user: discord.Member, role: discord.Role): await ctx.message.delete() if not perms.check_give_role( ctx.author, role) and not await self.bot.is_owner(ctx.author): await ctx.send(embed=interface.error_message( "Access Denied", f"You cannot take the **{role}** role.")) return if role in [r.name for r in user.roles]: await ctx.send(embed=interface.error_message( "Error", f"**{user}** does not have that role.")) return try: await user.remove_roles(role, atomic=True) except: await ctx.send(embed=interface.error_message( "Error", f"Unable to take **{role}** from **{user}**.")) else: await ctx.send(embed=interface.success_message( "Role Removal", f"Removed **{role}** from **{user.mention}**.", f"User ID: {user.id}"))
async def admin_give_command(self, ctx, role: discord.Role, cmd: str): """ Give a role permission to use a command. """ await ctx.message.delete() cmd = cmd.lower() if db.add_command_priv_role(role, cmd): await ctx.send( embed=interface.success_message( "Grant Command Access", f"**{role}** now has access to the **{cmd}** command." ) ) else: await ctx.send(embed=interface.error_message("Error", "There was an error adding the permission."))
async def chat_purge(self, ctx, count: int): await ctx.message.delete() if not perms.check_command_priv("purge", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **purge** command." )) return del_msgs = await ctx.message.channel.purge(limit=count, bulk=True) await ctx.send(embed=interface.success_message( "Purge", f"Purged last {len(del_msgs)} message(s) from {ctx.message.channel}." ))
async def mod_softban(self, ctx, user: discord.Member, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("softban", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **softban** command." )) return if user.id == ctx.message.author.id: await ctx.send(embed=interface.error_message( "Error", f"You can't softban yourself.")) return if ctx.author.guild.get_member(user.id): if perms.get_staff_rank( ctx.message.author) <= perms.get_staff_rank(user): await ctx.send(embed=interface.error_message( "Error", f"You can't softban someone of the same staff rank or higher." )) return if reason: chanmsg = f"{user.mention} has been softbanned.\n\nReason: **{reason}**" dmmsg = f"You have been softbanned.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been softbanned." dmmsg = f"You have been softbanned." try: await ctx.send(embed=interface.error_message( "Soft Ban", chanmsg, f"User ID: {user.id}")) if ctx.author.guild.get_member(user.id): await user.send(embed=interface.error_message( f"{ctx.message.guild} - Soft Ban", dmmsg)) db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "softban", reason) await ctx.author.guild.ban(user, reason=reason, delete_message_days=7) await ctx.author.guild.unban(user, reason=reason) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the ban you just attempted to issue.", ))
async def admin_take_command(self, ctx, role: discord.Role, cmd: str): """ Revoke a role's ability to use a command. """ await ctx.message.delete() cmd = cmd.lower() if db.del_command_priv_role(role, cmd): await ctx.send( embed=interface.success_message( "Remove Command Access", f"**{role}** no longer has access to the **{cmd}** command." ) ) else: await ctx.send( embed=interface.error_message("Error", "There was an error removing the command from that role.") )
async def cms_reload_all(self, ctx): msg = await ctx.send(embed=interface.working_message("Cog Management System", f"Trying to reload all cogs...")) loaded_extensions = self.bot.extensions try: for extension in loaded_extensions: self.bot.reload_extension(extension) except Exception as e: await msg.edit( embed=interface.error_message( "Cog Management System", f"An error occurred while reloading cogs.\nError: {e}" ) ) print(f"Error while reloading all cogs: {e}") else: await msg.edit(embed=interface.success_message("Cog Management System", f"All cogs reloaded.")) finally: await ctx.message.delete()
async def admin_list_commands(self, ctx, user: discord.Member = None): """ List the commands that you have access to. Alternatively, list the commands that someone else has access to. """ await ctx.message.delete() if user is None: user = ctx.message.author else: my_staff_rank = perms.get_staff_rank(ctx.message.author) their_staff_rank = perms.get_staff_rank(user) if their_staff_rank > my_staff_rank: await ctx.send( embed=interface.error_message( "Error", "You cannot check the access of someone of a higher staff rank." ) ) return granted_cmds = OrderedDict() for role in user.roles: role_cmds = db.get_command_priv_cmds(role) if not role_cmds: continue granted_cmds[role.name] = role_cmds granted_cmds[role.name].sort() if not granted_cmds: await ctx.send( embed=interface.normal_message( "Command Access", f"**{user}** cannot use any commands.", f"User ID: {user.id}" ) ) return cmdlist = "" for rname, cmds in reversed(granted_cmds.items()): cmdlist += f"{rname} grants:\n" for cmd in cmds: cmdlist += f":white_small_square: {cmd} " cmdlist += "\n" cmdlist = cmdlist.strip() await ctx.send( embed=interface.normal_message( "Command Access", f"**{user}** can use the following commands:\n\n{cmdlist}", f"User ID: {user.id}", ) )
async def mod_mute(self, ctx, user: discord.Member, duration: str, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("mute", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **mute** command." )) return if user.id == ctx.message.author.id: await ctx.send(embed=interface.error_message( "Error", f"You can't mute yourself.")) return if perms.get_staff_rank( ctx.message.author) <= perms.get_staff_rank(user): await ctx.send(embed=interface.error_message( "Error", f"You can't mute someone of the same staff rank or higher.")) return if defs.mute_role_id in [r.id for r in user.roles]: await ctx.send(embed=interface.error_message( "Error", f"{user} is already muted.", f"User ID: {user.id}")) return dur_num = 0 num = int(duration[:-1]) if duration.endswith("s"): dur_num = num elif duration.endswith("m"): dur_num = num * 60 elif duration.endswith("h"): dur_num = num * 3600 elif duration.endswith("d"): dur_num = num * 86400 exp_time = utils.get_timestamp() + dur_num if reason: chanmsg = f"{user.mention} has been muted for {utils.get_durationstr(dur_num)}.\n\nReason: **{reason}**" dmmsg = f"You have been muted for {utils.get_durationstr(dur_num)}.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been muted for {utils.get_durationstr(dur_num)}." dmmsg = f"You have been muted for {utils.get_durationstr(dur_num)}." try: db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, f"mute ({duration})", reason) db.add_mute(ctx.message.author, user, exp_time, reason) await user.remove_roles(*user.roles[1:], atomic=True) await user.add_roles(user.guild.get_role(defs.mute_role_id), atomic=True) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the mute you just attempted to issue.", )) else: await ctx.send(embed=interface.error_message( "Mute", chanmsg, f"User ID: {user.id}")) await user.send(embed=interface.error_message( f"{ctx.message.guild} - Mute", dmmsg))
async def mod_unjail(self, ctx, user: discord.Member, *, reason: str = None): await ctx.message.delete() if not perms.check_command_priv("unjail", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **unjail** command." )) return if user.id == ctx.message.author.id: await ctx.send(embed=interface.error_message( "Error", f"You can't unjail yourself.")) return if perms.get_staff_rank( ctx.message.author) <= perms.get_staff_rank(user): await ctx.send(embed=interface.error_message( "Error", f"You can't unjail someone of the same staff rank or higher.")) return if defs.jail_role_id not in [r.id for r in user.roles]: await ctx.send(embed=interface.error_message( "Error", f"{user} is not jailed.", f"User ID: {user.id}")) return if reason: chanmsg = f"{user.mention} has been released from jail.\n\nReason: **{reason}**" dmmsg = f"You have been released from jail.\n\nReason: **{reason}**" else: chanmsg = f"{user.mention} has been released from jail." dmmsg = f"You have been released from jail." try: db.log_staff_action(utils.get_timestamp(), ctx.message.author, user, "unjail", reason) jail = db.get_jail_record(user) roles = [user.guild.get_role(rid) for rid in jail["roles"]] roles = [ r for r in roles if r is not None and r.name != "@everyone" ] db.remove_jail(user) await user.remove_roles(user.guild.get_role(defs.jail_role_id), atomic=True) await user.add_roles(*roles, atomic=True) except: raise await ctx.author.send(embed=interface.error_message( f"{ctx.message.guild} - Error", "There was an error processing the unjail you just attempted to issue.", )) else: await ctx.send(embed=interface.success_message( "Unjail", chanmsg, f"User ID: {user.id}")) await user.send(embed=interface.success_message( f"{ctx.message.guild} - Unjail", dmmsg))
async def mod_history(self, ctx, user: discord.Member): """ List the moderation history of a user. <user> must be a Discord tag, ID number, or mention. """ await ctx.message.delete() if not perms.check_command_priv("history", ctx.message.author.roles): await ctx.send(embed=interface.error_message( "Access Denied", f"**{ctx.message.author}** does not have access to the **history** command." )) return logs = None msg = await ctx.send(embed=interface.working_message( "Moderation History", f"Retrieving history for **{user}**...")) try: logs = db.get_action_history(user) except: raise await ctx.send(embed=interface.error_message( "Error", f"There was an error retrieving history for **{user}**.")) if not logs: await msg.edit(embed=interface.success_message( f"Moderation History for {user}", f"**{user}** has no moderation history.", f"User ID: {user.id}")) else: log_dict = defaultdict(list) for log in logs: actor = ctx.message.guild.get_member(log["actor"]) action = log["action"] reason = log["reason"] edate = datetime.fromtimestamp(log["tval"], tz=timezone.utc).date() etime = datetime.fromtimestamp(log["tval"], tz=timezone.utc).timetz() if reason: log_dict[edate].append(( etime, f"**{action}** by **{actor}** with reason: **{reason}**" )) else: log_dict[edate].append( (etime, f"**{action}** by **{actor}**")) logstring = "" for date, events in log_dict.items(): logstring += date.strftime("%A, %b %d %Y\n") for time, event in sorted(events, key=lambda x: x[0], reverse=True): logstring += " {} - {}\n".format( time.strftime("%I:%M %p"), event) logstring += "\n" await msg.edit(embed=interface.success_message( f"Moderation History for {user}", logstring.strip(), f"User ID: {user.id}"))