WarnSystem

API Reference

class warnsystem.api.API(bot: Red, config: Config, cache: MemoryCache)[source]

Bases: object

Interact with WarnSystem from your cog.

To import the cog and use the functions, type this in your code:

warnsystem = bot.get_cog('WarnSystem').api

Warning

If warnsystem is None, the cog is not loaded/installed. You won’t be able to interact with the API at this point.

Tip

You can get the cog version by doing this

version = bot.get_cog('WarnSystem').__version__
await get_case(guild: Guild, user: User | Member, index: int) dict[source]

Get a specific case for a user.

Parameters:
Returns:

A dict which has the following body:

Return type:

dict

Raises:

NotFound – The case requested doesn’t exist.

await get_all_cases(guild: Guild, user: User | Member | None = None) list[source]

Get all cases for a member of a guild.

Parameters:
  • guild (discord.Guild) – The guild where you want to get the cases from.

  • user (Optional[Union[discord.User, discord.Member]]) – The user you want to get the cases from. If this arguments is omitted, all cases of the guild are returned.

Returns:

A list of all cases of a user/guild. The cases are sorted from the oldest to the newest.

If you specified a user, you should get something like this:

[
    {  # case #1
        "level"     : int,  # between 1 and 5, the warning level
        "author"    : Union[discord.Member, str],  # the member that warned the user
        "reason"    : Optional[str],  # the reason of the warn, can be None
        "time"      : datetime.datetime,  # the date when the warn was set
    },
    {
        # case #2
    },
    # ...
]

However, if you didn’t specify a user, you got all cases of the guild. As for the user, you will get a list of the cases, with another key for specifying the warned user:

{  # case #1
    "level"     : int,  # between 1 and 5, the warning level
    "author"    : Union[discord.Member, str],  # the member that warned the user
    "reason"    : Optional[str],  # the reason of the warn, can be None
    "time"      : datetime.datetime,  # the date when the warn was set

    "member"    : discord.User,  # the member warned, this key is specific to guild
}

Return type:

list

await edit_case(guild: Guild, user: User | Member, index: int, new_reason: str) bool[source]

Edit the reason of a case.

Parameters:
  • guild (discord.Guild) – The guild where you want to get the case from.

  • user (Union[discord.User, discord.Member]) – The user you want to get the case from.

  • index (int) – The number of the case you want to edit.

  • new_reason (str) – The new reason to set.

Returns:

True if the action succeeded.

Return type:

bool

Raises:
  • BadArgument – The reason is above 1024 characters. Due to Discord embed rules, you have to make it shorter.

  • NotFound – The case requested doesn’t exist.

await get_modlog_channel(guild: Guild, level: int | str | None = None) TextChannel[source]

Get the WarnSystem’s modlog channel on the current guild.

When you call this, the channel is get with the following order:

  1. Get the modlog channel associated to the type, if provided

  2. Get the defult modlog channel set with WarnSystem

  3. Get the Red’s modlog channel associated to the server

Parameters:
  • guild (discord.Guild) – The guild you want to get the modlog from.

  • level (Optional[Union[int, str]]) –

    Can be an int between 1 and 5, a str ("all") or None.

    • If the argument is omitted (or None is provided), the default modlog channel will be returned.

    • If an int is given, the modlog channel associated to this warning level will be returned. If a specific channel was not set for this level, the default modlog channel will be returned instead.

    • If "all" is returned, a dict will be returned. It should be built like this:

      {
          "main"      : 012345678987654321,
          "1"         : None,
          "2"         : None,
          "3"         : None,
          "4"         : 478065433996537900,
          "5"         : 567943553912O46428,
      }
      

      A dict with the possible channels is returned, associated with an int corresponding to the channel ID set, or None if it was not set.

      For technical reasons, the default channel is actually named "main" in the dict.

Returns:

channel – The channel requested.

Note

It can be None if the channel doesn’t exist anymore.

Return type:

discord.TextChannel

Raises:

NotFound – There is no modlog channel set with WarnSystem or Red, ask the user to set one.

await get_embeds(guild: Guild, member: Member | UnavailableMember, author: Member | str, level: int, reason: str | None = None, time: timedelta | None = None, date: datetime | None = None, message_sent: bool = True) tuple[source]

