Example #1
0
def _make_install_cog_func(
    cogs: List[CogItem], repo_list: Dict[str, RepoItem]
) -> Callable[[
        commands.Context,
        Union[List[str], List[discord.Embed]],
        Dict[Any, Callable[..., Awaitable[Any]]],
        discord.Message,
        int,
        float,
        str,
], Awaitable[Any], ]:
    async def install_cog(
        ctx: commands.Context,
        pages: Union[List[str], List[discord.Embed]],
        controls: Dict[Any, Callable[..., Awaitable[Any]]],
        message: discord.Message,
        page: int,
        timeout: float,
        emoji: str,
    ) -> Any:
        cog_item = cogs[page]
        if (repo_item := repo_list.get(cog_item["repo_name"])) is None:
            await ctx.send("Error: The repo for this cog is unknown.")
            return menu(ctx, pages, controls, message, page, timeout)

        downloader = cast(Optional[Downloader], ctx.bot.get_cog("Downloader"))
        if downloader is None:
            await ctx.send("Error: Downloader is not loaded.")
            return menu(ctx, pages, controls, message, page, timeout)

        url = repo_item["repo_url"]
        if (repo := get_repo_by_url(downloader, url)) is None:
            msg = await ctx.send(
                "Error: Repository with this URL couldn't have been found.\n"
                "Do you want to add it?")
            start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            await ctx.bot.wait_for("reaction_add", check=pred)
            result = cast(bool, pred.result)
            if not result:
                return menu(ctx, pages, controls, message, page, timeout)

            command = downloader._repo_add
            fake_context = await get_fake_context(ctx, command)

            branch = branch if (branch := repo_item["branch"]) != "-" else None
            await command(fake_context, repo_item["repo_name"], url, branch)
            if (repo := get_repo_by_url(downloader, url)) is None:
                await ctx.send(
                    "Error: I couldn't find the repo after adding it to Downloader."
                )
                return menu(ctx, pages, controls, message, page, timeout)
Example #2
0
    async def all(self, ctx: commands.Context):
        """List all commands and how many time they have been used."""
        message = "\n".join("- {cmd}: Used {count} time.".format(
            cmd=inline(d[0]), count=d[1]["count"]) for d in sorted(
                self.commands.items(),
                key=lambda infos: infos[1]["count"],
                reverse=True,
            ))

        embeds = []
        embed_base = discord.Embed(
            color=await ctx.embed_color(),
            title="All commands usage since last reboot:")
        embed_base.set_footer(
            text="Requested by {author}".format(author=ctx.author.name),
            icon_url=ctx.author.avatar_url,
        )
        for text in pagify(message):
            again_embed = embed_base.copy()
            again_embed.description = text
            embeds.append(again_embed)

        if len(embeds) > 1:
            self.bot.loop.create_task(
                menu(ctx, embeds, DEFAULT_CONTROLS, timeout=300))
        else:
            await ctx.send(embed=embeds[0])
Example #3
0
 async def embed_convert_error(ctx: commands.Context, error_type: str, error: Exception):
     embed = discord.Embed(
         color=await ctx.embed_color(),
         title=f"{error_type}: `{type(error).__name__}`",
         description=f"```py\n{error}\n```",
     )
     embed.set_footer(
         text=f"Use `{ctx.prefix}help {ctx.command.qualified_name}` to see an example"
     )
     asyncio.create_task(menus.menu(ctx, [embed], {"❌": menus.close_menu}))
     raise CheckFailure
Example #4
0
 async def install_cog(
     ctx: commands.Context,
     pages: Union[List[str], List[discord.Embed]],
     controls: Dict[Any, Callable[..., Awaitable[Any]]],
     message: discord.Message,
     page: int,
     timeout: float,
     emoji: str,
 ) -> Any:
     cog_item = cogs[page]
     if (repo_item := repo_list.get(cog_item["repo_name"])) is None:
         await ctx.send("Error: The repo for this cog is unknown.")
         return menu(ctx, pages, controls, message, page, timeout)
