Exemple #1
0
 async def _command(self, ctx: commands.Context, *, item):
     new_item = ...
     for converter in converters:
         with contextlib.suppress(commands.BadArgument):
             new_item = await converter().convert(ctx, item)
             break
     if new_item is ...:
         raise commands.BadArgument
     item = getattr(item, "id", item)
     # noinspection PyTypeChecker
     async with DummyModule().config.guild(
         ctx.guild).ignore.get_attr(conf_opt)() as ignored:
         if remove is False:
             if item in ignored:
                 await ctx.send(
                     warning(
                         i18n("That item is already currently being ignored"
                              )))
                 return
             ignored.append(item)
         else:
             if item not in ignored:
                 await ctx.send(
                     warning(
                         i18n("That item is not currently being ignored")))
                 return
             ignored.remove(item)
         log.debug("{} {!r} to/from {!r} {} ignore list".format(
             name, new_item, ctx.guild, conf_opt))
         await ctx.tick()
Exemple #2
0
    async def _add_remove(self,
                          ctx: commands.Context,
                          role: discord.Role,
                          *,
                          rm: bool = False):
        if role.is_default():
            raise commands.BadArgument(
                "cannot make a server's default role mentionable")
        async with self.config.guild(ctx.guild).roles() as roles:
            if rm is False:
                if role.id in roles:
                    await ctx.send(
                        warning(_("That role is already mentionable")))
                    return
                roles.append(role.id)

            else:
                if role.id not in roles:
                    await ctx.send(
                        warning(_("That role is not currently mentionable")))
                    return
                roles.remove(role.id)

            await ctx.send(
                escape(
                    tick(
                        _("`{}` is now allowed to be mentioned").format(role.
                                                                        name)),
                    mass_mentions=True,
                ) if rm is False else escape(
                    tick(
                        _("`{}` is no longer allowed to be mentioned").
                        format(role.name)),
                    mass_mentions=True,
                ))
    async def create(self, ctx):
        """Create personal role if you don't have one already"""

        role = await self.config.member(ctx.author).role()
        role = ctx.guild.get_role(role)

        if not role:
            pos = await self.config.guild(ctx.guild).position_role()
            pos = ctx.guild.get_role(pos)
            pos = pos.position if pos else 1

            try:
                role = await ctx.guild.create_role(name=str(ctx.author),
                                                   colour=ctx.author.colour,
                                                   reason=_("Personal role"))
                await asyncio.sleep(0.3)
                await role.edit(position=pos)
                await asyncio.sleep(0.3)
                await ctx.author.add_roles(role, reason=_("Personal Roles"))
                await self.config.member(ctx.author).role.set(role.id)
                await self.config.member(ctx.author).auto_role.set(True)
            except:
                await ctx.send(
                    chat.warning(
                        "Could not create your personal role, please contact an admin."
                    ))
                return

            await ctx.send(
                f"Role created! You can edit it using `{ctx.prefix}myrole name` and `{ctx.prefix}myrole colour` commands."
            )
        else:
            await ctx.send(chat.warning("You already have a personal role!"))
Exemple #4
0
    async def cogwhitelist_remove(self, ctx: commands.Context, cog: str, guild_id: int = None):
        """Removes a cog or guild from the list of whitelisted cogs/guilds

        If a guild ID is specified, it's removed from the specified cogs' list of allowed guilds
        """
        cog = cog.lower()
        proper_name = cog_name(self.bot, cog) or cog
        async with self.config.cogs() as cogs:
            if cog not in cogs:
                return await fmt(
                    ctx,
                    warning(_("**{cog}** doesn't currently require a whitelist to use")),
                    cog=proper_name,
                )
            if guild_id:
                if guild_id not in cogs[cog]:
                    return await fmt(
                        ctx,
                        warning(_("That guild isn't allowed to use **{cog}**")),
                        cog=proper_name,
                    )
                cogs[cog].remove(guild_id)
                await fmt(
                    ctx,
                    tick(_("That guild is no longer allowed to use **{cog}**.")),
                    cog=proper_name,
                )
            else:
                cogs.pop(cog)
                await fmt(
                    ctx, tick(_("**{cog}** no longer requires a whitelist to use")), cog=proper_name
                )
