Exemplo n.º 1
0
async def search_infractions_by_user(message: discord.Message, args: List[str],
                                     client: discord.Client,
                                     ctx: CommandCtx) -> Any:
    if not message.guild:
        return 1

    tstart = time.monotonic()

    if not ctx.verbose:
        raise lib_sonnetcommands.CommandError(
            "ERROR: search-infractions only meant to be called directly")

    # Reparse args
    try:
        args = shlex.split(" ".join(args))
    except ValueError:
        raise lib_sonnetcommands.CommandError(
            "ERROR: Shlex failed to parse arguments")

    # Parse flags
    parser = Parser("search-infractions")

    selected_chunk_f = parser.add_arg(["-p", "--page"], lambda s: int(s) - 1)
    responsible_mod_f = parser.add_arg(["-m", "--mod"], get_user_id)
    user_affected_f = parser.add_arg(["-u", "--user"], get_user_id)
    per_page_f = parser.add_arg(["-i", "--infractioncount"], int)
    infraction_type_f = parser.add_arg(["-t", "--type"], str)
    filtering_f = parser.add_arg(["-f", "--filter"], str)
    automod_f = lib_tparse.add_true_false_flag(parser, "automod")

    try:
        parser.parse(args, stderr=io.StringIO(), exit_on_fail=False, lazy=True)
    except lib_tparse.ParseFailureError:
        await message.channel.send("Failed to parse flags")
        return 1

    selected_chunk = selected_chunk_f.get(0)
    per_page = per_page_f.get(20)
    user_affected = user_affected_f.get()

    # Default to user if no user/mod flags are supplied
    if None is responsible_mod_f.get() is user_affected:
        try:
            user_affected = get_user_id(args[0])
        except (IndexError, ValueError):
            pass

    if not 5 <= per_page <= 40:  # pytype: disable=unsupported-operands
        await message.channel.send(
            "ERROR: Cannot exeed range 5-40 infractions per page")
        return 1

    refilter: "Optional[re.Pattern[str]]"

    if (f := filtering_f.get()) is not None:
        try:
            refilter = re.compile(f)
        except re.error:
            raise lib_sonnetcommands.CommandError(
                "ERROR: Filter regex is invalid")
Exemplo n.º 2
0
async def initialise_poll(message: discord.Message, args: List[str],
                          client: discord.Client, **kwargs: Any) -> Any:

    try:
        await message.add_reaction("👍")
        await message.add_reaction("👎")
    except discord.errors.Forbidden:
        raise lib_sonnetcommands.CommandError(
            "ERROR: The bot does not have permissions to add a reaction here")
    except discord.errors.NotFound:
        raise lib_sonnetcommands.CommandError(
            "ERROR: Could not find the message [404]")
Exemplo n.º 3
0
async def grab_guild_info(message: discord.Message, args: List[str],
                          client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    guild = message.guild

    embed_col = load_embed_color(guild, embed_colors.primary, kwargs["ramfs"])

    guild_embed = discord.Embed(title=f"Information on {guild}",
                                color=embed_col)
    if guild.owner:
        guild_embed.add_field(name="Server Owner:", value=guild.owner.mention)
    guild_embed.add_field(name="# of Roles:",
                          value=f"{len(guild.roles)} Roles")
    guild_embed.add_field(name="Top Role:", value=guild.roles[-1].mention)
    guild_embed.add_field(name="Member Count:", value=str(guild.member_count))
    guild_embed.add_field(name="Creation Date:",
                          value=parsedate(guild.created_at))

    guild_embed.set_footer(text=f"gid: {guild.id}")
    guild_embed.set_thumbnail(url=cast(str, guild.icon_url))

    try:
        await message.channel.send(embed=guild_embed)
    except discord.errors.Forbidden:
        raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)
Exemplo n.º 4
0
async def parse_channel_message_noexcept(
        message: discord.Message, args: list[str],
        client: discord.Client) -> tuple[discord.Message, int]:
    """
    Parse a channel message from a url, #channel messageid, or channelid-messageid field

    :returns: Tuple[discord.Message, int] -- The message and the amount of args the message grabbing took
    :raises: lib_sonnetcommands.CommandError -- The message did not exist or the function had invalid inputs
    """

    if not message.guild:
        raise lib_sonnetcommands.CommandError("ERROR: Not a guild message")

    try:
        message_link = args[0].replace("-", "/").split("/")
        log_channel: Union[str, int] = message_link[-2]
        message_id = message_link[-1]
        nargs = 1
    except IndexError:
        try:
            log_channel = args[0].strip("<#!>")
            message_id = args[1]
            nargs = 2
        except IndexError:
            raise lib_sonnetcommands.CommandError(
                constants.sonnet.error_args.not_enough)

    try:
        log_channel = int(log_channel)
    except ValueError:
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_channel.invalid)

    discord_channel = client.get_channel(log_channel)
    if not discord_channel:
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_channel.invalid)

    if not isinstance(discord_channel, discord.TextChannel):
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_channel.scope)

    if discord_channel.guild.id != message.guild.id:
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_channel.scope)

    try:
        discord_message = await discord_channel.fetch_message(int(message_id))
    except (ValueError, discord.errors.HTTPException):
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_message.invalid)

    if not discord_message:
        raise lib_sonnetcommands.CommandError(
            constants.sonnet.error_message.invalid)

    return (discord_message, nargs)
