예제 #1
0
    async def bankset_showsettings(self, ctx: commands.Context):
        """Show the current bank settings."""
        cur_setting = await bank.is_global()
        if cur_setting:
            group = bank._config
        else:
            if not ctx.guild:
                return
            group = bank._config.guild(ctx.guild)
        group_data = await group.all()
        bank_name = group_data["bank_name"]
        bank_scope = _("Global") if cur_setting else _("Server")
        currency_name = group_data["currency"]
        default_balance = group_data["default_balance"]
        max_balance = group_data["max_balance"]

        settings = _(
            "Bank settings:\n\nBank name: {bank_name}\nBank scope: {bank_scope}\n"
            "Currency: {currency_name}\nDefault balance: {default_balance}\n"
            "Maximum allowed balance: {maximum_bal}\n").format(
                bank_name=bank_name,
                bank_scope=bank_scope,
                currency_name=currency_name,
                default_balance=humanize_number(default_balance),
                maximum_bal=humanize_number(max_balance),
            )
        await ctx.send(box(settings))
예제 #2
0
    async def command_equalizer_reset(self, ctx: commands.Context):
        """Reset the eq to 0 across all bands."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Modify Preset"),
                description=_("You need the DJ role to reset the equalizer."),
            )
        player = lavalink.get_player(ctx.guild.id)
        eq = player.fetch("eq", Equalizer())

        for band in range(eq.band_count):
            eq.set_gain(band, 0.0)

        await self._apply_gains(ctx.guild.id, eq.bands)
        await self.config.custom("EQUALIZER",
                                 ctx.guild.id).eq_bands.set(eq.bands)
        player.store("eq", eq)
        await self._eq_msg_clear(player.fetch("eq_message"))
        message = await ctx.send(
            content=box(eq.visualise(), lang="ini"),
            embed=discord.Embed(colour=await ctx.embed_colour(),
                                title=_("Equalizer values have been reset.")),
        )
        player.store("eq_message", message)
예제 #3
0
 async def economyset_showsettings(self, ctx: commands.Context):
     """
     Shows the current economy settings
     """
     guild = ctx.guild
     if await bank.is_global():
         conf = self.config
     else:
         conf = self.config.guild(guild)
     await ctx.send(
         box(
             _("----Economy Settings---\n"
               "Minimum slot bid: {slot_min}\n"
               "Maximum slot bid: {slot_max}\n"
               "Slot cooldown: {slot_time}\n"
               "Payday amount: {payday_amount}\n"
               "Payday cooldown: {payday_time}\n"
               "Amount given at account registration: {register_amount}\n"
               "Maximum allowed balance: {maximum_bal}").format(
                   slot_min=humanize_number(await conf.SLOT_MIN()),
                   slot_max=humanize_number(await conf.SLOT_MAX()),
                   slot_time=humanize_number(await conf.SLOT_TIME()),
                   payday_time=humanize_number(await conf.PAYDAY_TIME()),
                   payday_amount=humanize_number(await
                                                 conf.PAYDAY_CREDITS()),
                   register_amount=humanize_number(
                       await bank.get_default_balance(guild)),
                   maximum_bal=humanize_number(await
                                               bank.get_max_balance(guild)),
               )))
예제 #4
0
    async def custom_trivia_list(self, ctx: commands.Context):
        """List uploaded custom trivia."""
        personal_lists = sorted(
            [p.resolve().stem for p in cog_data_path(self).glob("*.yaml")])
        no_lists_uploaded = _("No custom Trivia lists uploaded.")

        if not personal_lists:
            if await ctx.embed_requested():
                await ctx.send(
                    embed=discord.Embed(colour=await ctx.embed_colour(),
                                        description=no_lists_uploaded))
            else:
                await ctx.send(no_lists_uploaded)
            return

        if await ctx.embed_requested():
            await ctx.send(embed=discord.Embed(
                title=_("Uploaded trivia lists"),
                colour=await ctx.embed_colour(),
                description=", ".join(sorted(personal_lists)),
            ))
        else:
            msg = box(
                bold(_("Uploaded trivia lists")) + "\n\n" +
                ", ".join(sorted(personal_lists)))
            if len(msg) > 1000:
                await ctx.author.send(msg)
            else:
                await ctx.send(msg)
예제 #5
0
    async def cc_search(self, ctx: commands.Context, *, query):
        """
        Searches through custom commands, according to the query.

        Uses fuzzywuzzy searching to find close matches.

        **Arguments:**

        - `<query>` The query to search for. Can be multiple words.
        """
        cc_commands = await CommandObj.get_commands(self.config.guild(ctx.guild))
        extracted = process.extract(query, list(cc_commands.keys()))
        accepted = []
        for entry in extracted:
            if entry[1] > 60:
                # Match was decently strong
                accepted.append((entry[0], cc_commands[entry[0]]))
            else:
                # Match wasn't strong enough
                pass
        if len(accepted) == 0:
            return await ctx.send(_("No close matches were found."))
        results = self.prepare_command_list(ctx, accepted)
        if await ctx.embed_requested():
            content = " \n".join(map("**{0[0]}** {0[1]}".format, results))
            embed = discord.Embed(
                title=_("Search results"), description=content, colour=await ctx.embed_colour()
            )
            await ctx.send(embed=embed)
        else:
            content = "\n".join(map("{0[0]:<12} : {0[1]}".format, results))
            await ctx.send(_("The following matches have been found:") + box(content))
예제 #6
0
    async def send_leaderboard(self, ctx: commands.Context, data: dict,
                               key: str, top: int):
        """Send the leaderboard from the given data.

        Parameters
        ----------
        ctx : commands.Context
            The context to send the leaderboard to.
        data : dict
            The data for the leaderboard. This must map `discord.Member` ->
            `dict`.
        key : str
            The field to sort the data by. Can be ``wins``, ``total_score``,
            ``games`` or ``average_score``.
        top : int
            The number of members to display on the leaderboard.

        Returns
        -------
        `list` of `discord.Message`
            The sent leaderboard messages.

        """
        if not data:
            await ctx.send(_("There are no scores on record!"))
            return
        leaderboard = self._get_leaderboard(data, key, top)
        ret = []
        for page in pagify(leaderboard, shorten_by=10):
            ret.append(await ctx.send(box(page, lang="py")))
        return ret
예제 #7
0
    async def set_cases(self, ctx: commands.Context, action: str = None):
        """Enable or disable case creation for a mod action."""
        guild = ctx.guild

        if action is None:  # No args given
            casetypes = await modlog.get_all_casetypes(guild)
            await ctx.send_help()
            lines = []
            for ct in casetypes:
                enabled = _("enabled") if await ct.is_enabled() else _(
                    "disabled")
                lines.append(f"{ct.name} : {enabled}")

            await ctx.send(_("Current settings:\n") + box("\n".join(lines)))
            return

        casetype = await modlog.get_casetype(action, guild)
        if not casetype:
            await ctx.send(_("That action is not registered."))
        else:
            enabled = await casetype.is_enabled()
            await casetype.set_enabled(not enabled)
            await ctx.send(
                _("Case creation for {action_name} actions is now {enabled}.").
                format(action_name=action,
                       enabled=_("enabled") if not enabled else _("disabled")))
예제 #8
0
    async def command_equalizer(self, ctx: commands.Context):
        """Equalizer management."""
        if not self._player_check(ctx):
            ctx.command.reset_cooldown(ctx)
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        player = lavalink.get_player(ctx.guild.id)
        eq = player.fetch("eq", Equalizer())
        reactions = [
            "\N{BLACK LEFT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "\N{LEFTWARDS BLACK ARROW}\N{VARIATION SELECTOR-16}",
            "\N{BLACK UP-POINTING DOUBLE TRIANGLE}",
            "\N{UP-POINTING SMALL RED TRIANGLE}",
            "\N{DOWN-POINTING SMALL RED TRIANGLE}",
            "\N{BLACK DOWN-POINTING DOUBLE TRIANGLE}",
            "\N{BLACK RIGHTWARDS ARROW}\N{VARIATION SELECTOR-16}",
            "\N{BLACK RIGHT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "\N{BLACK CIRCLE FOR RECORD}\N{VARIATION SELECTOR-16}",
            "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}",
        ]
        await self._eq_msg_clear(player.fetch("eq_message"))
        eq_message = await ctx.send(box(eq.visualise(), lang="ini"))

        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            with contextlib.suppress(discord.HTTPException):
                await eq_message.add_reaction(
                    "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}")
        else:
            start_adding_reactions(eq_message, reactions)

        eq_msg_with_reacts = await ctx.fetch_message(eq_message.id)
        player.store("eq_message", eq_msg_with_reacts)
        await self._eq_interact(ctx, player, eq, eq_msg_with_reacts, 0)
예제 #9
0
    async def discover_guild(
        self,
        author: discord.User,
        *,
        mod: bool = False,
        permissions: Union[discord.Permissions, dict] = None,
        prompt: str = "",
    ):
        """
        discovers which of shared guilds between the bot
        and provided user based on conditions (mod or permissions is an or)

        prompt is for providing a user prompt for selection
        """
        shared_guilds = []
        if permissions is None:
            perms = discord.Permissions()
        elif isinstance(permissions, discord.Permissions):
            perms = permissions
        else:
            perms = discord.Permissions(**permissions)

        async for guild in AsyncIter(self.bot.guilds, steps=100):
            x = guild.get_member(author.id)
            if x is not None:
                if await self.internal_filter(x, mod, perms):
                    shared_guilds.append(guild)
        if len(shared_guilds) == 0:
            raise ValueError("No Qualifying Shared Guilds")
        if len(shared_guilds) == 1:
            return shared_guilds[0]
        output = ""
        guilds = sorted(shared_guilds, key=lambda g: g.name)
        for i, guild in enumerate(guilds, 1):
            output += "{}: {}\n".format(i, guild.name)
        output += "\n{}".format(prompt)

        for page in pagify(output, delims=["\n"]):
            await author.send(box(page))

        try:
            message = await self.bot.wait_for(
                "message",
                check=MessagePredicate.same_context(channel=author.dm_channel, user=author),
                timeout=45,
            )
        except asyncio.TimeoutError:
            await author.send(_("You took too long to select. Try again later."))
            return None

        try:
            message = int(message.content.strip())
            guild = guilds[message - 1]
        except (ValueError, IndexError):
            await author.send(_("That wasn't a valid choice."))
            return None
        else:
            return guild
예제 #10
0
 async def modset_showsettings(self, ctx: commands.Context):
     """Show the current server administration settings."""
     guild = ctx.guild
     data = await self.config.guild(guild).all()
     delete_repeats = data["delete_repeats"]
     warn_mention_spam = data["mention_spam"]["warn"]
     kick_mention_spam = data["mention_spam"]["kick"]
     ban_mention_spam = data["mention_spam"]["ban"]
     strict_mention_spam = data["mention_spam"]["strict"]
     respect_hierarchy = data["respect_hierarchy"]
     delete_delay = data["delete_delay"]
     reinvite_on_unban = data["reinvite_on_unban"]
     dm_on_kickban = data["dm_on_kickban"]
     default_days = data["default_days"]
     default_tempban_duration = data["default_tempban_duration"]
     msg = ""
     msg += _("Delete repeats: {num_repeats}\n").format(
         num_repeats=_("after {num} repeats").format(
             num=delete_repeats) if delete_repeats != -1 else _("No"))
     msg += _("Warn mention spam: {num_mentions}\n").format(
         num_mentions=_("{num} mentions").format(
             num=warn_mention_spam) if warn_mention_spam else _("No"))
     msg += _("Kick mention spam: {num_mentions}\n").format(
         num_mentions=_("{num} mentions").format(
             num=kick_mention_spam) if kick_mention_spam else _("No"))
     msg += _("Ban mention spam: {num_mentions}\n").format(
         num_mentions=_("{num} mentions").format(
             num=ban_mention_spam) if ban_mention_spam else _("No"))
     msg += (_(
         "Mention Spam Strict: All mentions will count including duplicates\n"
     ) if strict_mention_spam else
             _("Mention Spam Strict: Only unique mentions will count\n"))
     msg += _("Respects hierarchy: {yes_or_no}\n").format(
         yes_or_no=_("Yes") if respect_hierarchy else _("No"))
     msg += _("Delete delay: {num_seconds}\n").format(
         num_seconds=_("{num} seconds").format(
             num=delete_delay) if delete_delay != -1 else _("None"))
     msg += _("Reinvite on unban: {yes_or_no}\n").format(
         yes_or_no=_("Yes") if reinvite_on_unban else _("No"))
     msg += _("Send message to users on kick/ban: {yes_or_no}\n").format(
         yes_or_no=_("Yes") if dm_on_kickban else _("No"))
     if default_days:
         msg += _(
             "Default message history delete on ban: Previous {num_days} days\n"
         ).format(num_days=default_days)
     else:
         msg += _(
             "Default message history delete on ban: Don't delete any\n")
     msg += _("Default tempban duration: {duration}").format(
         duration=humanize_timedelta(seconds=default_tempban_duration))
     await ctx.send(box(msg))
예제 #11
0
    async def selfrole_list(self, ctx: commands.Context):
        """
        Lists all available selfroles.
        """
        selfroles = await self._valid_selfroles(ctx.guild)
        fmt_selfroles = "\n".join(["+ " + r.name for r in selfroles])

        if not fmt_selfroles:
            await ctx.send("There are currently no selfroles.")
            return

        msg = _("Available Selfroles:\n{selfroles}").format(
            selfroles=fmt_selfroles)
        await ctx.send(box(msg, "diff"))
예제 #12
0
    async def command_equalizer_list(self, ctx: commands.Context):
        """List saved eq presets."""
        eq_presets = await self.config.custom("EQUALIZER",
                                              ctx.guild.id).eq_presets()
        if not eq_presets.keys():
            return await self.send_embed_msg(
                ctx, title=_("No saved equalizer presets."))

        space = "\N{EN SPACE}"
        header_name = _("Preset Name")
        header_author = _("Author")
        header = box(
            "[{header_name}]{space}[{header_author}]\n".format(
                header_name=header_name,
                space=space * 9,
                header_author=header_author),
            lang="ini",
        )
        preset_list = ""
        for preset, bands in eq_presets.items():
            try:
                author = self.bot.get_user(bands["author"])
            except TypeError:
                author = "None"
            msg = f"{preset}{space * (22 - len(preset))}{author}\n"
            preset_list += msg

        page_list = []
        colour = await ctx.embed_colour()
        for page in pagify(preset_list, delims=[", "], page_length=1000):
            formatted_page = box(page, lang="ini")
            embed = discord.Embed(colour=colour,
                                  description=f"{header}\n{formatted_page}")
            embed.set_footer(text=_("{num} preset(s)").format(
                num=humanize_number(len(list(eq_presets.keys())))))
            page_list.append(embed)
        await menu(ctx, page_list, DEFAULT_CONTROLS)
예제 #13
0
 def format_playlist_picker_data(self, pid, pname, ptracks, pauthor,
                                 scope) -> str:
     """Format the values into a prettified codeblock."""
     author = self.bot.get_user(pauthor) or pauthor or _("Unknown")
     line = _(" - Name:   <{pname}>\n"
              " - Scope:  < {scope} >\n"
              " - ID:     < {pid} >\n"
              " - Tracks: < {ptracks} >\n"
              " - Author: < {author} >\n\n").format(
                  pname=pname,
                  scope=self.humanize_scope(scope),
                  pid=pid,
                  ptracks=ptracks,
                  author=author)
     return box(line, lang="md")
예제 #14
0
    async def command_equalizer_load(self, ctx: commands.Context,
                                     eq_preset: str):
        """Load a saved eq preset."""
        eq_preset = eq_preset.lower()
        eq_presets = await self.config.custom("EQUALIZER",
                                              ctx.guild.id).eq_presets()
        try:
            eq_values = eq_presets[eq_preset]["bands"]
        except KeyError:
            return await self.send_embed_msg(
                ctx,
                title=_("No Preset Found"),
                description=_(
                    "Preset named {eq_preset} does not exist.".format(
                        eq_preset=eq_preset)),
            )
        except TypeError:
            eq_values = eq_presets[eq_preset]

        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        player = lavalink.get_player(ctx.guild.id)
        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Load Preset"),
                description=_(
                    "You need the DJ role to load equalizer presets."),
            )

        await self.config.custom("EQUALIZER",
                                 ctx.guild.id).eq_bands.set(eq_values)
        await self._eq_check(ctx, player)
        eq = player.fetch("eq", Equalizer())
        await self._eq_msg_clear(player.fetch("eq_message"))
        message = await ctx.send(
            content=box(eq.visualise(), lang="ini"),
            embed=discord.Embed(
                colour=await ctx.embed_colour(),
                title=_("The {eq_preset} preset was loaded.".format(
                    eq_preset=eq_preset)),
            ),
        )
        player.store("eq_message", message)
예제 #15
0
 async def trivia_list(self, ctx: commands.Context):
     """List available trivia categories."""
     lists = set(p.stem for p in self._all_lists())
     if await ctx.embed_requested():
         await ctx.send(embed=discord.Embed(
             title=_("Available trivia lists"),
             colour=await ctx.embed_colour(),
             description=", ".join(sorted(lists)),
         ))
     else:
         msg = box(
             bold(_("Available trivia lists")) + "\n\n" +
             ", ".join(sorted(lists)))
         if len(msg) > 1000:
             await ctx.author.send(msg)
         else:
             await ctx.send(msg)
예제 #16
0
 async def triviaset_showsettings(self, ctx: commands.Context):
     """Show the current trivia settings."""
     settings = self.config.guild(ctx.guild)
     settings_dict = await settings.all()
     msg = box(
         _("Current settings\n"
           "Bot gains points: {bot_plays}\n"
           "Answer time limit: {delay} seconds\n"
           "Lack of response timeout: {timeout} seconds\n"
           "Points to win: {max_score}\n"
           "Reveal answer on timeout: {reveal_answer}\n"
           "Payout multiplier: {payout_multiplier}\n"
           "Allow lists to override settings: {allow_override}").format(
               **settings_dict),
         lang="py",
     )
     await ctx.send(msg)
예제 #17
0
 async def permissions_acl_yaml_example(self, ctx: commands.Context):
     """Sends an example of the yaml layout for permissions"""
     await ctx.send(
         _("Example YAML for setting rules:\n") + box(
             textwrap.dedent("""\
                     COMMAND:
                         ping:
                             12345678901234567: true
                             56789012345671234: false
                     COG:
                         General:
                             56789012345671234: true
                             12345678901234567: false
                             default: false
                     """),
             lang="yaml",
         ))
예제 #18
0
 async def paginate_alias_list(self, ctx: commands.Context,
                               alias_list: List[AliasEntry]) -> None:
     names = sorted(["+ " + a.name for a in alias_list])
     message = "\n".join(names)
     temp = list(pagify(message, delims=["\n"], page_length=1850))
     alias_list = []
     count = 0
     for page in temp:
         count += 1
         page = page.lstrip("\n")
         page = (_("Aliases:\n") + page +
                 _("\n\nPage {page}/{total}").format(page=count,
                                                     total=len(temp)))
         alias_list.append(box("".join(page), "diff"))
     if len(alias_list) == 1:
         await ctx.send(alias_list[0])
         return
     await menu(ctx, alias_list, DEFAULT_CONTROLS)
예제 #19
0
async def format_fuzzy_results(
        ctx: Context,
        matched_commands: List[Command],
        *,
        embed: Optional[bool] = None) -> Union[str, discord.Embed]:
    """Format the result of a fuzzy command search.

    Parameters
    ----------
    ctx : `commands.Context <beastbot.core.commands.Context>`
        The context in which this result is being displayed.
    matched_commands : List[`commands.Command <beastbot.core.commands.Command>`]
        A list of commands which have been matched by the fuzzy search, sorted
        in order of decreasing similarity.
    embed : bool
        Whether or not the result should be an embed. If set to ``None``, this
        will default to the result of `ctx.embed_requested`.

    Returns
    -------
    Union[str, discord.Embed]
        The formatted results.

    """
    if embed is not False and (embed is True or await ctx.embed_requested()):
        lines = []
        for cmd in matched_commands:
            short_doc = cmd.format_shortdoc_for_context(ctx)
            lines.append(
                f"**{ctx.clean_prefix}{cmd.qualified_name}** {short_doc}")
        return discord.Embed(
            title="Perhaps you wanted one of these?",
            colour=await ctx.embed_colour(),
            description="\n".join(lines),
        )
    else:
        lines = []
        for cmd in matched_commands:
            short_doc = cmd.format_shortdoc_for_context(ctx)
            lines.append(
                f"{ctx.clean_prefix}{cmd.qualified_name} -- {short_doc}")
        return "Perhaps you wanted one of these? " + box("\n".join(lines),
                                                         lang="vhdl")
예제 #20
0
 async def command_llsetup_info(self, ctx: commands.Context):
     """Display Lavalink connection settings."""
     configs = await self.config.all()
     host = configs["host"]
     password = configs["password"]
     rest_port = configs["rest_port"]
     ws_port = configs["ws_port"]
     msg = "----" + _("Connection Settings") + "----        \n"
     msg += _("Host:             [{host}]\n").format(host=host)
     msg += _("WS Port:          [{port}]\n").format(port=ws_port)
     if ws_port != rest_port:
         msg += _("Rest Port:        [{port}]\n").format(port=rest_port)
     msg += _("Password:         [{password}]\n").format(password=password)
     try:
         await self.send_embed_msg(ctx.author,
                                   description=box(msg, lang="ini"))
     except discord.HTTPException:
         await ctx.send(
             _("I need to be able to DM you to send you this info."))
예제 #21
0
    async def command_equalizer_set(self, ctx: commands.Context,
                                    band_name_or_position, band_value: float):
        """Set an eq band with a band number or name and value.

        Band positions are 1-15 and values have a range of -0.25 to 1.0.
        Band names are 25, 40, 63, 100, 160, 250, 400, 630, 1k, 1.6k, 2.5k, 4k,
        6.3k, 10k, and 16k Hz.
        Setting a band value to -0.25 nullifies it while +0.25 is double.
        """
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Set Preset"),
                description=_(
                    "You need the DJ role to set equalizer presets."),
            )

        player = lavalink.get_player(ctx.guild.id)
        band_names = [
            "25",
            "40",
            "63",
            "100",
            "160",
            "250",
            "400",
            "630",
            "1k",
            "1.6k",
            "2.5k",
            "4k",
            "6.3k",
            "10k",
            "16k",
        ]

        eq = player.fetch("eq", Equalizer())
        bands_num = eq.band_count
        if band_value > 1:
            band_value = 1
        elif band_value <= -0.25:
            band_value = -0.25
        else:
            band_value = round(band_value, 1)

        try:
            band_number = int(band_name_or_position) - 1
        except ValueError:
            band_number = 1000

        if band_number not in range(
                0, bands_num) and band_name_or_position not in band_names:
            return await self.send_embed_msg(
                ctx,
                title=_("Invalid Band"),
                description=_(
                    "Valid band numbers are 1-15 or the band names listed in "
                    "the help for this command."),
            )

        if band_name_or_position in band_names:
            band_pos = band_names.index(band_name_or_position)
            band_int = False
            eq.set_gain(int(band_pos), band_value)
            await self._apply_gain(ctx.guild.id, int(band_pos), band_value)
        else:
            band_int = True
            eq.set_gain(band_number, band_value)
            await self._apply_gain(ctx.guild.id, band_number, band_value)

        await self._eq_msg_clear(player.fetch("eq_message"))
        await self.config.custom("EQUALIZER",
                                 ctx.guild.id).eq_bands.set(eq.bands)
        player.store("eq", eq)
        band_name = band_names[
            band_number] if band_int else band_name_or_position
        message = await ctx.send(
            content=box(eq.visualise(), lang="ini"),
            embed=discord.Embed(
                colour=await ctx.embed_colour(),
                title=_("Preset Modified"),
                description=_(
                    "The {band_name}Hz band has been set to {band_value}.").
                format(band_name=band_name, band_value=band_value),
            ),
        )
        player.store("eq_message", message)
예제 #22
0
 async def send_table(self):
     """Send a table of scores to the session's channel."""
     table = "+ Results: \n\n"
     for user, score in self.scores.most_common():
         table += "+ {}\t{}\n".format(user, score)
     await self.ctx.send(box(table, lang="diff"))