Exemple #5
0
    async def stars_unignore(self,
                             ctx: Context,
                             name: str,
                             *,
                             reason: str = None):
        """Remove a channel or member from the server's ignore list

        `reason` is only used if unignoring a member
        """
        item = await resolve_any(ctx, name, commands.TextChannelConverter,
                                 commands.MemberConverter)

        if isinstance(item, discord.Member) and not await hierarchy_allows(
                self.bot, ctx.author, item):
            await ctx.send(
                error(
                    i18n(
                        "You aren't allowed to remove that member from the ignore list"
                    )))
            return
        elif (isinstance(item, discord.TextChannel)
              and item == await ctx.starboard.resolve_starboard()):
            await ctx.send(
                warning(
                    i18n(
                        "The starboard channel is always ignored and cannot be manually "
                        "ignored nor unignored.")))
            return

        if not await ctx.starboard.is_ignored(item):
            await ctx.send(
                warning(
                    i18n(
                        "That user is not already ignored from using this server's starboard"
                    ) if isinstance(item, discord.Member) else i18n(
                        "That channel is not already being ignored")))
            return

        await ctx.starboard.unignore(item)
        await ctx.send(
            tick(
                i18n("**{}** is no longer ignored from this server's starboard"
                     )).format(item))

        if isinstance(item, discord.Member):
            try:
                await modlog.create_case(
                    bot=self.bot,
                    guild=ctx.guild,
                    created_at=ctx.message.created_at,
                    action_type="starboardunblock",
                    user=item,
                    moderator=ctx.author,
                    reason=reason,
                    until=None,
                    channel=None,
                )
            except RuntimeError:
                pass
Exemple #6
0
 async def quote_message(self,
                         ctx: commands.Context,
                         message: int,
                         channel: discord.TextChannel = None):
     channel = channel or ctx.channel
     try:
         message = await channel.get_message(message)
     except discord.NotFound:
         await ctx.send(warning(translate("message_not_found")))
     except discord.Forbidden:
         await ctx.send(warning(translate("message_forbidden")))
     else:
         quote = await Quote.create(message.content, ctx.author,
                                    message.author)
         await ctx.send(tick(translate("quote_added")), embed=quote.embed)
Exemple #7
0
 async def getuserinfo(self, ctx, user_id: int):
     """Get info about any discord's user by ID"""
     try:
         user = await self.bot.get_user_info(user_id)
     except discord.errors.NotFound:
         await ctx.send(
             chat.error("Discord user with ID `{}` not found").format(
                 user_id))
         return
     except discord.errors.HTTPException:
         await ctx.send(
             chat.warning(
                 "Bot was unable to get data about user with ID `{}`. "
                 "Try again later".format(user_id)))
         return
     embed = discord.Embed(title=str(user),
                           timestamp=user.created_at,
                           color=await ctx.embed_color())
     embed.add_field(name="ID", value=user.id)
     embed.add_field(name="Bot?", value=bool_emojify(user.bot))
     embed.add_field(name="Mention", value=user.mention)
     embed.add_field(name="Default avatar",
                     value="[{}]({})".format(user.default_avatar,
                                             user.default_avatar_url))
     if user.avatar:
         embed.add_field(name="Avatar",
                         value="[`{}`]({})".format(
                             user.avatar,
                             user.avatar_url_as(static_format="png",
                                                size=2048)))
     embed.set_image(url=user.avatar_url_as(static_format="png", size=2048))
     embed.set_thumbnail(url=user.default_avatar_url)
     embed.set_footer(text="Created at")
     await ctx.send(embed=embed)
    async def icon_reset(self, ctx):
        """Remove icon of personal role"""
        role = await self.config.member(ctx.author).role()
        role = ctx.guild.get_role(role)
        if not role:
            await ctx.send(
                chat.warning(
                    f"Please create your role using `{ctx.prefix}myrole create`!"
                ))
            return

        try:
            await edit_role_icon(
                self.bot,
                role,
                icon=None,
                unicode_emoji=None,
                reason=get_audit_reason(ctx.author, _("Personal Role")),
            )
            await ctx.send(
                _("Removed icon of {user}'s personal role").format(
                    user=ctx.message.author.name))
        except discord.Forbidden:
            ctx.command.reset_cooldown(ctx)
            await ctx.send(
                chat.error(
                    _("Unable to edit role.\nRole must be lower than my top role"
                      )))
        except discord.HTTPException as e:
            ctx.command.reset_cooldown(ctx)
            await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
    async def name(self, ctx, *, name: str):
        """Change name of personal role
        You can't use blacklisted names
        Names must be 30 characters or less"""
        role = await self.config.member(ctx.author).role()
        role = ctx.guild.get_role(role)
        if not role:
            await ctx.send(
                chat.warning(
                    f"Please create your role using `{ctx.prefix}myrole create`!"
                ))
            return

        name = name[:30]
        if name.casefold() in await self.config.guild(ctx.guild).blacklist():
            await ctx.send(chat.error(_("This rolename is blacklisted.")))
            return
        try:
            await role.edit(name=name,
                            reason=get_audit_reason(ctx.author,
                                                    _("Personal Role")))
        except discord.Forbidden:
            ctx.command.reset_cooldown(ctx)
            await ctx.send(
                chat.error(
                    _("Unable to edit role.\n"
                      'Role must be lower than my top role and i must have permission "Manage Roles"'
                      )))
        except discord.HTTPException as e:
            ctx.command.reset_cooldown(ctx)
            await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
        else:
            await ctx.send(
                _("Changed name of {user}'s personal role to {name}").format(
                    user=ctx.message.author.name, name=name))
