async def rename_theme(self, ctx, *, query): """Rename a theme in the guild.""" themes = db.get(ctx.guild.id, "themes") try: before, after = query.split("|") except ValueError: raise UserInputError( "Command should be formatted as: $t.rn <theme> | <name>") # Find the correct color to remove. or dont. theme = theme_lookup(before.strip(), themes) if not theme: raise UserInputError("Couldn't find that theme") after = after.strip() if not after: raise UserInputError( "Command should be formatted as: $rename <color> | <name>") db.guilds.update_one({ "_id": ctx.guild.id, "themes": theme }, {"$set": { "themes.$.name": after }}) await ctx.invoke(self.bot.get_command("themes"))
def check_attachment(a): _supported = ((".png", ".jpg", ".jpeg", ".webp", ".gif") if not png else (".png", ".jpg", ".jpeg")) if not any(a.filename.endswith(suffix) for suffix in _supported): raise UserInputError("Unsupported file type.") max_filesize = 1024 * 1024 * 3 # 3 mb if a.size > max_filesize: raise UserInputError("Attachments must be under 3 megabytes.") max_width, max_height = 2048, 2048 if a.width > max_width: raise UserInputError( "Attachments must be under 2048 pixels in width.") if a.height > max_height: raise UserInputError( "Attachments must be under 2048 pixels in height.") return True
def fetch_count(self): fetched_counts = fetch_counts(self.url.long_url, self.tags) if fetched_counts == 0: raise UserInputError(f'Could not find posts with tags {self.tags}') self.paginator.post_count = min(1000, fetched_counts)
async def overwrite_theme(self, ctx, *, themename): """Overwrite one of the Guild's themes with another.""" colors, themes = db.get_many(ctx.guild.id, "colors", "themes") old_theme = theme_lookup(themename, themes) if not old_theme: raise UserInputError("Could not find that theme") # Remove unnecessary role attribute from database for color in colors: del color["role"] # create and add color new_theme = { "name": old_theme["name"], "colors": colors, } # update database db.guilds.update_one({ "_id": ctx.guild.id, "themes": old_theme }, {"$set": { "themes.$": new_theme }}) if ctx.guild.id not in cfg.suppress_output: await ctx.invoke(self.bot.get_command("themes"))
async def save_theme(self, ctx, *, name=""): """Save the current state of the guilds colors""" colors, themes = db.get_many(ctx.guild.id, "colors", "themes") if not colors: raise CommandError("There must be colors to save a theme") if len(themes) >= cfg.theme_limit: raise CommandError(f"Theme Limit Reached ({len(themes)}/10)") # Verufy name if "|" in name or len(name) >= 100: raise UserInputError( "Color names must be shorter than 100 characters and cannot include `|`" ) if not name: name = f"Theme {len(themes) + 1}" # Remove unnecessary role attribute from database for color in colors: del color["role"] # create and add color new_theme = { "name": name, "colors": colors, } # update database db.guilds.update_one({"_id": ctx.guild.id}, {"$push": { "themes": new_theme }}) await ctx.invoke(self.bot.get_command("themes")) # show new set
async def check_disallowed_tags(ctx: Context): tags = ctx.kwargs.get('tags') or '' disallowed_tags = tag_util.get_disallowed_tags(tags) if len(disallowed_tags) > 0: tag_txt = ', '.join(disallowed_tags) raise UserInputError(f'You are not allowed to search for: {tag_txt}')
async def hangman(self, ctx): """Starts up a game of hangman""" authorize(ctx, "mentions") # check for a mentioned user p1 = ctx.author p2 = ctx.message.mentions[0] # first mentioned user if p1 == p2: raise UserInputError("Can't play against yourself")
async def convert(self, ctx, argument): converter = self.original_converter if issubclass(converter, Converter): converter = converter() if isinstance(converter, Converter): converter = converter.convert result = await converter(ctx, argument) if await maybe_coroutine(self.filter_function, result): return result raise UserInputError()
def parsed_tags(self, tags: str, score: int) -> str: split_tags = tags.split(' ') if len(split_tags) > 2: raise UserInputError( f'Cannot search for more than 2 tags. You entered {len(split_tags)}.' ) if len(split_tags) == 2: return tags return super().parsed_tags(tags, score)
async def battleship(self, ctx): """Starts up a game of battleship.""" authorize(ctx, "mentions") # check for a mentioned user. p1 = Player.get(ctx.author.id) p2 = Player.get(ctx.message.mentions[0].id) if p1 == p2: raise UserInputError("Can't play against yourself") game = BattleShip(ctx.channel, p1, p2)
async def convert(self, ctx: Context, argument: str) -> str: """Ensure the extension exists and return the full extension path.""" argument = argument.lower() if "." not in argument: argument = f"xythrion.extensions.{argument}" if argument in EXTENSIONS: return argument raise UserInputError(f"Invalid argument {argument}")
def authorize(ctx, *args, **kwargs): """Check certain perms and assure passing.""" # Check if a user was mentioned if "mentions" in args and not ctx.message.mentions: raise UserInputError( "You need to mention a user for that command to work") if "registered" in args and classes.Player.get(ctx.author.id): raise RegistrationError("Already Registered") return True
async def tictactoe(self, ctx): """Starts up a game of tic tac toe with another user""" authorize(ctx, "mentions") # check for a mentioned user p1 = Player.get(ctx.author.id) p2 = Player.get(ctx.message.mentions[0].id) if p1 == p2: raise UserInputError("You can't play against yourself") # Create new game game = TicTacToe(ctx.channel, p1, p2) # draw and send board await game.update()
async def create_message(self): self.paginator.post_count = self.fetcher.fetch_count() if self.paginator.post_count == 0: raise UserInputError('No posts found.') self.fetcher.fetch_for_page(self.paginator.page, self.channel) self.message = await self.channel.send(**self.page_content().to_dict()) if self.message.guild: self.bot.add_listener(self.on_reaction_add) else: self.bot.add_listener(self.on_raw_reaction_add) await self.add_emojis()
async def rock_paper_scissors(self, ctx): """Starts up a game of rock paper scissors with another user""" authorize(ctx, "mentions") # check for a mentioned user p1 = Player.get(ctx.author.id) p2 = Player.get(ctx.message.mentions[0].id) # Ensure player is someone else if p1 == p2: raise UserInputError("You can't play against yourself") # Create new game embed = discord.Embed( title="Rock Paper Scissors", description= f"{p1.name} **VS** {p2.name}\n\nCheck DMs for how to play") await ctx.send(embed=embed) game = RPS(ctx.channel, p1, p2) await game.send_dms()
async def convert(self, ctx, argument): """Converts keyword arguments to booleans if they match the keyword name. Args: ctx (Context): The bot context. argument (str): The argument value. Returns: bool: Whether the argument matches the expected text. Raises: UserInputError: If the argument doesn't match and is not None. """ if argument == self.text_to_match: return True elif argument is None: return False else: raise UserInputError( f"{self.text_to_match.capitalize()} arg can only be `{self.text_to_match}` or nothing. Does your" " command have an unquoted alias?")
async def import_colors(self, ctx, *, name): """Save a preset as a theme.""" themes = db.get(ctx.guild.id, "themes") if len(themes) >= cfg.theme_limit: raise CommandError(f"Theme Limit Reached ({len(themes)}/10)") # Read in preset as dict name = name.replace(" ", "") try: with open(f"assets{sep}presets{sep}{name.lower()}.json" ) as preset_data: preset = json.load(preset_data) except FileNotFoundError: raise UserInputError("Could not find that preset") db.guilds.update_one({"_id": ctx.guild.id}, {"$push": { "themes": preset }}) if ctx.guild.id not in cfg.suppress_output: await ctx.invoke(self.bot.get_command("themes"))
async def check_in(self, ctx: commands.Context, word_count: NaturalInteger, *, message: str): """!kazhelp brief: BLOTS weekly check-in. description: | BLOTS weekly check-in. Enter your **total** word (or page) count and a brief update message. If your project type is "words", enter your word_count in words (total). If your project type is "visual" or "script", enter your total number of pages instead. See also {{!checkin type}}. Check-ins are **only** allowed from {{checkin_window_start}} to {{checkin_window_end}}, unless you are a mod or a member of the following roles: {{checkin_anytime_roles}}. The start and end of the checkin window are announced in the channel. parameters: - name: word_count type: number description: Your total word count (or total pages, depending on set project type). Do **not** include the word 'words' or 'pages'. - name: message type: string description: Your progress update. Maximum length 1000 characters. examples: - command: ".checkin 304882 Finished chapter 82 and developed some of the social and economic fallout of the Potato Battle of 1912." """ # check if allowed to checkin at the current time msg_time = ctx.message.timestamp window = self.c.get_check_in_window(msg_time) is_in_window = window[0] <= msg_time <= window[1] is_anytime = set(ctx.message.author.roles) & set( self.checkin_anytime_roles) if not check_mod(ctx) and not is_in_window and not is_anytime: import calendar window_name = "from {0} {2} to {1} {2}".format( calendar.day_name[window[0].weekday()], calendar.day_name[window[1].weekday()], self.c.checkin_time.strftime('%H:%M') + ' UTC') raise UserInputError( "**You cannot check-in right now!** Check-ins are {}. Need help? Ask us in #meta!" .format(window_name)) # validate argument word_count = word_count # type: int # for IDE type checking if word_count < 0: raise commands.BadArgument("word_count must be greater than 0.") if not message: raise commands.BadArgument("Check-in message is required.") # store the checkin check_in = self.c.save_check_in(member=ctx.message.author, word_count=word_count, message=message, timestamp=ctx.message.timestamp) start, end = self.c.get_check_in_week(ctx.message.timestamp) await self.bot.say( "{} Check-in for {:d} {} recorded for the week of {} to {}. Thanks!" .format(ctx.message.author.mention, check_in.word_count, self.PROJECT_UNIT_MAP[check_in.project_type], format_date(start), format_date(end)))
async def convert(self, ctx, argument): _method = float if self._ else int try: return _method(argument) except ValueError: raise UserInputError()
async def load_theme(self, ctx, *, themename): """Change the active colors to a theme.""" themes = db.get(ctx.guild.id, "themes") theme = theme_lookup(themename, themes) output_suppressed = ctx.guild.id in cfg.suppress_output if not theme: raise UserInputError("Could not find that theme") if not output_suppressed: embed = discord.Embed(title=f"Clearing Colors {loading_emoji()}") msg = await ctx.send(embed=embed) # Supress output from clear_colors and prevent other commands from modifying colors cfg.heavy_command_active.add(ctx.guild.id) cfg.suppress_output.add(ctx.guild.id) await ctx.invoke(self.bot.get_command("clear_colors")) # clear colors if not output_suppressed: cfg.suppress_output.discard(ctx.guild.id) # Progress update embed = discord.Embed(title=f"Creating Roles {loading_emoji()}") await msg.edit(embed=embed) # kind of a monster and probably impractical but it works # keeps only colors that have members that can be found owned_colors = [ color for color in theme["colors"] if color["members"] and all([ ctx.guild.get_member(member_id) for member_id in color["members"] ]) ] # Update colors in db colors = deepcopy(theme["colors"]) for color in colors: color["role"] = None color["members"] = [] db.guilds.update_one({"_id": ctx.guild.id}, {"$set": { "colors": colors }}) cm_pairs = [] # Color and Member pairs for color in owned_colors: # create role role = await ColorAssignment.create_role(ctx.guild, color) color["role"] = role.id # add to color member pair for member_id in color["members"]: cm_pairs.append((color, ctx.guild.get_member(member_id))) # Progress update if not output_suppressed: embed = discord.Embed(title=f"Applying Color {loading_emoji()}") await msg.edit(embed=embed) # loop and apply colors for color, member in cm_pairs: await ColorAssignment.color(member, color) await asyncio.sleep(1) cfg.heavy_command_active.discard(ctx.guild.id) # report success if ctx.guild.id not in cfg.suppress_output: success_embed = discord.Embed( title=f"Loaded {theme['name']} {check_emoji()}", color=discord.Color.green()) await msg.edit(embed=success_embed) await ctx.invoke(self.bot.get_command("colors"))