Exemplo n.º 5
0
async def parse_user_member_noexcept(
    message: discord.Message,
    args: List[str],
    client: discord.Client,
    argindex: int = 0,
    default_self: bool = False
) -> Tuple[UserInterface, Optional[discord.Member]]:
    """
    Parse a user and member object from a potential user string
    Always returns a user, only returns member if the user is in the guild
    User returned might be a member, do not rely on this.

    :returns: Tuple[Union[discord.User, discord.Member], Optional[discord.Member]] -- A discord user and optional member
    :raises: lib_sonnetcommands.CommandError -- Could not find the user or input invalid
    """

    if not message.guild or not isinstance(message.author, discord.Member):
        raise lib_sonnetcommands.CommandError("Not a guild message")

    try:
        uid = int(args[argindex].strip("<@!>"))
    except ValueError:
        raise lib_sonnetcommands.CommandError("Invalid UserID")
    except IndexError:
        if default_self:
            return message.author, message.author
        else:
            raise lib_sonnetcommands.CommandError("No user specified")

    member: Optional[discord.Member]
    user: Optional[discord.User | discord.Member]

    try:
        member = message.guild.get_member(uid)
        if not (user := client.get_user(uid)):
            user = await client.fetch_user(uid)
    except (discord.errors.NotFound, discord.errors.HTTPException):
        raise lib_sonnetcommands.CommandError("User does not exist")

    return user, member
Exemplo n.º 6
0
    async def full_help(self, page: int, per_page: int) -> discord.Embed:

        cmds = self.ctx.cmds
        cmds_dict = self.ctx.cmds_dict

        if page < 0 or page >= (len(self.ctx.cmds) +
                                (per_page - 1)) // per_page:
            raise lib_sonnetcommands.CommandError(
                f"ERROR: No such page {page+1}")

        cmd_embed = discord.Embed(
            title=
            f"Category Listing (Page {page+1} / {(len(cmds) + (per_page-1))//per_page})",
            color=load_embed_color(self.guild, embed_colors.primary,
                                   self.ctx.ramfs))
        cmd_embed.set_author(name=self.helpname)

        total = 0
        # Total counting is seperate due to pagination not counting all modules
        for cmd in cmds_dict:
            if 'alias' not in cmds_dict[cmd]:
                total += 1

        for module in sorted(
                cmds, key=lambda m: m.category_info['pretty_name'])[(
                    page * per_page):(page * per_page) + per_page]:
            mnames = [
                f"`{i}`" for i in module.commands
                if 'alias' not in module.commands[i]
            ]

            helptext = ', '.join(
                mnames) if mnames else module.category_info['description']
            cmd_embed.add_field(
                name=
                f"{module.category_info['pretty_name']} ({module.category_info['name']})",
                value=helptext,
                inline=False)

        cmd_embed.set_footer(
            text=f"Total Commands: {total} | Total Endpoints: {len(cmds_dict)}"
        )

        return cmd_embed
Exemplo n.º 7
0
async def avatar_function(message: discord.Message, args: List[str],
                          client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    user, _ = await parse_user_member_noexcept(message,
                                               args,
                                               client,
                                               default_self=True)

    embed = discord.Embed(description=f"{user.mention}'s Avatar",
                          color=load_embed_color(message.guild,
                                                 embed_colors.primary,
                                                 kwargs["ramfs"]))
    embed.set_image(url=user_avatar_url(user))
    embed.timestamp = datetime_now()
    try:
        await message.channel.send(embed=embed)
    except discord.errors.Forbidden:
        raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)
