def remove_reaction_role_requirement(message: discord.Message, emoji: typing.Union[discord.Emoji, str], role: discord.Role): """ Removes a role requirement for a reaction role :param message: Message that has the reaction role :param emoji: Emoji for the reaction role :param role: Role to remove as a requirement """ global guilds, raw_settings combo_id = str(message.channel.id) + str(message.id) guilds[message.guild]["reaction_roles"][message]["emojis"][emoji][ "reqs"].append(role) if isinstance(emoji, str): raw_settings["guilds"][str( message.guild.id )]["reaction_roles"][combo_id]["emojis"][emoji]["reqs"].remove(role.id) else: raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id]["emojis"][str( emoji.id)]["reqs"].remove(role.id) save_json(os.path.join("config", "settings.json"), raw_settings)
async def on_guild_remove(self, guild): """ Removes guilds from the settings """ self.leaderboards.pop(str(guild.id)) save_json(os.path.join("config", "leaderboards.json"), self.leaderboards)
async def reset_leaderboard(self, ctx): """ Resets all leaderboard information. Usage: .resetLeaderboard :param ctx: context object """ guild = ctx.message.guild await ctx.send("Resetting leaderboards...") self.leaderboards[str(guild.id)]["last_update"] = None self.leaderboards[str(guild.id)]["message_leaderboard"] = {} self.leaderboards[str(guild.id)]["reaction_leaderboard"] = {} self.leaderboards[str(guild.id)]["quote_leaderboard"] = {} self.leaderboards[str(guild.id)]["emoji_leaderboard"] = {} for emoji in guild.emojis: self.leaderboards[str(guild.id)]["emoji_leaderboard"][str( emoji.id)] = 0 save_json(os.path.join("config", "leaderboards.json"), self.leaderboards) await self.update_leaderboards() await ctx.send("Successfully reset leaderboards")
async def update_guilds(self): """ Updates guilds included in leaderboards.json """ global default_leaderboard saved_guilds = [] for guild_id in self.leaderboards: saved_guilds.append(int(guild_id)) guilds = [] for guild in self.bot.guilds: guilds.append(guild.id) add_guilds = [x for x in guilds if x not in saved_guilds] remove_guilds = [x for x in saved_guilds if x not in guilds] # Add new guilds for guild_id in add_guilds: self.leaderboards[str(guild_id)] = default_leaderboard # Remove disconnected guilds for guild_id in remove_guilds: self.leaderboards.pop(str(guild_id)) save_json(os.path.join("config", "leaderboards.json"), self.leaderboards)
async def remove_vote(self, ctx, *, title): """ Removes the calling user's vote from a given movie Usage: .removeVote <title> :param ctx: :param title: title of the movie """ author = str(ctx.message.author.id) if title in self.movie_list: if author in self.movie_list[title]["votes"]: self.movie_list[title]["votes"].remove(author) self.user_list[author]["votes"].remove(title) if len(self.movie_list[title]["votes"]) == 0: self.user_list[self.movie_list[title] ["request"]]["requests"].remove(title) del self.movie_list[title] await ctx.send( "Vote for " + title + " removed. Since you were the only vote for this movie, it has been removed from the list." ) else: await ctx.send("Vote for " + title + " removed.") else: await ctx.send("You have not voted for this movie.") return else: await ctx.send("Movie not found.") return save_json(os.path.join("config", "movie_list.json"), self.movie_list) save_json(os.path.join("config", "user_list.json"), self.user_list)
async def on_raw_message_delete(self, payload): """ Updates leaderboards based ond deleted message content """ if payload.guild_id is not None: guild = self.bot.get_guild(payload.guild_id) leaderboards = self.leaderboards[str(guild.id)] if payload.cached_message is not None: message = payload.cached_message if not message.author.bot: leaderboards["message_leaderboard"][str( message.author.id)] -= 1 if str(message.channel.id ) == leaderboards["quotes_channel"]: for user in message.mentions: leaderboards["quotes_channel"][str(user.id)] -= 1 for emoji in self.bot.emojis: emoji_name = "<:" + emoji.name + ":" + str( emoji.id) + ">" for index in range(0, message.content.count(emoji_name)): leaderboards["emoji_leaderboard"][str( emoji.id)] -= 1 leaderboards["lastUpdate"] = message.created_at.isoformat() save_json(os.path.join("config", "leaderboards.json"), self.leaderboards)
def update_wpi_verifications(): """ Checks the verification list and returns new WPI verified IDs :return: List of new IDs """ global guilds, raw_settings verifications = load_json( "/var/www/WPI-Discord-Flask/verifications.json" ) # Open the verification file and read the user IDs. Compare to the ones stored here. new_users = [] for token in verifications: if token not in guilds[main_guild]["verifications"]["wpi"]: guilds[main_guild]["verifications"]["wpi"][token] = verifications[ token] raw_settings["guilds"][str( main_guild.id )]["verifications"]["wpi"][token] = verifications[token] new_users.append(verifications[token]) if len(new_users) > 0: save_json(os.path.join("config", "settings.json"), raw_settings) return new_users
async def warn(self, ctx, member: discord.Member, *, reason): """ Warns a specific user for given reason Usage: .warn <member> <reason> :param ctx: context object :param member: member of the server to warn :param reason: reason to log and DM """ attachments = [] if len(ctx.message.attachments) > 0: for i in ctx.message.attachments: attachments.append(await i.to_file()) if len(reason) > 0: await member.send("You were warned in the " + ctx.guild.name + ". Reason:\n> " + reason, files=attachments) else: await ctx.send("No warning to send") return if str(member.id) in self.warns: self.warns[str(member.id)].append(reason) else: self.warns[str(member.id)] = [reason] save_json(os.path.join("config", "warns.json"), self.warns) await ctx.send( "Warning sent to " + member.display_name + " (" + str(member.id) + "), this is their " + make_ordinal(len(self.warns[str(member.id)])) + " warning" )
async def remove_vote(self, ctx): """ Removes your vote for an option in the poll Usage: .removeVote <option> :param ctx: context object """ if not self.vote_open: await ctx.send("There is no poll currently open") return user_option = ctx.message.content[ctx.message.content.find(" ") + 1:] count = 0 for option in self.votes["votes"]: if user_option == option["name"]: if ctx.author.id not in option["voters"]: await ctx.send("You haven't voted for this option") return option["voters"].remove(ctx.author.id) if len(option["voters"]) == 0 and self.votes["type"] == "open": self.votes["votes"].pop(count) save_json(os.path.join("config", "votes.json"), self.votes) await self.update_poll_message() await ctx.send("Successfully removed vote for " + user_option) return count += 1 await ctx.send("This option doesn't exist")
def remove_reaction_role(message: discord.Message, emoji: typing.Union[discord.Emoji, str]): """ Removes a reaction role from a message :param message: Message to remove reaction role from :param emoji: Emoji to remove """ global guilds, raw_settings combo_id = str(message.channel.id) + str(message.id) del guilds[message.guild]["reaction_roles"][message]["emojis"][emoji] if isinstance(emoji, str): del raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id]["emojis"][emoji] else: del raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id]["emojis"][str( emoji.id)] if len(guilds[message.guild]["reaction_roles"][message]["emojis"]) == 0: del guilds[message.guild]["reaction_roles"][message] del raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id] save_json(os.path.join("config", "settings.json"), raw_settings)
async def warn_note(self, ctx, user: typing.Union[discord.Member, discord.User], *, reason): """ Adds a warning to a user without DM'ing them Usage: .warnNote <user> <reason> :param ctx: context object :param user: user to add a note for :param reason: reason for the note """ attachments = [] if len(ctx.message.attachments) > 0: for i in ctx.message.attachments: attachments.append(await i.to_file()) if str(user.id) in self.warns: self.warns[str(user.id)].append(reason) else: self.warns[str(user.id)] = [reason] save_json(os.path.join("config", "warns.json"), self.warns) if isinstance(user, discord.Member): await ctx.send( "Warning added for " + user.display_name + " (" + str(user.id) + "), this is their " + make_ordinal(len(self.warns[str(user.id)])) + " warning" ) else: await ctx.send( "Warning added for " + user.name + " (" + str(user.id) + "), this is their " + make_ordinal(len(self.warns[str(user.id)])) + " warning" )
def clear_close_time(): """ Sets the close_time """ global close_time, raw_settings close_time = raw_settings["close_time"] = None save_json(os.path.join("config", "settings.json"), raw_settings)
def clear_dm_channel(): """ Clears the set DM channel """ global dm_channel, raw_settings dm_channel = raw_settings["dm_channel_id"] = None save_json(os.path.join("config", "settings.json"), raw_settings)
async def on_reaction_add(self, reaction, user): """ Adds a vote for a movie based on the reaction or updates a movie list embed """ # If the reaction was added to a voting embed if reaction.message.id in self.cached_voting: # If the reaction wasn't added by a bot if not user.bot: # If not a custom emoji if isinstance(reaction.emoji, str): page = self.cached_voting[reaction.message.id]["page"] length = len(self.movie_list) # If attempting to switch pages if reaction.emoji == "⬅️" or reaction.emoji == "➡️": # Check if page is in bounds if 0 < (page + self.emojiList[reaction.emoji]) <= math.ceil(length / 9): # Update to new page self.cached_voting[reaction.message.id]["page"] += self.emojiList[reaction.emoji] await self.update_movie_message(self.cached_voting[reaction.message.id]["message"]) # If attempting to vote for a movie elif reaction.emoji in self.emojiList.keys(): index = self.emojiList[reaction.emoji] - 1 page = self.cached_voting[reaction.message.id]["page"] index += 9 * (page - 1) titles = list(self.movie_list.keys()) # If user has not already voted for the movie if str(user.id) not in self.movie_list[titles[index]]["votes"]: self.movie_list[titles[index]]["votes"].append(str(user.id)) if str(user.id) not in self.user_list: self.user_list[str(user.id)] = {"requests": [], "votes": [titles[index]]} else: self.user_list[str(user.id)]["votes"].append(titles[index]) # Figure out how many positions the movie changed by differential = 0 while len(self.movie_list[titles[index]]["votes"]) < \ len(self.movie_list[titles[index - (differential + 1)]]["votes"]): differential += 1 # If the movie changed positions in leaderboard if differential > 0: # Min page number of leaderboard to update page = math.floor((index - differential) / 9) for messageID in self.cached_voting: if self.cached_voting[messageID]["page"] >= page: await self.update_movie_message(self.cached_voting[messageID]["message"]) else: await self.update_movie_message(reaction.message) save_json(os.path.join("config", "movie_list.json"), self.movie_list) # Remove reaction if not isinstance(reaction.message.channel, discord.channel.DMChannel): await reaction.remove(user)
def set_close_time(): """ Sets the closing time for the bot """ global close_time, raw_settings close_time = datetime.now() raw_settings["close_time"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") save_json(os.path.join("config", "settings.json"), raw_settings)
async def on_guild_join(self, guild): """ Creates default settings for new guilds """ global default_leaderboard if str(guild.id) not in self.leaderboards: self.leaderboards[str(guild.id)] = default_leaderboard save_json(os.path.join("config", "leaderboards.json"), self.leaderboards)
def set_prefix(new_prefix: str): """ Sets the prefix for the bot :param new_prefix: Prefix to use """ global prefix, raw_settings prefix = raw_settings["prefix"] = new_prefix save_json(os.path.join("config", "settings.json"), raw_settings)
def set_status(new_status: str): """ Sets the status for the bot :param new_status: String to use for the status """ global status, raw_settings status = raw_settings["status"] = new_status save_json(os.path.join("config", "settings.json"), raw_settings)
def add_verified_user(member: discord.Member): """ Adds a verified member :param member: Member to add """ global verifications, raw_settings raw_settings["verifications"]["users"] = verifications["users"] = member.id save_json(os.path.join("config", "settings.json"), raw_settings)
async def add_option(self, ctx): """ Adds an option to the poll Usage: .addOption <option> :param ctx: context object """ if not self.vote_open: await ctx.send("There is no poll currently open") return if not self.votes["type"] == "open": await ctx.send("Cannot add options to this type of poll") return user_option = ctx.message.content[ctx.message.content.find(" ") + 1:] if len(user_option) > 88: await ctx.send("This option is too long") return if not user_option.isalnum(): if "-" in user_option: modified_string = user_option.replace("-", "") if not modified_string.isalnum(): await ctx.send("Channel names have to be alphanumeric") return if not all(c.isdigit() or c.islower() or c == "-" for c in user_option): await ctx.send("Channel names must be lowercase") return elif " " in user_option or "\n" in user_option: await ctx.send( "Channel names cannot contain spaces (try using a \"-\" instead)" ) return else: # Check if the user has an option already or if the option already exists for option in self.votes["votes"]: if option["creator"] == ctx.author.id: await ctx.send("You already added an option to this poll") return if user_option == option["name"]: await ctx.send("This option already exists") return self.votes["votes"].append({ "name": user_option, "creator": ctx.author.id, "voters": [ctx.author.id] }) save_json(os.path.join("config", "votes.json"), self.votes) await self.update_poll_message() await ctx.send("Successfully added your option")
def set_dm_channel(channel: discord.TextChannel): """ Sets the DM channel :param channel: Channel to be used """ global dm_channel, raw_settings dm_channel = channel raw_settings["dm_channel_id"] = channel.id save_json(os.path.join("config", "settings.json"), raw_settings)
def add_reaction_role(message: discord.Message, emoji: typing.Union[discord.Emoji, str], role: discord.Role): """ Adds a reaction role to a message :param message: Message to add reaction role to :param emoji: Emoji to react with :param role: Role to give on react """ global guilds, raw_settings combo_id = str(message.channel.id) + str(message.id) # If reacts already exist on the message if message in guilds[message.guild]["reaction_roles"]: guilds[ message.guild]["reaction_roles"][message]["emojis"][emoji] = role if isinstance(emoji, str): raw_settings["guilds"][str( message.guild.id )]["reaction_roles"][combo_id]["emojis"][emoji] = role.id else: raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id]["emojis"][str( emoji.id)] = role.id else: guilds[message.guild]["reaction_roles"][message] = { "emojis": { emoji: role.id }, "exclusive": False } if isinstance(emoji, str): raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][combo_id] = { "emojis": { emoji: role.id }, "exclusive": False } else: raw_settings["guilds"][str( message.guild.id)]["reaction_roles"][str(emoji.id)] = { "emojis": { emoji.name: role.id }, "exclusive": False } save_json(os.path.join("config", "settings.json"), raw_settings)
def set_verification_role(role: discord.Role): """ Sets the verification role :param role: Role to set to """ global verifications, raw_settings verifications["role"] = role raw_settings["verifications"]["role"] = role.id save_json(os.path.join("config", "settings.json"), raw_settings)
def remove_lockout(member: discord.Member): """ Removes a user from the lockout list :param member: Member to lockout """ global lockouts, raw_settings del lockouts[member] del raw_settings["lockouts"][str(member.id)] save_json(os.path.join("config", "settings.json"), raw_settings)
def set_muted_role(role: discord.Role): """ Adds a muted role :param role: Role to set to """ global guilds, raw_settings guilds[role.guild]["muted_role"] = role raw_settings["guilds"][str(role.guild.id)]["muted_role"] = role.id save_json(os.path.join("config", "settings.json"), raw_settings)
def clear_opt_in_roles(guild: discord.Guild): """ Clears opt-in roles :param guild: Guild to clear opt-in roles for """ global guilds, raw_settings guilds[guild]["opt_in_roles"] = raw_settings["guilds"][str( guild.id)]["access_roles"] = [] save_json(os.path.join("config", "settings.json"), raw_settings)
def clear_staff_channel(guild: discord.Guild): """ Clears the staff channel for the guild :param guild: Guild to clear staff channel for """ global guilds, raw_settings guilds[guild]["logging"]["staff"] = raw_settings["guilds"][str( guild.id)]["logging"]["staff"] = None save_json(os.path.join("config", "settings.json"), raw_settings)
def remove_command_channel(channel: discord.TextChannel): """ Removes a command channel :param channel: Channel to remove """ global guilds, raw_settings raw_settings["guilds"][str(channel.guild.id)]["command_channels"].remove( channel.id) guilds[channel.guild]["command_channels"].remove(channel) save_json(os.path.join("config", "settings.json"), raw_settings)
def add_command_channel(channel: discord.TextChannel): """ Adds a command channel for a guild :param channel: Channel to add """ global guilds, raw_settings raw_settings["guilds"][str(channel.guild.id)]["command_channels"].append( channel.id) guilds[channel.guild]["command_channels"].append(channel) save_json(os.path.join("config", "settings.json"), raw_settings)
def remove_announcement_channel(channel: discord.TextChannel): """ Adds an announcement channel for a guild :param channel: Channel to add """ global guilds, raw_settings raw_settings["guilds"][str( channel.guild.id)]["announcement_channels"].remove(channel.id) guilds[channel.guild]["announcement_channels"].remove(channel) save_json(os.path.join("config", "settings.json"), raw_settings)