Exemple #1
0
 async def convert(self, ctx, argument) -> int:
     try:
         argument = int(argument)
     except ValueError:
         raise BadArgument("The provided input must be a number.")
     if argument == -1:
         return argument
     if argument < -1:
         raise BadArgument("You must provide a number greater than -1.")
     return max(min(100, argument), 0)
Exemple #2
0
 async def convert(self, ctx: commands.Context, argument: str) -> dict:
     query = {}
     argument = argument.replace("🧑‍🎨", ":artist:")
     # because discord will replace this in URI's automatically 🙄
     rec_str = r"|".join(i for i in VALID_RECOMMENDATIONS.keys())
     find_rec = re.compile(fr"({rec_str})\W(.+)", flags=re.I)
     if not ctx.cog.GENRES:
         try:
             ctx.cog.GENRES = await ctx.cog._spotify_client.recommendation_genre_seeds(
             )
         except Exception:
             raise BadArgument(
                 _("The bot owner needs to set their Spotify credentials "
                   "before this command can be used."
                   " See `{prefix}spotify set creds` for more details.").
                 format(prefix=ctx.clean_prefix))
     genre_str = r"|".join(i for i in ctx.cog.GENRES)
     find_genre = re.compile(fr"\b({genre_str})\b", flags=re.I)
     find_extra = find_rec.finditer(argument)
     genres = list(find_genre.findall(argument))
     song_data = SPOTIFY_RE.finditer(argument)
     tracks: List[str] = []
     artists: List[str] = []
     if song_data:
         for match in song_data:
             if match.group(2) == "track":
                 tracks.append(match.group(3))
             if match.group(2) == "artist":
                 artists.append(match.group(3))
     query = {
         "artist_ids": artists if artists else None,
         "genres": genres if genres else None,
         "track_ids": tracks if tracks else None,
         "limit": 100,
         "market": "from_token",
     }
     for match in find_extra:
         try:
             num_or_str = match.group(2).isdigit()
             if num_or_str:
                 result = VALID_RECOMMENDATIONS[match.group(1)](int(
                     match.group(2)))
             else:
                 result = VALID_RECOMMENDATIONS[match.group(1)](
                     match.group(2))
             query[f"target_{match.group(1)}"] = result
         except Exception:
             log.exception("cannot match")
             continue
     if not any([query[k] for k in ["artist_ids", "genres", "track_ids"]]):
         raise BadArgument(
             _("You must provide either an artist or track seed or a genre for this to work"
               ))
     return query
Exemple #3
0
 async def convert(self, ctx: commands.Context,
                   argument: str) -> StarboardEntry:
     cog = ctx.cog
     guild = ctx.guild
     if guild.id not in cog.starboards:
         raise BadArgument(
             _("There are no starboards setup on this server!"))
     try:
         starboard = cog.starboards[guild.id][argument.lower()]
     except KeyError:
         raise BadArgument(
             _("There is no starboard named {name}").format(name=argument))
     return starboard
Exemple #4
0
 async def convert(self, ctx, argument):
     result = None
     if argument.isdigit():
         if int(argument) > 118 or int(argument) < 1:
             raise BadArgument("`{}` is not a valid element!".format(argument))
         result = ELEMENTS(int(argument))
     else:
         try:
             result = ELEMENTS(argument.title())
         except Exception:
             raise BadArgument("`{}` is not a valid element!".format(argument))
     if not result:
         raise BadArgument("`{}` is not a valid element!".format(argument))
     return result
Exemple #5
0
    async def detect_file(self, ctx):
        if ctx.message.attachments:
            file = ctx.message.attachments[0].url

            if not file.endswith(".txt"):
                raise BadArgument(".txt files only")

        try:
            content = await http.get(file, no_cache=True)
        except Exception:
            raise BadArgument("Invalid .txt file")

        if not content:
            raise BadArgument("File you've provided is empty")
        return content