Return two embeds, one for the modlog and one for the member.

Warning

Unlike for the warning, the arguments are not checked and won’t raise errors if they are wrong. It is recommanded to call warn() and let it generate the embeds instead.

Parameters:
  • guild (discord.Guild) – The Discord guild where the warning takes place.

  • member (Union[discord.Member, UnavailableMember]) – The warned member. Should only be UnavailableMember in case of a hack ban.

  • author (Union[discord.Member, str]) – The moderator that warned the user. If it’s not a Discord user, you can specify a str instead (e.g. “Automod”).

  • level (int) – The level of the warning which should be between 1 and 5.

  • reason (Optional[str]) – The reason of the warning.

  • time (Optional[timedelta]) – The time before the action ends. Only for mute and ban.

  • date (Optional[datetime]) – When the action was taken.

  • message_sent (bool) – Set to False if the embed couldn’t be sent to the warned user.

Returns:

A tuple with the modlog embed at index 0, and the user embed at index 1.

Return type:

tuple

await maybe_create_mute_role(guild: Guild) bool[source]

Create the mod role for WarnSystem if it doesn’t exist. This will also edit all channels to deny the following permissions to this role:

  • send_messages

  • add_reactions

  • speak

Parameters:

guild (discord.Guild) – The guild you want to set up the mute in.

Returns:

  • False if the role already exists.

  • list if the role was created, with a list of errors for each channel. Empty list means completly successful edition.

Return type:

Union[bool, list]

Raises:
await format_reason(guild: Guild, reason: str | None = None) str[source]

Reformat a reason with the substitutions set on the guild.

Parameters:
  • guild (discord.Guild) – The guild where the warn is set.

  • reason (str) – The string you want to reformat.

Returns:

The reformatted string

Return type:

str

await warn(guild: Guild, members: Iterable[Member | UnavailableMember], author: Member | str, level: int, reason: str | None = None, time: timedelta | None = None, date: datetime | None = None, ban_days: int | None = None, log_modlog: bool | None = True, log_dm: bool | None = True, take_action: bool | None = True, automod: bool | None = True, progress_tracker: Callable[[int], Awaitable[None]] | None = None) bool[source]

Set a warning on a member of a Discord guild and log it with the WarnSystem system.

Tip

The message that comes with the following exceptions are already translated and ready to be sent to Discord:

Parameters:
  • guild (discord.Guild) – The guild of the member to warn

  • member (Iterable[Union[discord.Member, UnavailableMember]]) – The member that will be warned. It can be an instance of warnsystem.api.UnavailableMember if you need to ban someone not in the guild.

  • author (Union[discord.Member, str]) – The member that called the action, which will be associated to the log.

  • level (int) –

    An int between 1 and 5, specifying the warning level:

    1. Simple DM warning

    2. Mute (can be temporary)

    3. Kick

    4. Softban

    5. Ban (can be temporary ban, or hack ban, if the member is not in the server)

  • reason (Optional[str]) – The optional reason of the warning. It is strongly recommanded to set one.

  • time (Optional[timedelta]) – The time before cancelling the action. This only works for a mute or a ban.

  • date (Optional[datetime]) – When the action was taken. Only use if you want to overwrite the current date and time.

  • ban_days (Optional[int]) – Overwrite number of days of messages to delete for a ban. Only used for warnings level 4 or 5. If this is omitted, the bot will fall back to the user defined setting.

  • log_modlog (Optional[bool]) – Specify if an embed should be posted to the modlog channel. Default to True.

  • log_dm (Optional[bool]) – Specify if an embed should be sent to the warned user. Default to True.

  • take_action (Optional[bool]) – Specify if the bot should take action on the member (mute, kick, softban, ban). If set to False, the bot will only send a log embed to the member and in the modlog. Default to True.

  • automod (Optional[bool]) – Set to False to skip automod, preventing multiple warnings at once and saving performances. Automod might trigger on a next warning though.

  • progress_tracker (Optional[Callable[[int], Awaitable[None]]]) –

    an async callable (function or lambda) which takes one argument to follow the progress of the warn. The argument is the number of warns committed. Here’s an example:

    i = 0
    message = await ctx.send("Mass warn started...")
    
    async def update_count(count):
        i = count
    
    async def update_msg():
        await message.edit(content=f"{i}/{len(members)} members warned.")
        await asyncio.sleep(1)
    
    await api.warn(guild, members, ctx.author, 1, progress_tracker=update_count)
    