Exemple #10
0
    async def requirerole(self, ctx: commands.Context, *roles: RoleTuple):
        """Require one of any specific roles to use the bot in the current guild

        To require a member to __not__ have one or more roles, you can use
        `~` before the role name to treat it as a blacklisted role.
        If a role name has `~` at the start of it's name, you can escape
        it with a backslash (`\`) character. Blacklisted roles override
        any possible whitelisted roles a member may have.

        Role names are case sensitive. If a role has spaces in it's name, wrap it in quotes.
        Passing no roles removes any currently set role requirements.

        The guild owner and members with the Administrator permission
        always bypass these requirements, regardless of roles."""
        seen = SeenSet()
        roles = tuple(
            (k, v) for k, v in roles
            if seen.mark_seen(k))  # type: Tuple[Tuple[discord.Role, bool]]
        whitelist = tuple(r for r, v in roles
                          if v)  # type: Tuple[discord.Role]
        blacklist = tuple(r for r, v in roles
                          if not v)  # type: Tuple[discord.Role]

        if ctx.guild.default_role in roles:
            await ctx.send(
                warning(
                    _("I can't set a role requirement with the guild's default role - "
                      "if you'd like to clear your current role requirements, "
                      "you can execute this command with no arguments to do so."
                      )))
            return

        await self.config.guild(ctx.guild).roles.set({
            "whitelist": [x.id for x in whitelist],
            "blacklist": [x.id for x in blacklist]
        })
        if not roles:
            await ctx.send(tick(_("Cleared currently set role requirements.")))
            return

        whitelist = ", ".join(
            escape(str(x), mass_mentions=True, formatting=True)
            for x in whitelist)
        blacklist = ", ".join(
            escape(str(x), mass_mentions=True, formatting=True)
            for x in blacklist)

        msg = _(
            "A member will now need to pass the following checks to use my commands:\n\n"
        )
        if whitelist:
            msg += _("**Any of the following roles:**\n{roles}").format(
                roles=whitelist)
        if whitelist and blacklist:
            msg += "\n\n"
        if blacklist:
            msg += _("**None of the following roles:**\n{roles}").format(
                roles=blacklist)

        await ctx.send(tick(msg))
Exemple #11
0
    async def logset_channel(self,
                             ctx: commands.Context,
                             module: str,
                             channel: discord.TextChannel = None):
        """Set the log channel for a module

        Passing no log channel effectively acts as disabling the module
        """
        module = await retrieve_module(ctx, module)
        if channel and not channel.permissions_for(ctx.guild.me).send_messages:
            await ctx.send(
                warning(i18n("I'm not able to send messages in that channel")))
            return
        await module.module_config.set_raw("_log_channel",
                                           value=getattr(channel, "id", None))
        if channel:
            await ctx.send(
                tick(
                    i18n("Module **{module}** will now log to {channel}").
                    format(module=module.friendly_name,
                           channel=channel.mention)))
        else:
            await ctx.send(
                tick(
                    i18n(
                        "The log channel for module **{module}** has been cleared"
                    ).format(module=module.friendly_name)))