Exemple #6
0
    async def convert(self, ctx, argument):
        attachments = ctx.message.attachments
        mentions = MENTION_REGEX.finditer(argument)
        matches = IMAGE_LINKS.finditer(argument)
        ids = ID_REGEX.finditer(argument)
        urls = []
        if matches:
            for match in matches:
                urls.append(match.group(1))
        if mentions:
            for mention in mentions:
                user = ctx.guild.get_member(int(mention.group(1)))
                if user is not None:
                    if user.is_avatar_animated():
                        url = IMAGE_LINKS.search(str(user.avatar_url_as(format="gif")))
                        urls.append(url.group(1))
                    else:
                        url = IMAGE_LINKS.search(str(user.avatar_url_as(format="png")))
                        urls.append(url.group(1))
        if not urls and ids:
            for possible_id in ids:
                user = ctx.guild.get_member(int(possible_id.group(0)))
                if user:
                    if user.is_avatar_animated():
                        url = IMAGE_LINKS.search(str(user.avatar_url_as(format="gif")))
                        urls.append(url.group(1))
                    else:
                        url = IMAGE_LINKS.search(str(user.avatar_url_as(format="png")))
                        urls.append(url.group(1))
        if attachments:
            for attachment in attachments:
                urls.append(attachment.url)

        if not urls:
            if ctx.guild:
                user = ctx.guild.get_member_named(argument)
                if user:
                    if user.is_avatar_animated():
                        url = user.avatar_url_as(format="gif")
                        urls.append(url)
                    else:
                        url = user.avatar_url_as(format="png")
                        urls.append(url)
                else:
                    raise BadArgument("No images provided.")
        if not urls:
            raise BadArgument("No images provided.")
        return urls[0]
Exemple #7
0
    async def set_text_pageable(self,
                                *,
                                embed_name: str,
                                field_title: str,
                                pages: t.List[str],
                                author: discord.Member = None,
                                channel: discord.TextChannel,
                                timeout: int = 60):

        if not isinstance(pages, t.List):
            pages = [pages]

        if not all(isinstance(p, str) for p in pages):
            raise BadArgument(
                'All paginate text pages need to be of type string')

        embed = discord.Embed(title=embed_name, color=Colors.ClemsonOrange)
        # set the first page of the embed
        embed.add_field(name=field_title, value=pages[0])
        embed.set_footer(text=f'Page 1 of {len(pages)}')
        msg = await channel.send(embed=embed)

        # stores the message info
        message = Message(pages,
                          0,
                          author.id if author else None,
                          embed_name=embed_name,
                          field_title=field_title)
        self.messages[msg.id] = message
        await self.send_scroll_reactions(msg, author, timeout)
Exemple #8
0
 async def convert(self, ctx: commands.Context, argument: str):
     guild = ctx.guild
     result = None
     id_match = self._get_id_match(argument)
     channel_match = re.match(r"<#([0-9]+)>$", argument)
     member_match = re.match(r"<@!?([0-9]+)>$", argument)
     role_match = re.match(r"<@&([0-9]+)>$", argument)
     for converter in ["channel", "role", "member"]:
         if converter == "channel":
             match = id_match or channel_match
             if match:
                 channel_id = match.group(1)
                 result = guild.get_channel(int(channel_id))
             else:
                 result = discord.utils.get(guild.text_channels, name=argument)
         if converter == "member":
             match = id_match or member_match
             if match:
                 member_id = match.group(1)
                 result = guild.get_member(int(member_id))
             else:
                 result = guild.get_member_named(argument)
         if converter == "role":
             match = id_match or role_match
             if match:
                 role_id = match.group(1)
                 result = guild.get_role(int(role_id))
             else:
                 result = discord.utils.get(guild._roles.values(), name=argument)
         if result:
             break
     if not result:
         msg = _("{arg} is not a valid channel, user or role.").format(arg=argument)
         raise BadArgument(msg)
     return result
Exemple #9
0
    def convert(self):
        message = self.ctx.message
        bot = self.ctx.bot
        match = self._get_id_match() or re.match(r'<@!?([0-9]+)>$',
                                                 self.argument)
        server = message.server
        result = None
        if match is None:
            # not a mention...
            if server:
                result = server.get_member_named(self.argument)
            if result is None:
                result = _get_from_servers(bot, 'get_member_named',
                                           self.argument)
        else:
            user_id = match.group(1)
            if server:
                result = server.get_member(user_id)
            if result is None:
                result = _get_from_servers(bot, 'get_member', user_id)

        if result is None:
            raise BadArgument('User "{}" not found'.format(self.argument))

        return result
