async def on_member_remove(self, member: discord.Member): while not self.bot.startup_done: await asyncio.sleep(1) async for entry in member.guild.audit_logs( limit=1, action=discord.AuditLogAction.kick): if entry.target == member: channelid = Configuration.getConfigVar(member.guild.id, "MOD_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: await logChannel.send( f":boot: {member} (`{member.id}`) has been kicked." ) else: channelid = Configuration.getConfigVar(member.guild.id, "JOIN_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: await logChannel.send( f":outbox_tray: {member} (`{member.id}`) has left the server." )
async def on_member_join(self, member): channelid = Configuration.getConfigVar(member.guild.id, "WELCOME_CHANNEL") if channelid is not 0: welcomeChannel: discord.TextChannel = self.bot.get_channel(channelid) if welcomeChannel is not None: welcomeMessage = Configuration.getConfigVar(member.guild.id, "WELCOME_MESSAGE") if welcomeMessage is not None and welcomeMessage is not "": await welcomeChannel.send(welcomeMessage.replace("%mention%", f"<@{member.id}>").replace("%name%", member.name))
async def fanart(self, ctx, *content : str): type(content) channel = self.bot.get_channel(Configuration.getConfigVar(ctx.guild.id, "FAN_ART_CHANNEL")) censor = self.bot.get_channel(Configuration.getConfigVar(ctx.guild.id, "CENSORED_LOGS")) blacklist = Configuration.getConfigVar(ctx.guild.id, "BAD_LINKS") for badlink in blacklist: if badlink in content[0]: await censor.send(f":warning: **{ctx.author.name}#{ctx.author.discriminator} (``{ctx.author.id}``) has attempted to submit a censored link. Please view the link at your own caution:**```{content}```") return await ctx.message.delete() if os.path.exists(f'submissions/{ctx.guild.id}.json') is False: data = {} with open(f'submissions/{ctx.guild.id}.json', 'w') as outfile: json.dump(data, outfile, indent=4) if not channel: return await ctx.send("The submission channel is not configured, please tell a moderator.") links = re.findall(r"https?://\S+\.[^\s>]+", ' '.join(content)) if not links or len(links) > 1: reply = await ctx.send("Your submission must contain one link, and no more than one!") await asyncio.sleep(5) await reply.delete() await ctx.message.delete() return try: with open(f'submissions/{ctx.guild.id}.json', 'r') as infile: data = json.load(infile) if str(ctx.author.id) in data: reply = await ctx.send("You already submitted the following: " + data[str(ctx.author.id)]['SUBMISSION_LINK']) await asyncio.sleep(10) await reply.delete() await ctx.message.delete() return else: message = await channel.send(( f"**Artist:** {ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id})\n" f"**Link{'s' if len(links) > 1 else ''}:** {' '.join(links)}" )) data[str(ctx.author.id)] = {'SUBMISSION_LINK': ', '.join(links)} reply = await ctx.send("I've sent your submission through, good luck with the event!") await asyncio.sleep(5) await reply.delete() await ctx.message.delete() with open(f'submissions/{ctx.guild.id}.json', 'w') as outfile: json.dump(data, outfile, indent=4) except discord.Forbidden: return await ctx.send("I can't send messages to the submission channel, please tell a moderator.")
async def mute(self, ctx: commands.Context, target: discord.Member, *, reason="No reason provided"): """Mutes someone without unmuting them.""" if target == ctx.bot.user: await ctx.send( "Why would you like to mute me? :disappointed_relieved:") elif target == ctx.author: await ctx.send( "You have played yourself. But you cannot mute yourself!") else: roleid = Configuration.getConfigVar(ctx.guild.id, "MUTE_ROLE") if roleid is 0: await ctx.send( f":warning: Unable to comply, you haven't told me what role I could use to mute people, but I can still kick {target.mention} if you want while a server admin tells me what role I can use." ) else: role = discord.utils.get(ctx.guild.roles, id=roleid) if role is None: await ctx.send( f":warning: Unable to comply, someone has removed the role I was told to use, but I can still kick {target.mention} while a server admin makes a new role for me to use." ) else: await target.add_roles( role, reason=f"{reason}, as requested by {ctx.author.name}") await ctx.send(f"{target.display_name} has been muted!") await BugLog.logToModLog( ctx.guild, f":zipper_mouth: {target.name}#{target.discriminator} (`{target.id}`) has been muted by {ctx.author.name} for {reason}" )
async def mute(self, ctx: commands.Context, target: discord.Member, durationNumber: int, durationIdentifier: str, *, reason="No reason provided"): """Temporary mutes someone""" roleid = Configuration.getConfigVar(ctx.guild.id, "MUTE_ROLE") if roleid is 0: await ctx.send( f":warning: Unable to comply, you have not told me what role i can use to mute people, but i can still kick {target.mention} if you want while a server admin tells me what role i can use" ) else: role = discord.utils.get(ctx.guild.roles, id=roleid) if role is None: await ctx.send( f":warning: Unable to comply, someone has removed the role i was told to use, but i can still kick {target.mention} while a server admin makes a new role for me to use" ) else: duration = Util.convertToSeconds(durationNumber, durationIdentifier) until = time.time() + duration await target.add_roles( role, reason=f"{reason}, as requested by {ctx.author.name}") if not str(ctx.guild.id) in self.mutes: self.mutes[str(ctx.guild.id)] = dict() self.mutes[str(ctx.guild.id)][str(target.id)] = until await ctx.send(f"{target.display_name} has been muted") Util.saveToDisk("mutes", self.mutes) await BugLog.logToModLog( ctx.guild, f":zipper_mouth: {target.name}#{target.discriminator} (`{target.id}`) has been muted by {ctx.author.name} for {durationNumber} {durationIdentifier}: {reason}" )
async def list(self, ctx: commands.Context, page=""): """Provides a list of all joinable roles""" role_id_list = Configuration.getConfigVar(ctx.guild.id, "JOINABLE_ROLES") if len(role_id_list) == 0: await ctx.send("There are currently not selfroles set.") return rolesPerPage = 20 roles = "" ids = "" pages = math.ceil(len(role_id_list) / rolesPerPage) if page == "" or not page.isdigit(): page = 1 elif int(page) <= 1 or int(page) > pages: page = 1 for i in range(rolesPerPage * (int(page) - 1), rolesPerPage * int(page)): if i < len(role_id_list): role = role_id_list[i] roles += f"<@&{role}>\n\n" ids += str(role) + "\n\n" else: break embed = discord.Embed(title=ctx.guild.name + "'s Joinable roles", color=0x54d5ff) embed.add_field(name="\u200b", value=roles, inline=True) embed.add_field(name="\u200b", value=ids, inline=True) embed.set_footer(text=f"Page {page} of {pages}") await ctx.send(embed=embed)
async def on_raw_message_delete(self, message_id, channel_id): while not self.bot.startup_done: await asyncio.sleep(1) message = LoggedMessage.get_or_none(messageid=message_id) if message is not None: channel: discord.TextChannel = self.bot.get_channel(channel_id) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None channelid = Configuration.getConfigVar(channel.guild.id, "MINOR_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: embed = discord.Embed( timestamp=datetime.datetime.utcfromtimestamp( time.time()), description=self.bot.aes.decrypt(message.content)) embed.set_author( name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer(text=f"Sent in #{channel.name}") await logChannel.send( f":wastebasket: Message by {user.name if hasUser else message.author} (`{user.id}`) in {channel.mention} has been removed.", embed=embed)
async def on_raw_message_edit(self, message_id, data): while not self.bot.startup_done: await asyncio.sleep(1) message = LoggedMessage.get_or_none(messageid=message_id) if message is not None and "content" in data: channel: discord.TextChannel = self.bot.get_channel( int(data["channel_id"])) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None channelid = Configuration.getConfigVar(channel.guild.id, "MINOR_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: if message.content == data["content"]: # prob just pinned return embed = discord.Embed(timestamp=datetime.datetime. utcfromtimestamp(time.time())) embed.set_author( name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer(text=f"Sent in #{channel.name}") embed.add_field(name="Before", value=message.content, inline=False) embed.add_field(name="After", value=data["content"], inline=False) await logChannel.send( f":pencil: Message by {user.name} (`{user.id}`) in {channel.mention} has been edited", embed=embed) message.content = data["content"] message.save()
async def submit(self, ctx, *content): channel = self.bot.get_channel( int(Configuration.getConfigVar(ctx.guild.id, "SUBMISSION_CHANNEL"))) if not channel: return await ctx.send( "The submission channel is not configured, please tell a moderator." ) links = re.findall(r"https?://\S+\.\S+", ' '.join(content)) if not links or len(links) > 5: return await ctx.send( "Your submission must contain at least one link, and no more than five!" ) try: message = await channel.send(( f"**Artist:** {ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id})\n" f"**Link{'s' if len(links) > 1 else ''}:** {' '.join(links)}")) await message.add_reaction(self.upvote) return await ctx.send( "I've sent your submission through, good luck with the event!") except discord.Forbidden: return await ctx.send( "I can't send messages to the submission channel, please tell a moderator." )
async def logToModLog(guild, message=None, embed=None): modlog: discord.TextChannel = guild.get_channel( Configuration.getConfigVar(guild.id, "MOD_LOGS")) if modlog is not None: perms = modlog.permissions_for(guild.me) if perms.send_messages: await modlog.send(message, embed=embed)
async def leave(self, ctx: commands.Context, *, rolename): """Leaves one of the selfrole groups you are in""" role = None #mention if rolename.startswith("<@"): roleid = rolename.replace('<', '').replace('!', '').replace( '@', '').replace('&', '').replace('>', '') role = discord.utils.get(ctx.guild.roles, id=int(roleid)) #id elif rolename.isdigit(): role = discord.utils.get(ctx.guild.roles, id=int(rolename)) #name else: name = difflib.get_close_matches(rolename, Util.getRoleNameArray(ctx), 1, 0.4) if len(name) > 0: role = discord.utils.get(ctx.guild.roles, id=Util.getRoleIdDict(ctx)[name[0]]) if role is None: await ctx.send("I cannnot find that role!") return role_id_list = Configuration.getConfigVar(ctx.guild.id, "JOINABLE_ROLES") if role.id in role_id_list and role in ctx.author.roles: await ctx.message.author.remove_roles( role, reason=f"{ctx.message.author} Left role group {role.name}") await ctx.send(f"Succesfully left {role.name}") else: await ctx.send( "That role isn't leavable or you don't have the role.")
async def mute(self, ctx: commands.Context): """Disable the mute feature.""" role = discord.utils.get(ctx.guild.roles, id=Configuration.getConfigVar(ctx.guild.id, "MUTE_ROLE")) if role is not None: for member in role.members: await member.remove_roles(role, reason=f"Mute feature has been disabled.") Configuration.setConfigVar(ctx.guild.id, "MUTE_ROLE", 0) await ctx.send("Mute feature has been disabled, all people muted have been unmuted and the role can now be removed.")
def prefix_callable(bot, msg): user_id = bot.user.id prefixes = [f'<@!{user_id}> ', f'<@{user_id}> '] if msg.guild is None or not bot.startup_done: prefixes.append('!') #use default ! prefix in DMs else: prefixes.append(Configuration.getConfigVar(msg.guild.id, "PREFIX")) return prefixes
async def add(self, ctx: commands.Context, role: discord.Role): """Used to add roles to the joinable list""" role_list = Configuration.getConfigVar(ctx.guild.id, "JOINABLE_ROLES") if role.id in role_list: await ctx.send("This role is already joinable! To remove joinable roles use `!configure removejoinableRole` instead.") else: role_list.extend([role.id]) Configuration.setConfigVar(ctx.guild.id, "JOINABLE_ROLES", role_list) await ctx.send(f"{role.name} has been added to the selfrole list.")
def isServerMod(ctx: commands.Context): if ctx.guild is None: return False modrole = Configuration.getConfigVar(ctx.guild.id, "MOD_ROLE_ID") if modrole != 0: for role in ctx.author.roles: if str(role.id) == str(modrole): return True return isServerAdmin(ctx)
def isServerAdmin(ctx: commands.Context): if ctx.guild is None: return False adminrole = Configuration.getConfigVar(ctx.guild.id, "ADMIN_ROLE_ID") if adminrole != 0: for role in ctx.author.roles: if str(role.id) == str(adminrole): return True return ctx.author == ctx.guild.owner
async def on_member_remove(self, member: discord.Member): while not self.bot.startup_done: await asyncio.sleep(1) channelid = Configuration.getConfigVar(member.guild.id, "JOIN_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel(channelid) if logChannel is not None: await logChannel.send( f":outbox_tray: {member.display_name}#{member.discriminator} (`{member.id}`) has left the server." )
async def on_member_unban(self, guild, user): while not self.bot.startup_done: await asyncio.sleep(1) channelid = Configuration.getConfigVar(guild.id, "MOD_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel(channelid) if logChannel is not None: await logChannel.send( f":rotating_light: {user.display_name}#{user.discriminator} (`{user.id}`) has been unbanned from the server." )
async def on_member_join(self, member: discord.Member): while not self.bot.startup_done: await asyncio.sleep(1) channelid = Configuration.getConfigVar(member.guild.id, "JOIN_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel(channelid) if logChannel is not None: dif = (datetime.datetime.utcnow() - member.created_at) minutes, seconds = divmod(dif.days * 86400 + dif.seconds, 60) hours, minutes = divmod(minutes, 60) age = (f"{dif.days} days" ) if dif.days > 0 else f"{hours} hours, {minutes} mins." await logChannel.send( f":inbox_tray: {member.display_name}#{member.discriminator} (`{member.id}`) has joined, account created {age} ago." )
async def announce(self, ctx: commands.Context, *, announce=""): """Announces the given text in the set announcement channel.""" channel = ctx.bot.get_channel( int(Configuration.getConfigVar(ctx.guild.id, "ANNOUNCE"))) if channel != None: if (announce != ""): try: await channel.send(announce) except: await ctx.send( "I wasn't able to send a message in the set announce channel. Maybe check the permissions." ) else: await ctx.send( "You need to give me a message that I can announce.") else: await ctx.send("There is no announce channel set!")
async def on_raw_message_edit(self, event: RawMessageUpdateEvent): while not self.bot.startup_done: await asyncio.sleep(1) message = LoggedMessage.get_or_none(messageid=event.message_id) if message is not None and "content" in event.data: channel: discord.TextChannel = self.bot.get_channel( int(event.data["channel_id"])) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None channelid = Configuration.getConfigVar(channel.guild.id, "MINOR_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: if message.content == event.data["content"]: # prob just pinned return embed = discord.Embed(timestamp=datetime.datetime. utcfromtimestamp(time.time())) embed.set_author( name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer(text=f"Sent in #{channel.name}") if self.bot.aes.decrypt(message.content) is "": oldMessage = "---There was no message data before, this probably is the edit of an attachment.---" else: oldMessage = self.bot.aes.decrypt(message.content) embed.add_field(name="Before", value=(oldMessage[:1000] + '...') if len(oldMessage) > 1020 else oldMessage, inline=False) embed.add_field( name="After", value=(event.data["content"][:1000] + '...') if len(event.data["content"]) > 1020 else event.data["content"], inline=False) await logChannel.send( f":pencil: Message by {user.name} (`{user.id}`) in {channel.mention} has been edited", embed=embed) message.content = self.bot.aes.encrypt( event.data["content"]) message.save()
async def remove(self, ctx: commands.Context, roleraw): """Used to remove roles from the joinable list""" role_list = Configuration.getConfigVar(ctx.guild.id, "JOINABLE_ROLES") try: role = await commands.RoleConverter().convert(ctx, roleraw) if role.id in role_list: role_list.remove(role.id) Configuration.setConfigVar(ctx.guild.id, "JOINABLE_ROLES", role_list) await ctx.send(f"{role.name} has been removed from the selfrole list.") else: await ctx.send("That role already isn't joinable!") except: if role in role_list: role_list.remove(role) Configuration.setConfigVar(ctx.guild.id, "JOINABLE_ROLES", role_list) await ctx.send("Role successfully removed from the selfrole list.") else: await ctx.send("That role already isn't joinable or if you are trying to remove a role from the selfrole list you have already deleted please use the ID.")
async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): guild: discord.Guild = channel.guild roleid = Configuration.getConfigVar(guild.id, "MUTE_ROLE") if roleid is not 0: role = discord.utils.get(guild.roles, id=roleid) if role is not None and channel.permissions_for( guild.me).manage_channels: if isinstance(channel, discord.TextChannel): await channel.set_permissions( role, reason="Automatic mute role setup", send_messages=False, add_reactions=False) else: await channel.set_permissions( role, reason="Automatic mute role setup", speak=False, connect=False)
async def on_message(self, message: discord.Message): while not self.bot.startup_done: await asyncio.sleep(1) if not hasattr(message.channel, "guild") or message.channel.guild is None: return if Configuration.getConfigVar(message.guild.id, "MINOR_LOGS") is 0 or message.author.bot: return for a in message.attachments: LoggedAttachment.create(id=a.id, url=self.bot.aes.encrypt(a.url), isImage=(a.width is not None or a.width is 0), messageid=message.id) LoggedMessage.create(messageid=message.id, author=message.author.id, content=self.bot.aes.encrypt(message.content), timestamp=message.created_at.timestamp(), channel=message.channel.id)
async def minorLogChannel(self, ctx: commands.Context, channel: discord.TextChannel): """Sets the logging channel for minor logs (edit/delete)""" if channel is None: raise BadArgument("Missing channel") permissions = channel.permissions_for( ctx.guild.get_member(self.bot.user.id)) if permissions.read_messages and permissions.send_messages and permissions.embed_links: old = Configuration.getConfigVar(ctx.guild.id, "MINOR_LOGS") Configuration.setConfigVar(ctx.guild.id, "MINOR_LOGS", channel.id) await ctx.send(f"{channel.mention} will now be used for minor logs" ) if old == 0: await ctx.send(f"Caching recent messages for logging...") await self.buildCache(ctx.guild) await ctx.send("Caching complete") else: await ctx.send( f"I cannot use {channel.mention} for logging, I do not have the required permissions in there (read_messages, send_messages and embed_links)." )
async def end(self, ctx: commands.Context): """Ends the event!""" heads = [ 187606096418963456, 298618155281154058, 169197827002466304, 263495765270200320, 117101067136794628, 164475721173958657, 191793155685744640 ] channel = ctx.bot.get_channel( int(Configuration.getConfigVar(ctx.guild.id, "SUBMISSION_CHANNEL"))) everyone = None if ctx.author.id not in heads: return for role in channel.guild.roles: if role.id == channel.guild.id: everyone = role await channel.set_permissions(everyone, read_messages=False) await ctx.send("Event has ended!")
async def on_message(self, message: discord.Message): if message.author == self.bot.user: return if self.bot.user in message.mentions and ( "👈" in message.content or "👉" in message.content or 'poke' in message.content): muted = discord.utils.get(message.guild.roles, id=Configuration.getConfigVar( message.guild.id, "MUTED")) if muted is not None: await message.author.add_roles(muted) await message.channel.send( f"{message.author.mention} I do **NOT** appreciate being poked." ) await asyncio.sleep(2) await message.channel.send(f"Please don't do that again!") await asyncio.sleep(13) await message.author.remove_roles(muted) await asyncio.sleep(5 * 60) await message.channel.send( f"__pokes :point_right:{message.author.mention}:point_left:__" )
async def on_member_join(self, member: discord.Member): while not self.bot.startup_done: await asyncio.sleep(1) if str(member.guild.id) in self.mutes and member.id in self.mutes[str( member.guild.id)]: roleid = Configuration.getConfigVar(member.guild.id, "MUTE_ROLE") if roleid is not 0: role = discord.utils.get(member.guild.roles, id=roleid) if role is not None: if member.guild.me.guild_permissions.manage_roles: await member.add_roles( role, reason= "Member left and re-joined before mute expired") await BugLog.logToModLog( member.guild, f":zipper_mouth: {member.name}#{member.discriminator} (`{member.id}`) has re-joined the server before his mute expired has has been muted again" ) else: await BugLog.logToModLog( member.guild, f"{member.name}#{member.discriminator} (`{member.id}`) has re-joined before their mute expired but i am missing the permissions to re-apply the mute" )
async def unmute(self, ctx: commands.Context, target: discord.Member, *, reason="No reason provided"): roleid = Configuration.getConfigVar(ctx.guild.id, "MUTE_ROLE") if roleid is 0: await ctx.send( f"The mute feature has been dissabled on this server, as such i cannot unmute that person" ) else: role = discord.utils.get(ctx.guild.roles, id=roleid) if role is None: await ctx.send( f":warning: Unable to comply, the role i've been told to use for muting no longer exists" ) else: await target.remove_roles( role, reason=f"Unmuted by {ctx.author.name}, {reason}") await ctx.send(f"{target.display_name} has been unmuted") await BugLog.logToModLog( ctx.guild, f":innocent: {target.name}#{target.discriminator} (`{target.id}`) has been unmuted by {ctx.author.name}" )
async def on_ready(self): for guild in self.bot.guilds: if Configuration.getConfigVar(guild.id, "MINOR_LOGS") is not 0: await self.buildCache(guild)