Abc Reference

This Protocol simply defines how a Cache should work. This is going to only be useful if you either plan on working directly with an existing cache or wish to build your own.

Any form of internal cache is guranteed to implement this so you can treat it as a source of truth for usage. (Unless you bypass them)

class antispam.abc.Cache(*args, **kwargs)

A generic Protocol for any Cache to implement

async add_message(message: antispam.dataclasses.message.Message) None

Adds a Message to the relevant Member, creating the Guild/Member if they don’t exist

Parameters

message (Message) – The Message to add to the internal cache

Notes

This should silently create any Guild’s/Member’s required to fulfil this transaction

async delete_guild(guild_id: int) None

Removes a guild from the cache. This should also remove all members.

Parameters

guild_id (int) – The id of the guild we wish to remove

Notes

This fails silently.

async delete_member(member_id: int, guild_id: int) None

Removes a member from the cache.

Parameters
  • member_id (int) – The id of the member we wish to remove

  • guild_id (int) – The guild this member is in

Notes

This fails silently.

async drop() None

Drops the entire cache, deleting everything contained within.

async get_all_guilds() AsyncIterable[antispam.dataclasses.guild.Guild]

Returns a generator containing all cached guilds

Yields

Guild – A generator of all stored guilds

async get_all_members(guild_id: int) AsyncIterable[antispam.dataclasses.member.Member]

Fetches all members within a guild and returns them within a generator

Parameters

guild_id (int) – The guild we want members in

Yields

Member – All members in the given guild

Raises

GuildNotFound – The given guild was not found

async get_guild(guild_id: int) antispam.dataclasses.guild.Guild

Fetch a Guild dataclass populated with members

Parameters

guild_id (int) – The id of the Guild to retrieve from cache

Raises

GuildNotFound – A Guild could not be found in the cache with the given id

async get_member(member_id: int, guild_id: int) antispam.dataclasses.member.Member

Fetch a Member dataclass populated with messages

Parameters
  • member_id (int) – The id of the member to fetch from cache

  • guild_id (int) – The id of the guild this member is associated with

Raises
  • MemberNotFound – This Member could not be found on the associated Guild within the internal cache

  • GuildNotFound – The relevant guild could not be found

async initialize(*args, **kwargs) None

This method gets called once when the AntiSpamHandler init() method gets called to allow for setting up connections, etc

Notes

This is not required.

async reset_member_count(member_id: int, guild_id: int, reset_type: antispam.enums.reset_type.ResetType) None

Reset the chosen enum type back to the default value

Parameters
  • member_id (int) – The Member to reset

  • guild_id (int) – The guild this member is in

  • reset_type (ResetType) – An enum denoting the type of reset

Notes

This shouldn’t raise an error if the member doesn’t exist.

async set_guild(guild: antispam.dataclasses.guild.Guild) None

Stores a Guild in the cache

This is essentially a UPSERT operation

Parameters

guild (Guild) – The Guild that needs to be stored

Warning

This method should be idempotent.

The passed guild object should not experience a change to the callee.

async set_member(member: antispam.dataclasses.member.Member) None

Stores a Member internally and attaches them to a Guild, creating the Guild silently if required

Essentially an UPSERT operation

Parameters

member (Member) – The Member we want to cache

Warning

This method should be idempotent.

The passed member object should not experience a change to the callee.

class antispam.abc.Lib(*args, **kwargs)

A protocol to extend and implement for any libs that wish to hook into this package and work natively.

You also should to subclass antispam.libs.shared.base.Base as it implements a lot of shared functionality.

async check_message_can_be_propagated(message) antispam.dataclasses.propagate_data.PropagateData

Given a message from the relevant package, run all checks to check if this message should be propagated.

Notes

Should error on the following:
  • If not an instance of the library’s message class

  • If in dm’s

  • If the message is from yourself (the bot)

  • If self.handler.options.ignore_bots is True and the message is from a bot

  • If the guild id is in self.handler.options.ignored_guilds

  • If the member id is in self.handler.options.ignored_members

  • If the channel id is in self.handler.options.ignored_channels

  • If any of the member’s roles (id) are in self.handler.options.ignored_roles

PropagateData.has_perms_to_make_guild should be True if the member has permissions to kick and ban members

Parameters