Exemple #10
0
    async def convert(self, ctx: commands.Context, argument: str) -> List[discord.Member]:
        bot = ctx.bot
        match = self._get_id_match(argument) or re.match(r"<@!?([0-9]+)>$", argument)
        guild = ctx.guild
        result = []
        if match is None:
            # Not a mention
            if guild:
                for m in process.extract(
                    argument,
                    {m: unidecode(m.name) for m in guild.members},
                    limit=None,
                    score_cutoff=75,
                ):
                    result.append(m[2])
                for m in process.extract(
                    argument,
                    {m: unidecode(m.nick) for m in guild.members if m.nick and m not in result},
                    limit=None,
                    score_cutoff=75,
                ):
                    result.append(m[2])
        else:
            user_id = int(match.group(1))
            if guild:
                result.append(guild.get_member(user_id))
            else:
                result.append(_get_from_guilds(bot, "get_member", user_id))

        if not result or result == [None]:
            raise BadArgument('Member "{}" not found'.format(argument))

        return result
Exemple #11
0
 def get_item_id(cls, ctx, item_code: int):
     if item_code < 0 or item_code >= len(items):
         raise BadArgument(
             f"item_id must be an integer in the range of 0 and {len(items)}"
         )
     item = list(items.keys())[item_code]
     return cls(ctx.cog.bot, item, items[item])
Exemple #12
0
 async def convert(self, ctx: commands.Context, argument: str) -> re.Match:
     match = SPOTIFY_RE.match(argument)
     if not match:
         raise BadArgument(
             _("{argument} is not a valid Spotify URL or URI.").format(
                 argument=argument))
     return match
Exemple #13
0
 async def convert(self, ctx: commands.Context, argument: str) -> str:
     valid_types = [
         "user-read-private",
         "user-top-read",
         "user-read-recently-played",
         "user-follow-read",
         "user-library-read",
         "user-read-currently-playing",
         "user-read-playback-state",
         "user-read-playback-position",
         "playlist-read-collaborative",
         "playlist-read-private",
         "user-follow-modify",
         "user-library-modify",
         "user-modify-playback-state",
         "playlist-modify-public",
         "playlist-modify-private",
         "ugc-image-upload",
     ]
     find = argument.lower()
     if find not in valid_types:
         raise BadArgument(
             _("{argument} is not a valid scope.").format(
                 argument=argument))
     return find
Exemple #14
0
    async def convert(self, ctx, argument):
        message = ctx.message
        channel = ctx.message.channel
        attachments = ctx.message.attachments
        mentions = ctx.message.mentions
        match = IMAGE_LINKS.match(argument)
        emoji = EMOJI_REGEX.match(argument)
        urls = []
        if match:
            urls.append(match.group(1))
        if emoji:
            ext = "gif" if argument.startswith("<a") else "png"
            url = "https://cdn.discordapp.com/emojis/{id}.{ext}?v=1".format(
                id=emoji.group(1), ext=ext)
            urls.append(url)
        if mentions:
            for user in mentions:
                if user.is_avatar_animated():
                    urls.append(user.avatar_url_as(format="gif"))
                else:
                    urls.append(user.avatar_url_as(format="png"))
        if attachments:
            for attachment in attachments:
                urls.append(attachment.url)

        if not urls:
            raise BadArgument("No images provided.")
        return urls
Exemple #15
0
    async def get_user_choice(cls, ctx: Context, search_query: str, entries: List[Tuple[str]]) -> int:

        em = Embed(colour=cls._embed_colour,)
        em.set_author(name=f'{cls._track_type} search results - {search_query} - Requested by {ctx.author}')

        for index, entry in enumerate(entries, 1):
            em.add_field(
                name=f'{index} - {entry[0]}', value=entry[1], inline=False)

        search_message = await ctx.send(embed=em)
        ensure_future(add_numeric_reactions(search_message, len(entries)))

        def check(react: Reaction, user: User):
            return any((
                    react.message.id == search_message.id,
                    user == ctx.author,
                    react.emoji in (numeric_emoji(n) for n in range(1, 1+len(entries)))
            ))

        try:
            reaction, _ = await ctx.bot.wait_for('reaction_add', check=check, timeout=60)

        except TimeoutError:
            raise BadArgument("You did not choose a search result in time.")

        await search_message.delete()
        return int(reaction.emoji[0]) - 1