Example #5
0
 async def embed_convert_error(self, ctx: commands.Context, error_type: str,
                               error: Exception):
     embed = discord.Embed(
         color=await ctx.embed_color(),
         title=error_type,
         description=f"```py\n{error}\n```",
     )
     embed.set_footer(
         text=
         f"Use `{ctx.prefix}help {ctx.command.qualified_name}` to see an example"
     )
     emoji = ctx.bot.get_emoji(736038541364297738) or "❌"
     asyncio.create_task(menus.menu(ctx, [embed],
                                    {emoji: menus.close_menu}))
     raise CheckFailure
Example #6
0
    async def lyrics(self, ctx: commands.Context, *, song_name: Optional[str]):
        """Return the lyrics of a given music/song name or running music.

        This command can also find out the music you're actually listening to.
        Powered by KSoft.Si.
        """
        music = await self.determine_music_source(ctx, song_name)
        if not music and not song_name:
            await ctx.send_help()
            return
        try:
            client = await self.obtain_client()
        except AttributeError:
            await ctx.send(
                "Not key for KSoft.Si has been set, ask owner to add a key.")
            return
        try:
            music_lyrics = await client.music.lyrics(music)
        except ksoftapi.NoResults:
            await ctx.send("No lyrics were found for your music.")
            return
        except ksoftapi.APIError as e:
            await ctx.send("The API returned an unknown error: {error}".format(
                error=inline(str(e))))
            return
        except ksoftapi.Forbidden:
            await ctx.send("Request forbidden by the API.")
            return
        except KeyError:
            await ctx.send(
                "The set API key seem to be wrong. Please contact the bot owner."
            )
            return
        music = await self.get_song(ctx, music_lyrics, bool(song_name))
        if music is None:
            return
        embeds = await self.make_embed(music, ctx)
        if len(embeds) > 1:
            create_task(
                menu(ctx, embeds, DEFAULT_CONTROLS,
                     timeout=600))  # No await since max_concurrency is there
        else:
            await ctx.send(embed=embeds[0])
Example #7
0
def construct_menu(
    ctx: commands.Context,
    pages: Union[List[str], List[discord.Embed]],
    cogs: List[CogItem],
    repo_list: Dict[str, RepoItem],
    *,
    allow_install: bool = False,
) -> Awaitable[Any]:
    if allow_install:
        controls = {
            **DEFAULT_CONTROLS,
            DOWNWARDS_ARROW:
            _make_install_cog_func(cogs, repo_list),
        }
    else:
        # Red isn't typed that well (+ this is recursive type),
        # and I don't want to deal with this
        controls = DEFAULT_CONTROLS  # type: ignore[assignment]

    return menu(ctx, pages, controls)
Example #8
0
 async def page_logic(self,
                      ctx: commands.Context,
                      dictionary: dict,
                      item: str,
                      field_num: int = 15) -> None:
     """Convert a dictionary into a pagified embed"""
     embeds = []
     count = 0
     title = item
     embed = Embed.create(self,
                          ctx=ctx,
                          title=title,
                          thumbnail=ctx.guild.icon_url)
     if len(dictionary.keys()) > field_num:
         for key, value in dictionary.items():
             if count == field_num - 1:
                 embed.add_field(name=key, value=value, inline=True)
                 embeds.append(embed)
                 embed = Embed.create(self,
                                      ctx=ctx,
                                      title=title,
                                      thumbnail=ctx.guild.icon_url)
                 count = 0
             else:
                 embed.add_field(name=key, value=value, inline=True)
                 count += 1
         else:
             embeds.append(embed)
     else:
         for key, value in dictionary.items():
             embed.add_field(name=key, value=value, inline=True)
         embeds.append(embed)
     msg = await ctx.send(embed=embeds[0])
     control = menus.DEFAULT_CONTROLS if len(embeds) > 1 else {
         "\N{CROSS MARK}": menus.close_menu
     }
     asyncio.create_task(menus.menu(ctx, embeds, control, message=msg))
     menus.start_adding_reactions(msg, control.keys())