message (Union[discord.Message, hikari.messages.Message, pincer.objects.Embed]) – The message to check

Returns

The data required within propagate

Return type

PropagateData

Raises

PropagateFailure – This raises an error with the .data attribute set. .data is what gets returned from within propagate itself.

async create_message(message) antispam.dataclasses.message.Message

Given a message to extract data from, create and return a Message class.

The following should be dumped together as content. Order doesn’t matter as long as it’s consistent.

  • All sticker urls for stickers in the message

  • The actual message content

  • All embeds cast to a string via embed_to_string

Parameters

message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – The message to extract data from

Returns

The flushed out message

Return type

Message

Raises

InvalidMessage – If it couldn’t create a message, I.e message only contained attachments

Warning

This is REQUIRED to be inline with the end options.

1if self.handler.options.delete_zero_width_chars:
2    content = (
3        content.replace("u200B", "")
4        .replace("u200C", "")
5        .replace("u200D", "")
6        .replace("u200E", "")
7        .replace("u200F", "")
8        .replace("uFEFF", "")
9    )
async delete_member_messages(member: antispam.dataclasses.member.Member) None

Given a member, traverse all duplicate messages and delete them.

Parameters

member (Member) – The member whose messages should be deleted

Notes

Just call delete_message on each message

If you need to fetch the channel, cache it please.

async delete_message(message) None

Given a message, call and handle the relevant deletion contexts.

Parameters

message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – The message to delete

Notes

This should handle given errors silently.

async dict_to_embed(data: dict, message, warn_count: int, kick_count: int)
Parameters
  • data (dict) – The data to build an embed from

  • message (Union[discord.Message, hikari.messages.Message]) – The message to extract data from

  • warn_count (int) – How many warns this person has

  • kick_count (int) – How many kicks this person has

Returns

The embed

Return type

Union[discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]

Notes

This is implemented in antispam.libs.shared.base.Base so assuming you subclass it you don’t need to create this.

async dict_to_lib_embed(data: Dict)

Create an Embed object using a dictionary and return that.

Parameters

data (Dict) – The data to create the embed from

Returns

The dictionary as an embed

Return type

Union[discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]

async embed_to_string(embed) str

Given an embed, return a string representation.

This string representation should include the following. Ordering does not matter as long as it is consistent.

  • The embeds title

  • The embeds description

  • The embeds footer text

  • The embeds author name

  • All names + values for embed fields

Parameters

embed (Union[discord.Embed, hikari.embeds.Embed]) – The embed to cast to string

Returns

The embed as a string

Return type

str

Notes

This is implemented in antispam.libs.shared.base.Base so assuming you subclass it you don’t need to create this.

async get_channel_by_id(channel_id: int)

Returns the given channel object for the id.

async get_channel_from_message(message)

Given a message, return the channel object it was sent in.

async get_channel_id(message) int

Returns the id of the channel this message was sent in.

get_file(path: str)

Returns a file object for the given path.

For example, in discord.py this is discord.File

async get_guild_id(message) int

Returns the id of the guild this message was sent in.

async get_member_from_message(message)

Given the message, return the Author’s object

Parameters

message (Union[discord.Message, hikari.messages.Message, pincer.objects.Embed]) – The message to extract it from

Returns

The member object

Return type

Union[discord.Member, hikari.guilds.Member, …]

async get_message_mentions(message) List[int]

Returns all the mention id’s from a message.

This should include:
  • People

  • Roles

  • Channels

async get_substitute_args(message) antispam.libs.shared.substitute_args.SubstituteArgs

Given a message, return the relevant class filled with data for usage within substitute_args

Parameters

message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – The message we are using for creation

Returns

A dataclass with the relevant data for substitution.

Return type

SubstituteArgs

is_dm(message) bool

Returns True if this message occurred in a dm, False otherwise.

Parameters

message – The discord message this is called on.

async is_member_currently_timed_out(member) bool

Given the libraries member object, return True if they are currently timed out or False otherwise.

Parameters

member (Union[discord.member, hikari.guilds.Member]) – The member to check agaisnt.

Returns

True if timed out, otherwise False

Return type

bool

async lib_embed_as_dict(embed) Dict

Given the relevant Embed object for your library, return it in dictionary form.

Parameters

embed (Union[discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]) – The embed

Returns

The embed as a dictionary

Return type