Exemple #16
0
    async def convert(
        self, ctx: Context, argument: str
    ) -> Optional[Union[List[Dict[str, dict]], str]]:
        result: Optional[Union[List[Dict[str, dict]], str]] = []
        team_list = await check_valid_team(argument)
        my_perms = ctx.channel.permissions_for(ctx.guild.me)
        if team_list == []:
            raise BadArgument('Team "{}" not found'.format(argument))
        if len(team_list) == 1:
            result = team_list[0]
        else:
            # This is just some extra stuff to correct the team picker
            msg = _("There's multiple teams with that name, pick one of these:\n")
            new_msg = None
            if my_perms.add_reactions and my_perms.use_external_emojis:
                new_msg = await ctx.send(msg)
                team_emojis = [
                    await EmojiConverter().convert(ctx, "<:" + TEAMS[team]["emoji"] + ">")
                    for team in team_list
                ]
                log.debug(team_emojis)
                log.debug(team_list)
                pred = ReactionPredicate.with_emojis(team_emojis, message=new_msg)
                start_adding_reactions(new_msg, team_emojis)
                try:
                    reaction, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60)
                except asyncio.TimeoutError:
                    await new_msg.edit(content=_("I guess not."))
                    return None
                else:
                    result = team_list[pred.result]
                    log.debug(result)
            else:
                for i, team_name in enumerate(team_list):
                    msg += "{}: {}\n".format(i + 1, team_name)

                def msg_check(m):
                    return m.author == ctx.message.author

                try:
                    msg = await ctx.bot.wait_for("message", check=msg_check, timeout=60)
                except asyncio.TimeoutError:
                    await new_msg.edit(content=_("I guess not."))
                    return None

                if msg.content.isdigit():
                    msg = int(msg.content) - 1
                    try:
                        result = team_list[msg]
                    except (IndexError, ValueError, AttributeError):
                        pass
                else:
                    return_team = None
                    for team in team_list:
                        if msg.content.lower() in team.lower():
                            return_team = team
                    result = return_team
            if new_msg:
                await new_msg.delete()
        return result
Exemple #17
0
 async def convert(self, ctx: Context, argument: str) -> re.Match:
     find = YEAR_RE.search(argument)
     if find:
         return find
     else:
         raise BadArgument(
             _("`{arg}` is not a valid year.").format(arg=argument))
Exemple #18
0
    async def convert(self, ctx: Context, argument: str) -> TextChannel:
        bot = ctx.bot

        search = self._get_id_match(argument) or match(r'<#([0-9]+)>$',
                                                       argument)

        if match is None:
            # not a mention
            if ctx.guild:
                result = get(ctx.guild.text_channels, name=argument)
            else:

                def check(c):
                    return isinstance(c, TextChannel) and c.name == argument

                result = find(check, bot.get_all_channels())
        else:
            channel_id = int(search.group(1))
            if ctx.guild:
                result = ctx.guild.get_channel(channel_id)
            else:
                result = _get_from_guilds(bot, 'get_channel', channel_id)

        if not isinstance(result, TextChannel):
            raise BadArgument('Channel "{}" not found.'.format(argument))

        return result
Exemple #19
0
    async def convert(self, ctx, argument):
        if argument is None:
            return ctx.bot.get_user(ctx.message.author.id)
        match = self._get_id_match(argument) or re.match(
            r'<@!?([0-9]+)>$', argument)
        result = None
        state = ctx._state

        if match is not None:
            user_id = int(match.group(1))
            result = ctx.bot.get_user(user_id)
        else:
            arg = argument
            # Check if argument contains one of the following phrases
            if arg in ["me", "-", ".", "self"]:
                # Return message author's user
                result = ctx.bot.get_user(ctx.message.author.id)
            # check for discriminator if it exists
            if len(arg) > 5 and arg[-5] == '#':
                discrim = arg[-4:]
                name = arg[:-5]
                predicate = lambda u: u.name == name and u.discriminator == discrim
                result = discord.utils.find(predicate, state._users.values())
            if result is not None:
                return result

            predicate = lambda u: u.name == arg
            result = discord.utils.find(predicate, state._users.values())

        if result is None:
            raise BadArgument('User "{}" not found'.format(argument))

        return result
