示例#1
0
    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"))
示例#2
0
 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
示例#3
0
    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)
示例#4
0
    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"))
示例#5
0
    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
示例#6
0
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}')
示例#7
0
    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")
示例#8
0
 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()
示例#9
0
    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)
示例#10
0
    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)
示例#11
0
    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}")
示例#12
0
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
示例#13
0
    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()
示例#14
0
    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()
示例#15
0
    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()
示例#16
0
    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?")
示例#17
0
    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"))
示例#18
0
    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)))
示例#19
0
 async def convert(self, ctx, argument):
     _method = float if self._ else int
     try:
         return _method(argument)
     except ValueError:
         raise UserInputError()
示例#20
0
    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"))