Example #9
0
    async def lyrics(self, ctx: commands.Context, *, song_name: str):
        """Return the lyrics of a given music/song name.

        Powered by KSoft.Si.
        """
        song_name = BOT_SONG_RE.sub("", song_name)
        try:
            client = await self.obtain_client()
        except AttributeError:
            await ctx.send("Not key for KSoft.Si has been set, ask owner to add a key.")
            return
        try:
            music_lyrics = await client.music.lyrics(song_name)
        except ksoftapi.NoResults:
            await ctx.send("No lyrics were found for your music.")
            return
        except ksoftapi.APIError as e:
            await ctx.send(
                "The API returned an unknown error: {error}".format(error=inline(str(e)))
            )
            return
        except ksoftapi.Forbidden:
            await ctx.send("Request forbidden by the API.")
            return
        except KeyError:
            await ctx.send("The set API key seem to be wrong. Please contact the bot owner.")
            return
        message, available_musics = await self._title_choose(music_lyrics)
        bot_message = await ctx.maybe_send_embed(message)
        predicator = MessagePredicate.less(10, ctx)
        try:
            user_message = await self.bot.wait_for("message", check=predicator, timeout=60)
            await bot_message.delete()
        except Te:
            await ctx.send("Rude.")
            await bot_message.delete()
            return

        chosen_music = user_message.content
        if chosen_music not in available_musics:
            await ctx.send(
                "I was unable to find the corresponding music in the available music list."
            )
            return
        music = available_musics[chosen_music]
        embeds = []
        color = await ctx.embed_color()
        for text in pagify(music.lyrics):
            embed = discord.Embed(color=color, title=music.name, description=None)
            embed.set_thumbnail(
                url=music.album_art
                if str(music.album_art) != "https://cdn.ksoft.si/images/Logo1024%20-%20W.png"
                else discord.Embed.Empty
            )
            embed.set_footer(text="Powered by KSoft.Si.", icon_url=ctx.author.avatar_url)
            embed.description = text
            embeds.append(embed)
        if len(embeds) > 1:
            create_task(
                menu(ctx, embeds, DEFAULT_CONTROLS, timeout=600)
            )  # No await since max_concurrency is here
        else:
            await ctx.send(embed=embeds[0])
Example #10
0
                return menu(ctx, pages, controls, message, page, timeout)

            command = downloader._repo_add
            fake_context = await get_fake_context(ctx, command)

            branch = branch if (branch := repo_item["branch"]) != "-" else None
            await command(fake_context, repo_item["repo_name"], url, branch)
            if (repo := get_repo_by_url(downloader, url)) is None:
                await ctx.send(
                    "Error: I couldn't find the repo after adding it to Downloader."
                )
                return menu(ctx, pages, controls, message, page, timeout)

        await downloader._cog_install(ctx, repo, cog_item["name"])

        return menu(ctx, pages, controls, message, page, timeout)

    return install_cog