Exemple #12
0
 async def starboard_minstars(self, ctx: Context, stars: int):
     """Set the amount of stars required for a message to be sent to this server's starboard"""
     if stars < 1:
         await ctx.send(
             warning(i18n("The amount of stars must be a non-zero number")))
         return
     if stars > len([x for x in ctx.guild.members if not x.bot]):
         await ctx.send(
             warning(
                 i18n(
                     "There aren't enough members in this server to reach"
                     " the given amount of stars. Maybe try a lower number?"
                 )))
         return
     await ctx.starboard.min_stars.set(stars)
     await ctx.tick()
Exemple #13
0
    async def process_rule_agreement_reaction(self, member: discord.Member, emoji: str, add: bool):
        """
        Handles the rule agreement reaction
        """        

        if emoji.startswith("\N{THUMBS UP SIGN}"):
            if add:
                msg = (
                    f"Thank you for agreeing to the rules of {member.guild.name}.\n"
                    "You have now been granted full access to the server."
                )
                action = "added"
                await member.add_roles(self.roles["reader"]["obj"])
            else:
                msg = (
                    f"It is unfortunate that you can no longer agree to the rules of {member.guild.name}.\n"
                    "Your access to the server has been restricted.\n"
                    "If you decide to agree to the rules in the future, your access will be restored."
                )
                action = "removed"
                await member.remove_roles(self.roles["reader"]["obj"])
            
            await self.log.send(f"`{member.name}` {action} `reader` role.")
            with contextlib.suppress(discord.HTTPException):
                # we don't want blocked DMs preventing the function working
                await member.send(msg)
        else:
            await self.log.send(warning(f"`{member.name}` tried to add a role but used the wrong emoji."))
Exemple #14
0
    async def greetRemove(self, ctx: Context, name: str):
        """
        Remove a greeting

        Parameters:
        -----------
        name: name of the greeting to remove
        """

        def check(message: discord.Message):
            return message.author == ctx.message.author and message.channel == ctx.message.channel

        greetings = await self.config.guild(ctx.guild).greetings()
        if name in greetings:
            await ctx.send(
                warning("Are you sure you wish to delete this greeting? Respond with 'yes' if yes")
            )
            try:
                response = await self.bot.wait_for("message", timeout=30.0, check=check)
            except asyncio.TimeoutError:
                await ctx.send("You took too long, not deleting")
                return

            if response.content.lower() != "yes":
                await ctx.send("Not deleting")
                return

            # delete the greeting
            del greetings[name]
            await ctx.send(f"{name} removed from list")
            await self.config.guild(ctx.guild).greetings.set(greetings)
        else:
            ctx.send(f"{name} not in list of greetings")
        return
Exemple #15
0
 async def cleanup_users(self, ctx, days: int = 1):
     """Cleanup inactive server members"""
     if days > 30:
         await ctx.send(
             chat.info(
                 _("Due to Discord Restrictions, you cannot use more than 30 days for that cmd."
                   )))
         days = 30
     elif days <= 0:
         await ctx.send(chat.info(_('"days" arg cannot be less than 1...')))
         days = 1
     to_kick = await ctx.guild.estimate_pruned_members(days=days)
     await ctx.send(
         chat.warning(
             _("You about to kick **{to_kick}** inactive for **{days}** days members from this server. "
               'Are you sure?\nTo agree, type "yes"').format(
                   to_kick=to_kick, days=days)))
     pred = MessagePredicate.yes_or_no(ctx)
     try:
         await self.bot.wait_for("message", check=pred, timeout=30)
     except AsyncTimeoutError:
         pass
     if pred.result:
         cleanup = await ctx.guild.prune_members(days=days,
                                                 reason=get_audit_reason(
                                                     ctx.author))
         await ctx.send(
             chat.info(
                 _("**{removed}**/**{all}** inactive members removed.\n"
                   "(They was inactive for **{days}** days)").format(
                       removed=cleanup, all=to_kick, days=days)))
     else:
         await ctx.send(chat.error(_("Inactive members cleanup canceled.")))