Returns:

A dict of members which couldn’t be warned associated to the exception related.

Return type:

dict

Raises:
  • InvalidLevel – The level must be an int between 1 and 5.

  • BadArgument – You need to provide a valid discord.Member object, except for a hackban where a discord.User works.

  • MissingMuteRole – You’re trying to mute someone but the mute role was not setup yet. You can fix this by calling maybe_create_mute_role().

  • LostPermissions – The bot lost a permission to do something (it had the perm before). This can be lost permissions for sending messages to the modlog channel or interacting with the mute role.

  • MemberTooHigh – The bot is trying to take actions on someone but their top role is higher than the bot’s top role in the guild’s hierarchy.

  • NotAllowedByHierarchy – The moderator trying to warn someone is lower than them in the role hierarchy, while the bot still has permissions to act. This is raised only if the hierarchy check is enabled.

  • MissingPermissions – The bot lacks a permissions to do something. Can be adding role, kicking or banning members.

  • discord.errors.NotFound – When the user ID provided for hackban isn’t recognized by Discord.

  • discord.errors.HTTPException – Unknown error from Discord API. It’s recommanded to catch this potential error too.

enable_automod()[source]

Enable automod checks and listeners on the bot.

disable_automod()[source]

Disable automod checks and listeners on the bot.

await automod_check_for_autowarn(guild: Guild, member: Member, author: Member, level: int)[source]

Iterate through member’s modlog, looking for possible automatic warns.

Level is the last warning’s level, which will filter a lot of possible autowarns and, therefore, save performances.

This can be a heavy call if there are a lot of possible autowarns and a long modlog.

Errors

Custom error handling used for the cog and the API.

If you need to prevent and exception, do it like this:

warnsystem = bot.get_cog('WarnSystem')
api = cog.api
errors = cog.errors

try:
    await api.warn(5, user, "my random reason")
except discord.errors.Forbidden:
    print("Missing permissions")
except errors.InvalidLevel:
    print("Wrong warning level")
except:
    # occurs for any exception
    print("Fatal error")
else:
    # executed if the try succeeded
    print("All good")
finally:
    # always executed
    print("End of function")
exception warnsystem.errors.InvalidLevel[source]

Bases: Exception

The level argument for warn() is wrong. It must be between 1 and 5.

exception warnsystem.errors.NotFound[source]

Bases: Exception

Something was not found in the WarnSystem data. The meaning of this exception depends of what you called, it may be a missing WarnSystem channel.

exception warnsystem.errors.MissingMuteRole[source]

Bases: Exception

You requested a mute warn but the mute role doesn’t exist. Call maybe_create_role() to fix this.

exception warnsystem.errors.BadArgument[source]

Bases: Exception

The arguments provided for your request are wrong, check the types.

exception warnsystem.errors.MissingPermissions[source]

Bases: Exception

The bot lacks a permission to do an action.

This is raised instead of discord.errors.Forbidden to prevent a useless API call, we check the bot’s permissions before calling.

exception warnsystem.errors.MemberTooHigh[source]

Bases: Exception

The member to take action on is above the bot in the guild’s role hierarchy.

To fix this, set the bot’s top role above the member’s top role. For more informations about Discord Permissions, read this: https://support.discordapp.com/hc/en-us/articles/206029707

This is raised instead of discord.errors.Forbidden to prevent a useless API call, we check the bot’s permissions before calling.

exception warnsystem.errors.NotAllowedByHierarchy[source]

Bases: Exception

The bot is set to respect the role hierarchy; the moderator requested a warn against someone equal or higher than them in the hierarchy, which is not allowed by Discord permissions rules.

The moderator must have a role higher than the warned member to continue.

Note

This cannot be raised if the admins disabled the role hierarchy check.

exception warnsystem.errors.LostPermissions[source]

Bases: Exception

The bot lost a permission it had.

This can be the permission to send messages in the modlog channel or use the mute role.

exception warnsystem.errors.SuicidePrevention[source]

Bases: Exception

This is raised when the bot attempts to warn itself.

Warning Red will cause issues and is not designed for this.