dict

async punish_member(original_message, member: antispam.dataclasses.member.Member, internal_guild: antispam.dataclasses.guild.Guild, user_message, guild_message, is_kick: bool, user_delete_after: Optional[int] = None, channel_delete_after: Optional[int] = None)

A generic method to handle multiple methods of punishment for a user. Supports: kicking, banning

Parameters
  • member (Member) – A reference to the member we wish to punish

  • internal_guild (Guild) – A reference to the guild this member is in

  • original_message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – Where we get everything from :)

  • user_message (Union[str, discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]) – A message to send to the user who is being punished

  • guild_message (Union[str, discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]) – A message to send in the guild for whoever is being punished

  • is_kick (bool) – Is it a kick? Else ban

  • user_delete_after (int, Optional) – An int value denoting the time to delete user sent messages after

  • channel_delete_after (int, Optional) – An int value denoting the time to delete channel sent messages after

Raises

MissingGuildPermissions – I lack perms to carry out this punishment

Returns

Did the punishment succeed?

Return type

bool

Notes

Due to early design decisions, this will only ever support kicking or banning. A pain for you and I.

async send_guild_log(guild, message, delete_after_time: Optional[int], original_channel, file=None) None

Sends a message to the guilds log channel

Parameters
  • guild (Guild) – The guild we wish to send this too

  • message (Union[str, discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]) – What to send to the guilds log channel

  • delete_after_time (Optional[int]) – How long to delete these messages after

  • original_channel (Union[discord.abc.GuildChannel,discord.abc.PrivateChannel,hikari.channels.GuildTextChannel,pincer.objects.Channel]) – Where to send the message assuming this guild has no guild log channel already set.

  • file – A file to send

Notes

This should catch any sending errors, log them and then proceed to return None.

If no log channel, don’t send anything.

async send_message_to_(target, message, mention: str, delete_after_time: Optional[int] = None) None

Send the given message to the target.

Parameters
  • target (Union[discord.abc.Messageable, hikari.channels.TextableChannel]) –

    Where to send the message.

    Types are unknown for Pincer at this time.

  • message (Union[str, discord.Embed, hikari.embeds.Embed, pincer.objects.Embed]) – The message to send

  • mention (str) – A string denoting a raw mention of the punished user

  • delete_after_time (Optional[int]) – When to delete the message after

Notes

This should implement Options.mention_on_embed

async substitute_args(message: str, original_message, warn_count: int, kick_count: int) str

Given a message, substitute in relevant arguments and return a valid string

Parameters
  • message (str) – The message to substitute args into

  • original_message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – The message to extract data from

  • warn_count (int) – How many warns this person has

  • kick_count (int) – How many kicks this person has

Returns

The message with substituted args

Return type

str

Notes

This is implemented in antispam.libs.shared.base.Base so assuming you subclass it you don’t need to create this.

async timeout_member(member, original_message, until: datetime.timedelta) None

Timeout the given member.

Parameters
  • member (Union[discord.Member, hikari.guilds.Member]) – The member to timeout

  • original_message – The message being propagated

  • until (datetime.timedelta) – How long to time them out for.

Raises
async transform_message(item: Union[str, dict], message, warn_count: int, kick_count: int)
Parameters
  • item (Union[str, dict]) – The data to substitute

  • message (Union[discord.Message, hikari.messages.Message, pincer.objects.UserMessage]) – The message to extract data from

  • warn_count (int) – How many warns this person has

  • kick_count (int) – How many kicks this person has

Returns

A template complete message ready for sending

Return type

Union[str, discord.Embed, hikari.embeds.Embed]

Notes

This is implemented in antispam.libs.shared.base.Base so assuming you subclass it you don’t need to create this.

async visualizer(content: str, message, warn_count: int = 1, kick_count: int = 2)

Returns a message transformed as if the handler did it

Parameters
  • content (Union[str, discord.Embed, hikari.embeds.Embed]) – What to transform

  • message (Union[discord.Message, hikari.messages.Message]) – Where to extract our values from

  • warn_count (int) – The warns to visualize with

  • kick_count (int) – The kicks to visualize with

Returns

The transformed content

Return type

Union[str, discord.Embed]

Notes

This is implemented in antispam.libs.shared.base.Base so assuming you subclass it you don’t need to create this.