Exemple #16
0
    async def rndactivity_list(self, ctx: commands.Context):
        statuses = list(await self.config.statuses())
        if not statuses:
            return await ctx.send(
                warning(translate("no_setup_statuses", prefix=ctx.prefix)))

        pages = []
        for status in statuses:
            index = statuses.index(status) + 1
            game_type = 0
            stream_url = None
            if isinstance(status, dict):
                game_type = status.get("type", 0)
                stream_url = status.get("url")
                status = status.get("game")
            status = escape(status, formatting=True, mass_mentions=True)
            if stream_url:
                status = f"[{status}]({stream_url})"
            pages.append(
                f"**#{index}** \N{EM DASH} **{translate('game_type')[game_type]}** {status}"
            )

        colour = await ctx.embed_colour()
        pages = [
            discord.Embed(colour=colour, description=x)
            for x in pagify("\n".join(pages))
        ]
        await PaginatedMenu(pages=pages,
                            bot=ctx.bot,
                            channel=ctx.channel,
                            member=ctx.author).prompt()
Exemple #17
0
    async def channel_delete(self, ctx: commands.Context, *,
                             channel: Union[discord.TextChannel,
                                            discord.VoiceChannel]):
        """Remove a channel from server

        Example:
            `[p]channel delete channel`
        """
        self.check_channel_permission(ctx, channel)
        pred = MessagePredicate.yes_or_no(ctx)
        if not ctx.assume_yes:
            await ctx.send(
                chat.warning(
                    _("You are about to delete channel {channel}. This cannot be undone. Are you sure?\n"
                      'To agree, type "yes"').format(channel=channel.mention)))
            try:
                await self.bot.wait_for("message", check=pred, timeout=30)
            except AsyncTimeoutError:
                pass
        if ctx.assume_yes or pred.result:
            try:
                await channel.delete(reason=get_audit_reason(ctx.author))
            except discord.Forbidden:
                await ctx.send(chat.error(_("I can't delete this channel")))
            except discord.HTTPException as e:
                await ctx.send(
                    chat.error(
                        _("I am unable to delete a channel: {}").format(e)))
            else:
                await ctx.tick()
Exemple #18
0
    async def allsfx(self, ctx):
        """Sends a list of every sound in a PM."""

        # await self.bot.type()

        server = ctx.message.guild
        serverid = str(server.id)

        if serverid not in os.listdir(self.sound_base):
            os.makedirs(os.path.join(self.sound_base, serverid))

        if serverid not in self.settings:
            self.settings[serverid] = {}
            self.save_json(self.settings_path, self.settings)

        strbuffer = self._list_sounds(serverid)

        if len(strbuffer) == 0:
            await ctx.send(cf.warning(
                "No sounds found. Use `{}addsfx` to add one.".format(
                    ctx.prefix)))
            return

        mess = "```"
        for line in strbuffer:
            if len(mess) + len(line) + 4 < 2000:
                mess += "\n" + line
            else:
                mess += "```"
                await ctx.send(mess)
                mess = "```" + line
        if mess != "":
            mess += "```"
            await ctx.send(mess)
Exemple #19
0
    async def rndactivity_add(self, ctx: commands.Context,
                              game_type: Optional[ActivityTypeConverter], *,
                              game: str):
        stream = None
        if game_type is None:
            game_type = discord.ActivityType.playing
        elif game_type == discord.ActivityType.streaming:
            game = game.split(" ")
            stream, game = game.pop(), " ".join(game)
            if not TWITCH_REGEX.match(stream):
                raise commands.BadArgument(translate("no_stream_provided"))
        activity = {
            "type": game_type.value,
            "game": game,
            "url": stream.strip("<>") if stream else None,
        }

        try:
            self.format_status(activity, error_deprecated=True)
        except KeyError as e:
            await ctx.send(
                warning(
                    translate("parse_fail_invalid_placeholder",
                              placeholder=str(e))))
        else:
            async with self.config.statuses() as statuses:
                statuses.append(activity)
                await ctx.send(
                    tick(translate("added_status", id=len(statuses))))
Exemple #20
0
    async def logging_level_setter(self, ctx: commands.Context, logging_level: int):
        """
        Set the logging level of the cog.

        The logging level must be an integrer between 1 and 5.
        The lowest the logging level is, the more alert you will receive in your bot's log.

        1 - DEBUG
        2 - INFO
        3 - WARNING
        4 - ERROR
        5 - CRITICAL

        **Level 1 is meant for developers, tester and monitoring purpose.**
        """
        if logging_level > 5:
            await ctx.send("The logging level cannot be more than 5.")
            return
        if logging_level < 0:
            await ctx.send("The logging level cannot be less than 0.")
        value = getattr(LoggingLevels, "Lvl" + str(logging_level)).value
        await self.data.log_level.set(logging_level * 10)
        await ctx.send(
            warning(
                "The logging level has been set to: {val}, {lev}".format(
                    val=value, lev=logging_level
                )
            )
        )

        await self._initialize(False)