def construct_menu(
    ctx: commands.Context,
    pages: Union[List[str], List[discord.Embed]],
    cogs: List[CogItem],
    repo_list: Dict[str, RepoItem],
    *,
    allow_install: bool = False,
) -> Awaitable[Any]:
    if allow_install:
        controls = {
            **DEFAULT_CONTROLS,
Example #11
0
async def update_profile(bot, user_data: dict, author: discord.User):
    msg = await author.send(
        "What country are you from (Enter the number next to the country)?")
    country_data = WorldData.get("country", {})
    validcountries = sorted(
        list(value.get("name") for _, value in country_data.items()))
    desc = ""
    valid_county_list = []
    for index, value in enumerate(validcountries, start=1):
        desc += f"{index}. {value}\n"
        valid_county_list.append(str(index))
    pages = [
        box(page, lang="md") for page in list(pagify(desc, shorten_by=20))
    ]
    ctx = namedtuple("Context", "author me bot send channel")
    new_ctx = ctx(author, bot.user, bot, author.send, msg.channel)
    menu_task = asyncio.create_task(
        menu(new_ctx, pages, DEFAULT_CONTROLS, timeout=180))
    country = None
    pred_check = MessagePredicate.contained_in(valid_county_list, ctx=new_ctx)
    while not country:
        with contextlib.suppress(asyncio.TimeoutError):
            await bot.wait_for("message", timeout=30.0, check=pred_check)
        country = (valid_county_list[pred_check.result]
                   if pred_check.result is not None else None)
    with contextlib.suppress(Exception):
        menu_task.cancel()
    user_data["country"] = validcountries[int(country) - 1]
    cached_country = user_data["country"].lower().strip()

    if cached_country:
        country_data = WorldData.get("country", {})
        region = country_data.get(cached_country, {}).get("region")
        country_timezones = country_data.get(cached_country,
                                             {}).get("timezones")
        user_data["subzone"] = country_data.get(cached_country,
                                                {}).get("subregion")
    else:
        region = None
        country_timezones = None

    continent_data = sorted(CONTINENT_DATA.values())

    if not region:
        await author.send("Which zone are you from?")
        embed = discord.Embed(title="Pick a number that matches your zone")
        desc = ""
        valid_continent_list = []
        for index, value in enumerate(continent_data, start=1):
            desc += f"{index}. {value.title()}\n"
            valid_continent_list.append(str(index))
        embed.description = box(desc, lang="md")
        await author.send(embed=embed)
        zone = None
        pred_check = MessagePredicate.contained_in(valid_continent_list,
                                                   ctx=new_ctx)
        while not zone:
            with contextlib.suppress(asyncio.TimeoutError):
                await bot.wait_for("message", timeout=30.0, check=pred_check)
            zone = (valid_continent_list[pred_check.result]
                    if pred_check.result is not None else None)
        user_data["zone"] = continent_data[int(zone) - 1]
    else:
        user_data["zone"] = country_data.get(cached_country,
                                             {}).get("region", None)

    user_data["language"] = None

    if country_timezones and len(country_timezones) > 1:
        country_timezones_dict = {
            str(i): key
            for i, key in enumerate(country_timezones, start=1)
        }
        country_timezones = sorted(country_timezones_dict.values())

        await author.send(
            "There are multiple timezone for your country, please pick the one that match yours?"
        )
        embed = discord.Embed(title="Pick a number that matches your timezone")
        desc = ""
        valid_timezone_list = []
        for index, value in enumerate(country_timezones, start=1):
            desc += f"{index}. {value.upper()}\n"
            valid_timezone_list.append(str(index))

        embed.description = box(desc, lang="md")
        await author.send(embed=embed)
        timezone = None
        pred_check = MessagePredicate.contained_in(valid_timezone_list,
                                                   ctx=new_ctx)
        while not timezone:
            with contextlib.suppress(asyncio.TimeoutError):
                await bot.wait_for("message", timeout=30.0, check=pred_check)
            timezone = (valid_timezone_list[pred_check.result]
                        if pred_check.result is not None else None)
        user_data["timezone"] = country_timezones[int(timezone) - 1]
    elif country_timezones and len(country_timezones) == 1:
        user_data["timezone"] = country_timezones[0]

    return user_data
Example #12
0
    async def awbadge(self, ctx, tier: str = None, group: int = None):
        """Get alliance war badges."""
        if group is not None and group >= 1 and group < 4:
            group_num = group - 1  # This is to make sure that it will work with the urls
        tiers = {
            "master": [
                "https://media.discordapp.net/attachments/401476363707744257/738083791654092940/47EFB6D4D1380ABD2C40D2C7B0533A29245F7955.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083791113027654/650E29ADB8C5C382FF5A358113B2C02B8EADA415.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083791440052294/08BA0A081A9D56E35E60E3FD61FAB7ED9A10CD00.png"
            ],
            "platinum": [
                "https://media.discordapp.net/attachments/401476363707744257/738083790718631937/E78E2BAF9B0C9BA6C7FE45BE726FFB0B0B0CACFD.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083790362116116/487EA26A1BA0F2C2848E7C87F10430BD218C2178.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083790559117352/0ED8BD10441C6D086AEB7BBA5271269F46E009D1.png"
            ],
            "gold": [
                "https://media.discordapp.net/attachments/401476363707744257/738083790131298375/76BC21BF523A415866D19814BD8AF4BE16EF30A9.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083998462509096/8CD52FEB7540016B6ABA1EC67B9F1777E3C29878.png",
                "https://media.discordapp.net/attachments/401476363707744257/738084001926873098/3A9A8FDA006D0BE225242AAA5909021CD52BCFB3.png"
            ],
            "silver": [
                "https://media.discordapp.net/attachments/401476363707744257/738084001465499789/4B389D377A94EDA747B38DF640C0B33A3A3F61AE.png",
                "https://media.discordapp.net/attachments/401476363707744257/738084001465499789/4B389D377A94EDA747B38DF640C0B33A3A3F61AE.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083994612006914/5302FA8FA04735224847C8BBF82D1D54C8567B9C.png"
            ],
            "bronze": [
                "https://media.discordapp.net/attachments/401476363707744257/738083995211792404/719AC2C2AB5833D815C899DAF9ADB7CF11819CBA.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083993043337276/E636A90C3F0DFFDAED0176D972AA0C73F3E40FF8.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083997866786876/5B06D509847E0FA1405A50021486C1A5D8C6F9B2.png"
            ],
            "stone": [
                "https://media.discordapp.net/attachments/401476363707744257/738083996054978730/9AC92A2FDC2996C346125296356C664373147F2F.png",
                "https://media.discordapp.net/attachments/401476363707744257/738083993681002586/BF3D13EACC9F44216E754884AA183185761C84CF.png",
                "https://media.discordapp.net/attachments/401476363707744257/738084098857238670/EA938C0B0C2AE3E6DB91514F5F8768C4F033D373.png"
            ]
        }
        tier = tier.lower() if tier is not None else None
        if tier is None or tier not in tiers:
            embed = Embed.create(
                self, ctx, title="Alliance War Badge Tiers",
                description="Please choose one of the tiers below :arrow_down:\nSyntax: `,awbadge <tier>`"
            )
            normal = "\n".join([t.capitalize() for t in tiers.keys()])
            embed.add_field(
                # Unfortunatly I have to do this to make sure that participation gets in the list :/
                name="Badges", value="{}\nParticipation".format(normal)
            )

            normal = "\n".join(tiers)
            return await ctx.send(embed=embed)
        if tier == "participation":
            embed = Embed.create(
                self, ctx, title="Participation",
                image="https://media.discordapp.net/attachments/401476363707744257/738083790886535228/DA7D39277836A9CF1B39A68D37EAF99999B366C7.png"
            )
            return await ctx.send(embed=embed)
        if group is None:
            embeds = []
            for i in range(3):
                embed = Embed.create(
                    self, ctx,
                    title="{} Badges".format(tier.capitalize()), image=tiers[tier][i]
                )
                embeds.append(embed)
            msg = await ctx.send(embed=embeds[0])
            control = menus.DEFAULT_CONTROLS if len(embeds) > 1 else {
                "\N{CROSS MARK}": menus.close_menu
            }
            asyncio.create_task(menus.menu(ctx, embeds, control, message=msg))
            menus.start_adding_reactions(msg, control.keys())
        else:
            embed = Embed.create(
                self, ctx,
                title="{} Badge".format(tier.capitalize()), description="{} {}".format(tier.capitalize(), group),
                image=tiers[tier][group_num]
            )
            await ctx.send(embed=embed)