예제 #23
0
    async def cog_before_invoke(self, ctx: commands.Context) -> None:
        await self.cog_ready_event.wait()
        # check for unsupported arch
        # Check on this needs refactoring at a later date
        # so that we have a better way to handle the tasks
        if self.command_llsetup in [ctx.command, ctx.command.root_parent]:
            pass

        elif self.lavalink_connect_task and self.lavalink_connect_task.cancelled(
        ):
            await ctx.send(
                _("You have attempted to run Audio's Lavalink server on an unsupported"
                  " architecture. Only settings related commands will be available."
                  ))
            raise RuntimeError(
                "Not running audio command due to invalid machine architecture for Lavalink."
            )

        current_perms = ctx.channel.permissions_for(ctx.me)
        surpass_ignore = (isinstance(ctx.channel, discord.abc.PrivateChannel)
                          or await ctx.bot.is_owner(ctx.author)
                          or await ctx.bot.is_admin(ctx.author))
        guild = ctx.guild
        if guild and not current_perms.is_superset(self.permission_cache):
            current_perms_set = set(iter(current_perms))
            expected_perms_set = set(iter(self.permission_cache))
            diff = expected_perms_set - current_perms_set
            missing_perms = dict((i for i in diff if i[-1] is not False))
            missing_perms = OrderedDict(sorted(missing_perms.items()))
            missing_permissions = missing_perms.keys()
            log.debug(
                "Missing the following perms in %d, Owner ID: %d: %s",
                ctx.guild.id,
                ctx.guild.owner.id,
                humanize_list(list(missing_permissions)),
            )
            if not surpass_ignore:
                text = _("I'm missing permissions in this server, "
                         "Please address this as soon as possible.\n\n"
                         "Expected Permissions:\n")
                for perm, value in missing_perms.items():
                    text += "{perm}: [{status}]\n".format(
                        status=_("Enabled") if value else _("Disabled"),
                        perm=HUMANIZED_PERM.get(perm),
                    )
                text = text.strip()
                if current_perms.send_messages and current_perms.read_messages:
                    await ctx.send(box(text=text, lang="ini"))
                else:
                    log.info(
                        "Missing write permission in %d, Owner ID: %d",
                        ctx.guild.id,
                        ctx.guild.owner.id,
                    )
                raise CheckFailure(message=text)

        with contextlib.suppress(Exception):
            player = lavalink.get_player(ctx.guild.id)
            notify_channel = player.fetch("channel")
            if not notify_channel:
                player.store("channel", ctx.channel.id)

        self._daily_global_playlist_cache.setdefault(
            self.bot.user.id, await self.config.daily_playlists())
        if self.local_folder_current_path is None:
            self.local_folder_current_path = Path(await
                                                  self.config.localpath())
        if not ctx.guild:
            return

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        self._daily_playlist_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).daily_playlists())
        self._persist_queue_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).persist_queue())
        if dj_enabled:
            dj_role = self._dj_role_cache.setdefault(
                ctx.guild.id, await self.config.guild(ctx.guild).dj_role())
            dj_role_obj = ctx.guild.get_role(dj_role)
            if not dj_role_obj:
                await self.config.guild(ctx.guild).dj_enabled.set(None)
                self._dj_status_cache[ctx.guild.id] = None
                await self.config.guild(ctx.guild).dj_role.set(None)
                self._dj_role_cache[ctx.guild.id] = None
                await self.send_embed_msg(
                    ctx, title=_("No DJ role found. Disabling DJ mode."))