Exemple #21
0
    async def rule_channel_list(self,
                                ctx,
                                channel: Union[discord.TextChannel,
                                               discord.VoiceChannel] = None):
        """
        List all rules for a channel
        Defaults to current channel.

        For voice channels, use the voice channel ID
        """
        if channel:
            rules = await self.config.channel(channel).rules()
        else:
            channel = ctx.channel
            rules = await self.config.channel(channel).rules()

        embeds = []
        rules_keys = sorted([int(r) for r in rules.keys()])
        num_rules = len(rules_keys)
        for i, rule_num in enumerate(rules_keys):
            embed = discord.Embed(title=f"{channel.name} rules",
                                  colour=ctx.guild.me.colour)
            embed.add_field(name=f"Rule {rule_num}",
                            value=rules[str(rule_num)])
            embed.set_footer(text=f"Page {i+1} of {num_rules}")
            embeds.append(embed)

        if not embeds:
            await ctx.send(chat.warning("No rules defined."))
            return

        await menu(ctx, embeds, DEFAULT_CONTROLS)
Exemple #22
0
    async def wikipedia(self, ctx: commands.Context, *, query: str):
        """Get information from Wikipedia."""
        can_not_embed_links = not ctx.channel.permissions_for(
            ctx.me).embed_links
        can_not_add_reactions = not ctx.channel.permissions_for(
            ctx.me).add_reactions
        only_first_result = can_not_embed_links or can_not_add_reactions
        async with ctx.typing():
            embeds, url = await self.perform_search(
                query, only_first_result=only_first_result)

        if not embeds:
            await ctx.send(
                error(f"I'm sorry, I couldn't find \"{query}\" on Wikipedia"))
        elif can_not_embed_links:
            await ctx.send(
                warning(
                    f"I'm not allowed to do embeds here, so here's the first result:\n{url}"
                ))
        elif can_not_add_reactions:
            embeds[0].set_author(
                name=f"Result 1 (I need add reactions permission to show more)"
            )
            await ctx.send(embed=embeds[0])
        elif len(embeds) == 1:
            embeds[0].set_author(name="Result 1 of 1")
            await ctx.send(embed=embeds[0])
        else:
            count = 0
            for embed in embeds:
                count += 1
                embed.set_author(name=f"Result {count} of {len(embeds)}")
            await menu(ctx, embeds, DEFAULT_CONTROLS, timeout=60.0)
Exemple #23
0
    async def _list_guilds(self, ctx: commands.Context, cog: str):
        cogs = await self.config.cogs()
        if cog.lower() not in cogs:
            await ctx.send(warning(_("That cog doesn't require a whitelist to use")))
            return

        proper_name = cog_name(self.bot, cog) or cog

        def converter(page, page_id, total_pages):
            embed = discord.Embed(
                colour=ctx.me.colour,
                title=_("Whitelisted Guilds"),
                description=_("The following guilds are allowed to use {}").format(proper_name),
            )

            for guild_id in page:
                guild = self.bot.get_guild(guild_id)
                try:
                    name = escape(guild.name, formatting=True)
                except AttributeError:
                    name = inline(_("Unknown guild"))

                embed.add_field(
                    name=_("Guild #{}").format(((page_id * 10) + page.index(guild_id)) + 1),
                    value=_("**Name:** {name}\n**ID:** `{id}`").format(name=name, id=guild_id),
                    inline=False,
                )

            embed.set_footer(text=_("Page {}/{}").format(page_id + 1, total_pages))
            return embed

        await PaginateMenu(ctx, pages=chunks(cogs[cog.lower()], 6), converter=converter, actions={})