Exemplo n.º 8
0
async def help_function(message: discord.Message, args: List[str],
                        client: discord.Client, ctx: CommandCtx) -> Any:
    if not message.guild:
        return 1

    helpname: str = f"{BOT_NAME} Help"
    per_page: int = 10

    cmds = ctx.cmds
    cmds_dict = ctx.cmds_dict

    parser = Parser("help")
    pageP = parser.add_arg(["-p", "--page"], lambda s: int(s) - 1)
    commandonlyP = parser.add_arg("-c", lib_tparse.store_true, flag=True)

    try:
        parser.parse(args,
                     stderr=io.StringIO(),
                     exit_on_fail=False,
                     lazy=True,
                     consume=True)
    except lib_tparse.ParseFailureError:
        raise lib_sonnetcommands.CommandError("Could not parse pagecount")

    page = pageP.get(0)
    commandonly = commandonlyP.get() is True

    prefix = ctx.conf_cache["prefix"]
    help_helper = HelpHelper(message, message.guild, args, client, ctx, prefix,
                             helpname)

    if args:

        modules = {mod.category_info["name"] for mod in cmds}

        # Per module help
        if (a := args[0].lower()) in modules and not commandonly:

            description, commands, curmod = await help_helper.category_help(a)
            pagecount = (len(commands) + (per_page - 1)) // per_page

            cmd_embed = discord.Embed(
                title=
                f"{curmod.category_info['pretty_name']} (Page {page+1} / {pagecount})",
                description=description,
                color=load_embed_color(message.guild, embed_colors.primary,
                                       ctx.ramfs))
            cmd_embed.set_author(name=helpname)

            if not (0 <= page < pagecount):  # pytype: disable=unsupported-operands
                raise lib_sonnetcommands.CommandError(
                    f"ERROR: No such page {page+1}")

            for name, desc in commands[page * per_page:(page * per_page) +
                                       per_page]:
                cmd_embed.add_field(name=name, value=desc, inline=False)

            try:
                await message.channel.send(embed=cmd_embed)
            except discord.errors.Forbidden:
                raise lib_sonnetcommands.CommandError(
                    constants.sonnet.error_embed)

        # Per command help
        elif a in cmds_dict:
            try:
                await message.channel.send(
                    embed=await help_helper.single_command(a))
            except discord.errors.Forbidden:
                raise lib_sonnetcommands.CommandError(
                    constants.sonnet.error_embed)

        # Do not echo user input
        else:
            # lets check if they cant read documentation
            probably_tried_paging: bool
            try:
                probably_tried_paging = int(
                    args[0]) <= ((len(cmds) + (per_page - 1)) // per_page)
            except ValueError:
                probably_tried_paging = False

            no_command_text: str = f"No command {'or command module '*(not commandonly)}with that name"

            if probably_tried_paging:
                raise lib_sonnetcommands.CommandError(
                    f"{no_command_text} (did you mean `{prefix}help -p {int(args[0])}`?)"
                )

            raise lib_sonnetcommands.CommandError(no_command_text)
Exemplo n.º 9
0
async def profile_function(message: discord.Message, args: List[str],
                           client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    user, member = await parse_user_member_noexcept(message,
                                                    args,
                                                    client,
                                                    default_self=True)

    # Status hashmap
    status_map = {
        "online": "🟢 (online)",
        "offline": "⚫ (offline)",
        "idle": "🟡 (idle)",
        "dnd": "🔴 (dnd)",
        "do_not_disturb": "🔴 (dnd)",
        "invisible": "⚫ (offline)"
    }

    embed = discord.Embed(title="User Information",
                          description=f"User information for {user.mention}:",
                          color=load_embed_color(message.guild,
                                                 embed_colors.primary,
                                                 kwargs["ramfs"]))
    embed.set_thumbnail(url=user_avatar_url(user))
    embed.add_field(name="Username", value=str(user), inline=True)
    embed.add_field(name="User ID", value=str(user.id), inline=True)
    if member:
        embed.add_field(name="Status",
                        value=status_map[member.raw_status],
                        inline=True)
        embed.add_field(name="Highest Rank",
                        value=f"{member.top_role.mention}",
                        inline=True)
    embed.add_field(name="Created",
                    value=parsedate(user.created_at),
                    inline=True)
    if member:
        embed.add_field(name="Joined",
                        value=parsedate(member.joined_at),
                        inline=True)

    # Parse adding infraction count
    with db_hlapi(message.guild.id) as db:
        viewinfs = parse_boolean(
            db.grab_config("member-view-infractions") or "0")
        moderator = await parse_permissions(message,
                                            kwargs["conf_cache"],
                                            "moderator",
                                            verbose=False)
        if moderator or (viewinfs and user.id == message.author.id):
            embed.add_field(
                name="Infractions",
                value=f"{db.grab_filter_infractions(user=user.id, count=True)}"
            )

    embed.timestamp = datetime_now()
    try:
        await message.channel.send(embed=embed)
    except discord.errors.Forbidden:
        raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)
Exemplo n.º 10
0
            if probably_tried_paging:
                raise lib_sonnetcommands.CommandError(
                    f"{no_command_text} (did you mean `{prefix}help -p {int(args[0])}`?)"
                )

            raise lib_sonnetcommands.CommandError(no_command_text)

    # Total help
    else:

        try:
            await message.channel.send(
                embed=await help_helper.full_help(page, per_page))
        except discord.errors.Forbidden:
            raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)


async def grab_guild_info(message: discord.Message, args: List[str],
                          client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    guild = message.guild

    embed_col = load_embed_color(guild, embed_colors.primary, kwargs["ramfs"])

    guild_embed = discord.Embed(title=f"Information on {guild}",
                                color=embed_col)
    if guild.owner:
        guild_embed.add_field(name="Server Owner:", value=guild.owner.mention)