Exemple #20
0
 async def convert(self, ctx: commands.Context, argument: str) -> str:
     possible_results = {
         "allpvp": {"code": "allPvP", "alt": ["pvp"]},
         "patrol": {"code": "patrol", "alt": []},
         "raid": {"code": "raid", "alt": ["all"]},
         "story": {"code": "story", "alt": []},
         "allstrikes": {"code": "allStrikes", "alt": ["strikes", "strike"]},
         "allpve": {"code": "allPvE", "alt": ["pve"]},
         "allpvecompetitive": {"code": "allPvECompetitive", "alt": ["gambit"]},
     }
     result = None
     argument = argument.lower()
     if argument in possible_results:
         result = possible_results[argument]["code"]
     else:
         for k, v in possible_results.items():
             if argument in v["alt"]:
                 result = v["code"]
     if not result:
         raise BadArgument(
             _("That is not an available stats page, pick from these: {activity_list}").format(
                 activity_list=humanize_list(list(possible_results.keys()))
             )
         )
     return result
Exemple #21
0
    async def convert(self, ctx, argument):
        bot = ctx.bot
        match = self._get_id_match(argument) or re.match(
            r'<@!?([0-9]+)>$', argument)
        guild = ctx.guild
        result = None
        if match is None:
            # not a mention...
            if guild:
                result = guild.get_member_named(argument)
            else:
                result = _get_from_guilds(bot, 'get_member_named', argument)
        else:
            user_id = int(match.group(1))
            if guild:
                result = guild.get_member(user_id)
            else:
                result = _get_from_guilds(bot, 'get_member', user_id)
        if urlparse(argument).scheme in ["http", "https"]:
            result = argument

        if result is None:
            raise BadArgument(
                f"{argument} is neither a Member nor a valid URL")

        return result
Exemple #22
0
    async def set_embed_pageable(self,
                                 *,
                                 pages: t.List[discord.Embed],
                                 author: discord.Member = None,
                                 channel: discord.TextChannel,
                                 timeout: int = 60):

        if not isinstance(pages, t.List):
            pages = [pages]

        if not all(isinstance(p, discord.Embed) for p in pages):
            raise BadArgument(
                'All paginate embed pages need to be of type discord.Embed')

        pages[0].set_footer(text=f'Page 1 of {len(pages)}')
        # send the first initial embed
        msg = await channel.send(embed=pages[0])
        await self.bot.messenger.publish(Events.on_set_deletable,
                                         msg=msg,
                                         author=msg.author)

        # stores the message info
        message = Message(pages, 0, author.id if author else None)
        self.messages[msg.id] = message
        await self.send_scroll_reactions(msg, author, timeout)
Exemple #23
0
def point_range(argument) -> typing.Optional[list]:
    if '-' in argument:
        argument = argument.split('-')
        if len(argument) != 2:
            raise BadArgument('Too many -, invalid range')
        try:
            point_high = int(argument[0])
            point_low = int(argument[1])
            return [point_high, point_low]
        except ValueError as e:
            raise BadArgument('Point values are not an integer')
    try:
        point_high = point_low = int(argument)
        return [point_high, point_low]
    except ValueError as e:
        raise BadArgument('Point value is not an integer')
Exemple #24
0
    async def convert(self, ctx: Context,
                      duration: str) -> t.Union[int, float]:
        """
        Convert a `duration` string into a relativedelta using
        super `TimeDelta` converter. After that, simply change
        the relative delta into the amount of seconds it represents.

        Accepted inputs (in order):
        * infinity inputs: `-1`, `inf`, `infinity`, `infinite`
        * zero inputs: `0`, `none`, `null`
        * `TimeDelta` converter inputs
        """
        duration = duration.lower()

        if duration in ["-1", "inf", "infinite", "infinity"]:
            return float("inf")
        if duration in ["0", "none", "null"]:
            return 0

        delta = await super().convert(ctx, duration)

        now = datetime.utcnow()
        try:
            diff = (now + delta) - now
        except ValueError:
            raise BadArgument("Specified duration is outside maximum range.")

        return diff.total_seconds()