Exemple #24
0
    async def cogwhitelist_reset(self, ctx: commands.Context):
        """Reset whitelisted cog settings"""
        cogs = len(await self.config.cogs())
        if not cogs:
            return await fmt(
                ctx,
                info(
                    _(
                        "No cogs are currently setup to require a whitelist to use, and as such "
                        "you cannot reset any cog whitelist settings."
                    )
                ),
            )

        warn_str = warning(
            _(
                "Are you sure you want to reset your cog whitelist settings?\n"
                "This action will make {cogs} cog(s) usable by any server.\n\n"
                "Unless you have a time machine, **this action cannot be undone.**"
            )
        )

        if await ConfirmMenu(ctx=ctx, content=warn_str.format(cogs=cogs)).prompt():
            await self.config.cogs.set({})
            await ctx.tick()
        else:
            await ctx.send(_("Ok then."))
Exemple #25
0
 async def dice(self, ctx: commands.Context, *, roll: str):
     """Perform die roll."""
     try:
         # Pass 1: Tokenize and convert #d# into die objects
         roll_pass1 = self.get_equation_tokens(
             roll,
             await self.config.max_dice_rolls(),
             await self.config.max_die_sides(),
         )
         # Pass 2: Roll dice and build math string to evaluate
         roll_log = ""
         roll_pass2 = ""
         roll_friendly = ""
         for token in roll_pass1:
             if isinstance(token, Die):
                 token.roll()
                 roll_pass2 += str(token.total)
                 roll_log += "\nRolling {}: {} = {}".format(
                     str(token), str(token.rolls), str(token.total))
             else:
                 roll_pass2 += str(token)
             roll_friendly += str(token)
         # Pass 3: Evaluate results
         if roll_log:
             result = str(eval_expr(roll_pass2))
             roll_pass2 = roll_pass2.replace("*", "×")
             roll_friendly = roll_friendly.replace("*", "×")
             roll_log = "\n*Roll Log:" + roll_log
             if len(roll_pass1) > 1:
                 roll_log += "\nResulting equation: {} = {}".format(
                     roll_pass2, result)
             roll_log += "*"
             if len(roll_log) > 1500:
                 roll_log = "\n*(Log too long to display)*"
             await ctx.send(
                 "\N{GAME DIE} {} rolled {} and got **{}**{}".format(
                     ctx.message.author.mention, roll_friendly, result,
                     roll_log))
         else:
             await ctx.send(
                 warning(
                     "{}, that notation doesn't have any dice for me to roll."
                     .format(ctx.message.author.mention)))
     except TooManySides as exception:
         await ctx.send(
             error("{}, I don't own a {} sided die to perform that roll.".
                   format(ctx.message.author.mention, exception.value)))
     except TooManyDice:
         await ctx.send(
             error("{}, I don't have that many dice to roll...".format(
                 ctx.message.author.mention)))
     except KeyError:
         await ctx.send(
             error("{}, that is too complex for me to roll.".format(
                 ctx.message.author.mention)))
     except (ValueError, SyntaxError, TypeError):
         await ctx.send(
             error("{}, that doesn't seem like a proper dice equation.".
                   format(ctx.message.author.mention)))
Exemple #26
0
    async def staff(self, ctx: commands.Context, *, reason: str = None):
        """
        Alert for the staff.
        """

        channel = await self.config.guild(ctx.guild).channel()
        role = await self.config.guild(ctx.guild).role()

        if not channel:
            return await ctx.send(
                error("The staff have not yet setup a staff channel."))

        channel = self.bot.get_channel(channel)
        role = ctx.guild.get_role(role)

        message_list = []
        backslash = "\n"

        async for message in ctx.channel.history(limit=6):
            author, msg = message.author, message.content.replace("`", "")
            if len(msg) > 90:
                msg = msg[:90].strip(" ") + "..."
            elif not len(msg):
                msg = "[Embed, Attachment or File]"
            message_list.append(
                f"{str(author.display_name)}: {msg.replace(backslash, ' ')}")

        context = box("\n".join(message_list), lang="yaml")
        reason = reason or "No reason was provided."

        embed = discord.Embed(
            title=warning("Staff Attention Pending | Conspicuous Activity"),
            description="[Click here for context]({})".format(
                ctx.message.jump_url),
            color=await ctx.embed_colour(),
        )

        embed.add_field(name="Member", value=ctx.author.mention, inline=True)
        embed.add_field(name="Channel", value=ctx.channel.mention, inline=True)
        embed.add_field(name="Time", value=self.timestamp, inline=True)
        embed.add_field(name="Reason", value=reason, inline=False)
        embed.add_field(name="Context", value=context, inline=False)

        if await ctx.embed_requested():
            try:
                await channel.send(
                    allowed_mentions=discord.AllowedMentions(roles=True),
                    content=role.mention if role else None,
                    embed=embed,
                )
                await ctx.send(
                    "I have alerted the authorities, please remain calm.")
            except discord.Forbidden:
                return await ctx.send(
                    "I do not have permissions to alert the staff.")
        else:
            return await ctx.send(
                "I do not have permissions to send embeds in the staff's channel."
            )