예제 #24
0
    async def leaderboard(self,
                          ctx: commands.Context,
                          top: int = 10,
                          show_global: bool = False):
        """Print the leaderboard.

        Defaults to top 10.

        Examples:
            - `[p]leaderboard`
            - `[p]leaderboard 50` - Shows the top 50 instead of top 10.
            - `[p]leaderboard 100 yes` - Shows the top 100 from all servers.

        **Arguments**

        - `<top>` How many positions on the leaderboard to show. Defaults to 10 if omitted.
        - `<show_global>` Whether to include results from all servers. This will default to false unless specified.
        """
        guild = ctx.guild
        author = ctx.author
        embed_requested = await ctx.embed_requested()
        footer_message = _("Page {page_num}/{page_len}.")
        max_bal = await bank.get_max_balance(ctx.guild)

        if top < 1:
            top = 10

        base_embed = discord.Embed(title=_("Economy Leaderboard"))
        if await bank.is_global() and show_global:
            # show_global is only applicable if bank is global
            bank_sorted = await bank.get_leaderboard(positions=top, guild=None)
            base_embed.set_author(name=ctx.bot.user.name,
                                  icon_url=ctx.bot.user.avatar_url)
        else:
            bank_sorted = await bank.get_leaderboard(positions=top,
                                                     guild=guild)
            if guild:
                base_embed.set_author(name=guild.name, icon_url=guild.icon_url)

        try:
            bal_len = len(humanize_number(bank_sorted[0][1]["balance"]))
            bal_len_max = len(humanize_number(max_bal))
            if bal_len > bal_len_max:
                bal_len = bal_len_max
            # first user is the largest we'll see
        except IndexError:
            return await ctx.send(_("There are no accounts in the bank."))
        pound_len = len(str(len(bank_sorted)))
        header = "{pound:{pound_len}}{score:{bal_len}}{name:2}\n".format(
            pound="#",
            name=_("Name"),
            score=_("Score"),
            bal_len=bal_len + 6,
            pound_len=pound_len + 3,
        )
        highscores = []
        pos = 1
        temp_msg = header
        for acc in bank_sorted:
            try:
                name = guild.get_member(acc[0]).display_name
            except AttributeError:
                user_id = ""
                if await ctx.bot.is_owner(ctx.author):
                    user_id = f"({str(acc[0])})"
                name = f"{acc[1]['name']} {user_id}"

            balance = acc[1]["balance"]
            if balance > max_bal:
                balance = max_bal
                await bank.set_balance(MOCK_MEMBER(acc[0], guild), balance)
            balance = humanize_number(balance)
            if acc[0] != author.id:
                temp_msg += (f"{f'{humanize_number(pos)}.': <{pound_len+2}} "
                             f"{balance: <{bal_len + 5}} {name}\n")

            else:
                temp_msg += (f"{f'{humanize_number(pos)}.': <{pound_len+2}} "
                             f"{balance: <{bal_len + 5}} "
                             f"<<{author.display_name}>>\n")
            if pos % 10 == 0:
                if embed_requested:
                    embed = base_embed.copy()
                    embed.description = box(temp_msg, lang="md")
                    embed.set_footer(text=footer_message.format(
                        page_num=len(highscores) + 1,
                        page_len=ceil(len(bank_sorted) / 10),
                    ))
                    highscores.append(embed)
                else:
                    highscores.append(box(temp_msg, lang="md"))
                temp_msg = header
            pos += 1

        if temp_msg != header:
            if embed_requested:
                embed = base_embed.copy()
                embed.description = box(temp_msg, lang="md")
                embed.set_footer(text=footer_message.format(
                    page_num=len(highscores) + 1,
                    page_len=ceil(len(bank_sorted) / 10),
                ))
                highscores.append(embed)
            else:
                highscores.append(box(temp_msg, lang="md"))

        if highscores:
            await menu(
                ctx,
                highscores,
                DEFAULT_CONTROLS
                if len(highscores) > 1 else {"\N{CROSS MARK}": close_menu},
            )
        else:
            await ctx.send(_("No balances found."))