Exemple #25
0
    async def convert(self, ctx, argument) -> List[discord.Member]:
        bot = ctx.bot
        match = self._get_id_match(argument) or re.match(r"<@!?([0-9]+)>$", argument)
        guild = ctx.guild
        result = []
        if match is None:
            # Not a mention
            if guild:
                for m in guild.members:
                    if argument.lower() in unidecode.unidecode(m.display_name.lower()):
                        # display_name so we can get the nick of the user first
                        # without being NoneType and then check username if that matches
                        # what we're expecting
                        result.append(m)
                        continue
                    if argument.lower() in unidecode.unidecode(m.name.lower()):
                        result.append(m)
                        continue
        else:
            user_id = int(match.group(1))
            if guild:
                result.append(guild.get_member(user_id))
            else:
                result.append(_get_from_guilds(bot, "get_member", user_id))

        if not result:
            raise BadArgument('Member "{}" not found'.format(argument))

        return result
Exemple #26
0
 def strip_options(self, result: Dict[str, Union[List[str], str, bool,
                                                 timedelta]],
                   argument: str):
     possible_options = OPTIONS_RE.match(argument)
     if not possible_options:
         raise BadArgument("You have no options for this poll.")
     options = [
         s.strip() for s in SPLIT_RE.split(possible_options[0])
         if s.strip()
     ]
     if len(options) > 20:
         raise BadArgument(
             "Use less options for the poll. Max options: 20.")
     result["options"] = options
     no_options = OPTIONS_RE.sub("", argument)
     return result, no_options
Exemple #27
0
 async def search_for_images(
     self, ctx: commands.Context
 ) -> List[Union[discord.Asset, discord.Attachment, str]]:
     urls = []
     if not ctx.channel.permissions_for(ctx.me).read_message_history:
         raise BadArgument("I require read message history perms to find images.")
     async for message in ctx.channel.history(limit=10):
         if message.attachments:
             for attachment in message.attachments:
                 urls.append(attachment)
         match = IMAGE_LINKS.match(message.content)
         if match:
             urls.append(match.group(1))
     if not urls:
         raise BadArgument("No Images found in recent history.")
     return urls
Exemple #28
0
    async def convert(self, ctx, argument):
        match = self._get_id_match(argument) or re.match(
            r'<@!?([0-9]+)>$', argument)
        guild = ctx.guild
        result = None
        user_id = None
        if match is None:
            # not a mention...
            if guild:
                result = guild.get_member_named(argument)
        else:
            user_id = int(match.group(1))
            if guild:
                result = guild.get_member(user_id) or discord.utils.get(
                    ctx.message.mentions, id=user_id)

        if result is None and guild and user_id:
            try:
                _message_cache[guild.id]["users"][user_id]
            except KeyError:
                pass
            else:
                result = CacheUser(_id=user_id, guild=guild)

        if result is None:
            raise BadArgument(
                "User not found in the guild nor in the recorded messages.")

        return result
Exemple #29
0
async def detect_file(ctx):
    print(ctx.message.attachments)
    if ctx.message.attachments:
        file = ctx.message.attachments[0].url

        if not file.endswith(".txt"):
            raise BadArgument("只接受txt檔")
    else:
        raise
    try:
        content = await http.get(file, no_cache=True)
    except Exception:
        raise BadArgument("無效的txt檔")

    if not content:
        raise BadArgument("你提供的檔案是空的")
    return content
Exemple #30
0
def parse_gimme(argument) -> typing.Optional[str]:
    keywords = [
        'adhoc', 'Ad Hoc', 'math', 'Advanced Math', 'Intermediate Math',
        'Simple Math', 'bf', 'Brute Force', 'ctf', 'Capture the Flag', 'ds',
        'Data Structures', 'd&c', 'Divide and Conquer', 'dp',
        'Dynamic Programming', 'geo', 'Geometry', 'gt', 'Graph Theory',
        'greedy', 'Greedy Algorithms', 'regex', 'Regular Expressions',
        'string', 'String Algorithms'
    ]
    if argument in keywords:
        raise BadArgument("Argument is keyword")

    try:
        print(point_range(argument))
    except BadArgument:
        return argument.replace('\'', '')
    raise BadArgument("Argument is point range")