Exemple #27
0
    async def maintenance_disable(self, ctx: commands.Context):
        if os.environ.get("RED_MAINTENANCE"):
            await ctx.send(warning(translate("set_by_env")))
            return

        manager.bot = False
        await self.config.maintenance.set_raw("global", value=False)
        await ctx.send(tick(translate("disabled")))
Exemple #28
0
    async def identicon(
        self,
        ctx: commands.Context,
        user: Union[discord.Member, discord.User, int] = None,
    ):
        """
        Generate an unique pydenticon with an user's Discord ID

        Parameters
        ----------
        `[user]` - any valid user that shares a server with this bot (ID|tag#1234|tag)
        """

        msg = ""
        DEFAULT_SCALE = 9
        DEFAULT_SIZE = 120

        scale = DEFAULT_SCALE
        size = DEFAULT_SIZE - DEFAULT_SIZE % scale

        if isinstance(user, int):
            try:
                user = await ctx.bot.fetch_user(user)
            except discord.NotFound:
                await ctx.send(
                    chat.error("Discord user with ID `{}` not found").format(
                        user))
                return
            except discord.HTTPException:
                await ctx.send(
                    chat.warning(
                        "I was unable to get data about user with ID `{}`. Try again later"
                    ).format(user))
                return
        if user is None:
            user = ctx.author

        random.seed(user.id)
        color_white = "#000000"
        color_black = "#ffffff"
        fg: [str]
        bg: str
        fg = ["#{:06x}".format(random.randint(0x0, 0xFFFFFF))]
        bg = "#{:06x}".format(random.randint(0x0, 0xFFFFFF))
        if fg[0] == bg:
            # squashing an edge case for some users...
            bg = color_black if fg != color_black else color_white

        f = BytesIO()
        generator = pydenticon.Generator(scale,
                                         scale,
                                         foreground=fg,
                                         background=bg)
        icon = generator.generate(str(user.id), size, size)
        f.write(icon)
        f.seek(0)
        f.name = "identicon.png"
        await ctx.send(msg + f"{user.name}'s identicon:", file=discord.File(f))
Exemple #29
0
    async def timedmute(
        self,
        ctx: commands.Context,
        member: discord.Member,
        duration: TimeConverter,
        *,
        reason: str = None,
    ):
        from timedrole.api import TempRole

        if not await hierarchy_allows(self.bot, mod=ctx.author, member=member):
            await ctx.send(warning(translate("hierarchy_disallows")))
            return

        role = await self.get_punished_role(ctx.guild)
        if role is None:
            tmp_msg = await ctx.send(translate("setting_up"))
            async with ctx.typing():
                role = await self.setup_role(ctx.guild)
            await tmp_msg.delete()

        if role in member.roles:
            await ctx.send(warning(translate("already_muted")))
            return

        role = await TempRole.create(
            member, role, duration=duration, added_by=ctx.author, reason=reason
        )
        await role.apply_role(reason=reason)

        try:
            await modlog.create_case(
                bot=self.bot,
                guild=ctx.guild,
                user=member,
                moderator=ctx.author,
                reason=reason,
                until=role.expires_at,
                action_type="timedmute",
                created_at=role.added_at,
            )
        except RuntimeError:
            pass

        await ctx.send(tick(translate("member_muted", member=member, duration=Humanize(duration))))
Exemple #30
0
    async def star_remove(self, ctx: Context, message: StarboardMessage):
        """Remove a previously added star"""
        if not message.has_starred(ctx.author):
            await fmt(
                ctx,
                warning(
                    i18n("You haven't starred that message\n\n"
                         "(you can use `{prefix}star` to star it)")),
                delete_after=15,
            )
            return

        try:
            await message.remove_star(ctx.author)
        except StarboardException:
            await ctx.send(warning(i18n("Failed to remove star")))
        else:
            await ctx.tick()