예제 #25
0
    async def _eq_interact(
        self,
        ctx: commands.Context,
        player: lavalink.Player,
        eq: Equalizer,
        message: discord.Message,
        selected: int,
    ) -> None:
        player.store("eq", eq)
        emoji = {
            "far_left": "\N{BLACK LEFT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "one_left": "\N{LEFTWARDS BLACK ARROW}\N{VARIATION SELECTOR-16}",
            "max_output": "\N{BLACK UP-POINTING DOUBLE TRIANGLE}",
            "output_up": "\N{UP-POINTING SMALL RED TRIANGLE}",
            "output_down": "\N{DOWN-POINTING SMALL RED TRIANGLE}",
            "min_output": "\N{BLACK DOWN-POINTING DOUBLE TRIANGLE}",
            "one_right": "\N{BLACK RIGHTWARDS ARROW}\N{VARIATION SELECTOR-16}",
            "far_right": "\N{BLACK RIGHT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}",
            "reset": "\N{BLACK CIRCLE FOR RECORD}\N{VARIATION SELECTOR-16}",
            "info": "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}",
        }
        selector = f'{" " * 8}{"   " * selected}^^'
        try:
            await message.edit(content=box(f"{eq.visualise()}\n{selector}", lang="ini"))
        except discord.errors.NotFound:
            return
        try:
            (react_emoji, react_user) = await self._get_eq_reaction(ctx, message, emoji)
        except TypeError:
            return

        if not react_emoji:
            await self.config.custom("EQUALIZER", ctx.guild.id).eq_bands.set(eq.bands)
            await self._clear_react(message, emoji)

        if react_emoji == "\N{LEFTWARDS BLACK ARROW}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            await self._eq_interact(ctx, player, eq, message, max(selected - 1, 0))

        if react_emoji == "\N{BLACK RIGHTWARDS ARROW}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            await self._eq_interact(ctx, player, eq, message, min(selected + 1, 14))

        if react_emoji == "\N{UP-POINTING SMALL RED TRIANGLE}":
            await self.remove_react(message, react_emoji, react_user)
            _max = float("{:.2f}".format(min(eq.get_gain(selected) + 0.1, 1.0)))
            eq.set_gain(selected, _max)
            await self._apply_gain(ctx.guild.id, selected, _max)
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{DOWN-POINTING SMALL RED TRIANGLE}":
            await self.remove_react(message, react_emoji, react_user)
            _min = float("{:.2f}".format(max(eq.get_gain(selected) - 0.1, -0.25)))
            eq.set_gain(selected, _min)
            await self._apply_gain(ctx.guild.id, selected, _min)
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{BLACK UP-POINTING DOUBLE TRIANGLE}":
            await self.remove_react(message, react_emoji, react_user)
            _max = 1.0
            eq.set_gain(selected, _max)
            await self._apply_gain(ctx.guild.id, selected, _max)
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{BLACK DOWN-POINTING DOUBLE TRIANGLE}":
            await self.remove_react(message, react_emoji, react_user)
            _min = -0.25
            eq.set_gain(selected, _min)
            await self._apply_gain(ctx.guild.id, selected, _min)
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{BLACK LEFT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            selected = 0
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{BLACK RIGHT-POINTING TRIANGLE}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            selected = 14
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{BLACK CIRCLE FOR RECORD}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            for band in range(eq.band_count):
                eq.set_gain(band, 0.0)
            await self._apply_gains(ctx.guild.id, eq.bands)
            await self._eq_interact(ctx, player, eq, message, selected)

        if react_emoji == "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}":
            await self.remove_react(message, react_emoji, react_user)
            await ctx.send_help(self.command_equalizer)
            await self._eq_interact(ctx, player, eq, message, selected)
예제 #26
0
    async def get_playlist_match(
        self,
        context: commands.Context,
        matches: MutableMapping,
        scope: str,
        author: discord.User,
        guild: discord.Guild,
        specified_user: bool = False,
    ) -> Tuple[Optional[Playlist], str, str]:
        """
        Parameters
        ----------
        context: commands.Context
            The context in which this is being called.
        matches: dict
            A dict of the matches found where key is scope and value is matches.
        scope:str
            The custom config scope. A value from :code:`PlaylistScope`.
        author: discord.User
            The user.
        guild: discord.Guild
            The guild.
        specified_user: bool
            Whether or not a user ID was specified via argparse.
        Returns
        -------
        Tuple[Optional[Playlist], str, str]
            Tuple of Playlist or None if none found, original user input and scope.
        Raises
        ------
        `TooManyMatches`
            When more than 10 matches are found or
            When multiple matches are found but none is selected.

        """
        correct_scope_matches: List[Playlist]
        original_input = matches.get("arg")
        lazy_match = False
        if scope is None:
            correct_scope_matches_temp: MutableMapping = matches.get("all")
            lazy_match = True
        else:
            correct_scope_matches_temp: MutableMapping = matches.get(scope)
        guild_to_query = guild.id
        user_to_query = author.id
        correct_scope_matches_user = []
        correct_scope_matches_guild = []
        correct_scope_matches_global = []
        if not correct_scope_matches_temp:
            return None, original_input, scope or PlaylistScope.GUILD.value
        if lazy_match or (scope == PlaylistScope.USER.value):
            correct_scope_matches_user = [
                p for p in matches.get(PlaylistScope.USER.value)
                if user_to_query == p.scope_id
            ]
        if lazy_match or (scope == PlaylistScope.GUILD.value
                          and not correct_scope_matches_user):
            if specified_user:
                correct_scope_matches_guild = [
                    p for p in matches.get(PlaylistScope.GUILD.value) if
                    guild_to_query == p.scope_id and p.author == user_to_query
                ]
            else:
                correct_scope_matches_guild = [
                    p for p in matches.get(PlaylistScope.GUILD.value)
                    if guild_to_query == p.scope_id
                ]
        if lazy_match or (scope == PlaylistScope.GLOBAL.value
                          and not correct_scope_matches_user
                          and not correct_scope_matches_guild):
            if specified_user:
                correct_scope_matches_global = [
                    p for p in matches.get(PlaylistScope.GLOBAL.value)
                    if p.author == user_to_query
                ]
            else:
                correct_scope_matches_global = [
                    p for p in matches.get(PlaylistScope.GLOBAL.value)
                ]

        correct_scope_matches = [
            *correct_scope_matches_global,
            *correct_scope_matches_guild,
            *correct_scope_matches_user,
        ]
        match_count = len(correct_scope_matches)
        if match_count > 1:
            correct_scope_matches2 = [
                p for p in correct_scope_matches
                if p.name == str(original_input).strip()
            ]
            if correct_scope_matches2:
                correct_scope_matches = correct_scope_matches2
            elif original_input.isnumeric():
                arg = int(original_input)
                correct_scope_matches3 = [
                    p for p in correct_scope_matches if p.id == arg
                ]
                if correct_scope_matches3:
                    correct_scope_matches = correct_scope_matches3
        match_count = len(correct_scope_matches)
        # We done all the trimming we can with the info available time to ask the user
        if match_count > 10:
            if original_input.isnumeric():
                arg = int(original_input)
                correct_scope_matches = [
                    p for p in correct_scope_matches if p.id == arg
                ]
            if match_count > 10:
                raise TooManyMatches(
                    _("{match_count} playlists match {original_input}: "
                      "Please try to be more specific, or use the playlist ID."
                      ).format(match_count=match_count,
                               original_input=original_input))
        elif match_count == 1:
            return correct_scope_matches[
                0], original_input, correct_scope_matches[0].scope
        elif match_count == 0:
            return None, original_input, scope or PlaylistScope.GUILD.value

        # TODO : Convert this section to a new paged reaction menu when Toby Menus are Merged
        pos_len = 3
        playlists = f"{'#':{pos_len}}\n"
        number = 0
        correct_scope_matches = sorted(correct_scope_matches,
                                       key=lambda x: x.name.lower())
        async for number, playlist in AsyncIter(
                correct_scope_matches).enumerate(start=1):
            author = self.bot.get_user(
                playlist.author) or playlist.author or _("Unknown")
            line = _("{number}."
                     "    <{playlist.name}>\n"
                     " - Scope:  < {scope} >\n"
                     " - ID:     < {playlist.id} >\n"
                     " - Tracks: < {tracks} >\n"
                     " - Author: < {author} >\n\n").format(
                         number=number,
                         playlist=playlist,
                         scope=self.humanize_scope(playlist.scope),
                         tracks=len(playlist.tracks),
                         author=author,
                     )
            playlists += line

        embed = discord.Embed(
            title=_("{playlists} playlists found, which one would you like?").
            format(playlists=number),
            description=box(playlists, lang="md"),
            colour=await context.embed_colour(),
        )
        msg = await context.send(embed=embed)
        avaliable_emojis = ReactionPredicate.NUMBER_EMOJIS[1:]
        avaliable_emojis.append("🔟")
        emojis = avaliable_emojis[:len(correct_scope_matches)]
        emojis.append("\N{CROSS MARK}")
        start_adding_reactions(msg, emojis)
        pred = ReactionPredicate.with_emojis(emojis, msg, user=context.author)
        try:
            await context.bot.wait_for("reaction_add", check=pred, timeout=60)
        except asyncio.TimeoutError:
            with contextlib.suppress(discord.HTTPException):
                await msg.delete()
            raise TooManyMatches(
                _("Too many matches found and you did not select which one you wanted."
                  ))
        if emojis[pred.result] == "\N{CROSS MARK}":
            with contextlib.suppress(discord.HTTPException):
                await msg.delete()
            raise TooManyMatches(
                _("Too many matches found and you did not select which one you wanted."
                  ))
        with contextlib.suppress(discord.HTTPException):
            await msg.delete()
        return (
            correct_scope_matches[pred.result],
            original_input,
            correct_scope_matches[pred.result].scope,
        )
예제 #27
0
        )

        cooldowns = cmd.get("cooldowns", {})

        if cooldowns:
            cooldown_text = _("Cooldowns:\n")
            for rate, per in cooldowns.items():
                cooldown_text += _("{num} seconds per {period}\n").format(num=per, period=rate)
            text += cooldown_text

        text += _("Responses:\n")
        responses = ["- " + r for r in responses]
        text += "\n".join(responses)

        for p in pagify(text):
            await ctx.send(box(p, lang="yaml"))

    @commands.Cog.listener()
    async def on_message_without_command(self, message):
        is_private = isinstance(message.channel, discord.abc.PrivateChannel)

        # user_allowed check, will be replaced with self.bot.user_allowed or
        # something similar once it's added
        user_allowed = True

        if len(message.content) < 2 or is_private or not user_allowed or message.author.bot:
            return

        if await self.bot.cog_disabled_in_guild(self, message.guild):
            return