ILLEST Developers

illest.py 2.3.1

Client and Bot

Read from the library itself: every signature and every word here is its own docstring.

Client

class

illest.Client

class Client(token: 'str | None' = None, server_url: 'str | None' = None, intents: 'Intents | None' = None, http_url: 'str | None' = None, read_missed: 'bool' = True, max_messages: 'int | None' = 1000, *, message_store: 'str | os.PathLike | None' = None, allowed_mentions: 'Any' = None, activity: 'Any' = None, status: 'Any' = None, heartbeat_timeout: 'float | None' = None, **_ignored: 'Any')

One bot account, one gateway, one event loop.

Events dispatch by name: define on_message, on_ready, on_interaction, on_member_join and so on with @client.event. An event with no handler is skipped silently: a missing handler is a choice, not an error.

The token is given to run(token) or start(token), or here (Client(token)), as this library's first version did.

event

event(coro: 'EventHandler') -> 'EventHandler'

Make a function an event handler: on_message, on_ready... One per event; it replaces the default.

Any coroutine is set on the client by its name, so @bot.event async def setup_hook() replaces the hook.

on_button

on_button(custom_id: 'str')

A callback for one button, matched by what it reports (this library's first version; a ui.View is the current way).

It runs only for a press on a message this bot sent, naming a button that message carried and left enabled, from somebody who could see the message. Any other press is dropped (and said once in the log): a press is a message any member can seal.

listen

listen(name: 'str | None' = None)

A listener: like event, but any number can listen to one event, beside its @event handler.

add_listener

add_listener(func: 'EventHandler', name: 'str | None' = None) -> 'None'

remove_listener

remove_listener(func: 'EventHandler', name: 'str | None' = None) -> 'None'

extra_events

property

wait_for

async
async wait_for(event: 'str', /, *, check: 'Callable[..., bool] | None' = None, timeout: 'float | None' = None) -> 'Any'

Wait for the next event ("message" or "on_message") that passes check, and return what it was handed.

Raises asyncio.TimeoutError after timeout seconds. One value is returned as itself, several as a tuple.

dispatch

dispatch(event: 'str', /, *args: 'Any', **kwargs: 'Any') -> 'None'

Fire an event ("message" runs on_message), from code of the bot's own; it runs as its own task.

on_error

async
async on_error(event_method: 'str', /, *args: 'Any', **kwargs: 'Any') -> 'None'

What a handler's exception does when the bot sets no on_error: the traceback, logged.

get_user

get_user(id: 'Any', /) -> 'User | None'

get_channel

get_channel(id: 'Any', /) -> 'Any'

get_partial_messageable

get_partial_messageable(id: 'Any', *, guild_id: 'Any' = None, type: 'Any' = None) -> 'PartialMessageable'

get_guild

get_guild(id: 'Any', /) -> 'Guild | None'

get_message

get_message(id: 'Any', /) -> 'Message | None'

get_emoji

get_emoji(id: 'Any', /) -> 'Any'

get_all_channels

get_all_channels()

get_all_members

get_all_members()

guilds

property

The servers the bot knows it is in.

users

property

emojis

property

private_channels

property

cached_messages

property

application_id

property

The bot's user id: on ILLEST the application and its bot account are one.

application

property

latency

property

How long the server took to answer the last heartbeat, in seconds. The first is sent on connecting, so this is known a round trip after the bot signs in (nan only before that answer).

rate_limits

property

Per action the bot has used: its limit, what is left of it now, the seconds spent waiting for it, and refusals.

persistent_views

property

tree

property

The bot's slash commands, when it has made an app_commands.CommandTree(client) (a commands.Bot always has one).

is_ready

is_ready() -> 'bool'

is_closed

is_closed() -> 'bool'

is_ws_ratelimited

is_ws_ratelimited() -> 'bool'

wait_until_ready

async
async wait_until_ready() -> 'None'

send_message

async
async send_message(channel_id: 'str', text: 'str | None' = None, *, reply_to: 'str | None' = None, thread_root: 'str | None' = None, embed: 'Any' = None, embeds: 'list[Any] | None' = None, view: 'Any' = None, mentions: 'list[int] | None' = None, attachments: 'list[dict] | None' = None, ephemeral_for: 'int | None' = None, client_id: 'str | None' = None) -> 'Message'

Seal and send a message (this library's first version; channel.send is the current way).

client_id is this message's own name: 8 to 64 letters, digits, - or _. Pass the same one again to retry a send whose answer never came back, and the server answers with the message it already stored instead of posting a second one.

fetch_media

async
async fetch_media(url: 'str') -> 'dict[str, Any] | None'

A picture at url, fetched once by this bot's server and sealed as a file, so it can be sent with a message and shown in place: its reference, or None when the server will not fetch it (its switch is off, the address is private, it is not a picture). Readers then open it from the conversation's sealed files and never reach url's host.

add_view

add_view(view: 'Any', *, message_id: 'Any' = None) -> 'None'

Keep a view answering across restarts: timeout=None and its own custom_id on every item, given here in setup_hook.

request

async
async request(action: 'str', data: 'dict[str, Any] | None' = None) -> 'dict[str, Any]'

Any server action by name, answered (or refused with a GatewayError subclass). Paced to its rate limit.

edit_message

async
async edit_message(channel_id: 'str', message_id: 'str', text: 'str') -> 'None'

Replace the text of one of this bot's own messages (this library's first version; message.edit is the current way).

delete_message

async
async delete_message(channel_id: 'str', message_id: 'str') -> 'None'

Take back one of this bot's own messages, on every client; its buttons stop answering.

redact_message

async
async redact_message(channel_id: 'str', message_id: 'str') -> 'None'

Destroy the stored ciphertext of anybody's message, as a moderator (moderate scope, and the permission there).

add_reaction

async
async add_reaction(channel_id: 'str', message_id: 'str', emoji: 'str') -> 'None'

Put an emoji on a message: one emoji, or a server's emoji as its <:name:id> token.

remove_reaction

async
async remove_reaction(channel_id: 'str', message_id: 'str', emoji: 'str') -> 'None'

send_typing

async
async send_typing(channel_id: 'str') -> 'None'

Show the bot as composing in a channel for a few seconds.

open_dm

async
async open_dm(user_id: 'int') -> 'DMChannel'

The direct conversation with a person, opened if it is not (messages.write).

create_dm

async
async create_dm(user: 'Any') -> 'DMChannel'

change_presence

async
async change_presence(*, activity: 'Any' = None, status: 'Any' = None) -> 'None'

What the bot shows, everywhere a person's status shows: the member list, its profile, direct messages.

Args: activity: One line under its name: Game("chess"), Streaming(name=..., url=...), Activity(type=ActivityType.watching, name="/help") (or listening), or CustomActivity("Type /help") for words of its own. None clears it. Each call replaces the line. status: Status.online, Status.idle, Status.dnd or Status.invisible (or those words). Left out, the status stays as it is. Invisible shows the bot as offline while it keeps working.

Everybody who shares a server or a conversation with the bot sees it. It lasts until the bot disconnects; when it connects again it shows the default its team set on the developer portal's Bot page, until this is called again.

Python
await bot.change_presence(activity=illest.Activity(type=illest.ActivityType.watching, name="/help"))
await bot.change_presence(status=illest.Status.idle, activity=illest.CustomActivity("Back soon"))

fetch_guilds

fetch_guilds(*, limit: 'int | None' = 200, before: 'Any' = None, after: 'Any' = None, with_counts: 'bool' = True) -> '_Listing'

Every server the bot is in (guilds.read): await it for a list, or async for over it.

fetch_guild

async
async fetch_guild(guild_id: 'Any', /, *, with_counts: 'bool' = True) -> 'Guild'

One server, with its channels and roles (guilds.read).

fetch_channel

async
async fetch_channel(channel_id: 'Any', /) -> 'Any'

A channel the bot can see. A server's channels are read with the server; a direct conversation is the one held.

fetch_invite

async
async fetch_invite(url: 'Any', /, **_: 'Any') -> 'Any'

join_guild

async
async join_guild(code: 'str') -> 'Guild | None'

Join a server by an invite code, as anybody does (guilds.read). None when the server asks applicants to apply first.

leave_guild

async
async leave_guild(guild_id: 'Any') -> 'None'

fetch_members

async
async fetch_members(guild_id: 'Any', *, limit: 'int | None' = None, query: 'str | None' = None) -> 'list[Member]'

The members of a server: everyone in a small one, a page of limit in a large one, or those whose name matches query (members.read).

fetch_user

async
async fetch_user(user_id: 'Any', /) -> 'User'

An account's public profile, by id.

kick

async
async kick(guild_id: 'Any', user_id: 'int', *, reason: 'str | None' = None) -> 'None'

Remove somebody from a server (moderate, and KICK_MEMBERS there above them).

ban

async
async ban(guild_id: 'Any', user_id: 'int', *, reason: 'str | None' = None) -> 'None'

unban

async
async unban(guild_id: 'Any', user_id: 'int', *, reason: 'str | None' = None) -> 'None'

timeout

async
async timeout(guild_id: 'Any', user_id: 'int', seconds: 'int', *, reason: 'str | None' = None) -> 'None'

Keep somebody from speaking in a server for seconds: 0 lifts it, 28 days at most (moderate).

upload_attachment

async
async upload_attachment(data: 'bytes', name: 'str', mime: 'str | None' = None) -> 'dict'

Seal a file here, send the ciphertext, and return the reference to attach to a message.

The same sealed format the first-party client makes, so a picture sent this way opens in its reader: a fresh key for the file, the key inside the message and never beside the bytes, and the server holding something it cannot open. A file over 8 MiB goes up in parts. Raises AttachmentError with a sentence (the server's own, when it refused: it knows the limit it enforced).

open_attachment

async
async open_attachment(ref: 'dict[str, Any]') -> 'bytes'

Fetch a sealed file a message carries and open it with the key the message holds.

setup_hook

async
async setup_hook() -> 'None'

Runs once the bot has signed in and before on_ready: load extensions, add_view, tree.sync() here.

login

async
async login(token: 'str | None' = None) -> 'None'

Take the token to sign in with. The sign-in itself is part of connect, since a bot proves its device on the socket.

connect

async
async connect(*, reconnect: 'bool' = True) -> 'None'

Connect and run until the bot is closed. A dropped socket is resumed, or signed in again, by itself.

start

async
async start(token: 'str | None' = None, *, reconnect: 'bool' = True) -> 'None'

login and connect: run the bot until it stops.

run

run(token: 'str | None' = None, *, reconnect: 'bool' = True, log_handler: 'logging.Handler | None' = Ellipsis, log_formatter: 'logging.Formatter | None' = None, log_level: 'int' = 20, root_logger: 'bool' = False) -> 'None'

Block on the bot until it stops. Ctrl-C stops it.

Sets up logging to the terminal first, unless the program has configured logging itself; pass log_handler=None to leave logging alone, or a handler of your own.

key_changed

key_changed(user_id: 'int') -> 'bool'

Is a key other than the pinned one waiting to be accepted for this account?

accept_key_change

accept_key_change(user_id: 'int') -> 'bool'

The operator's word that the key an account now shows is its own. Call it only after asking the person another way.

close

async
async close() -> 'None'

Stop: the socket closes and start returns.

clear

clear() -> 'None'

Ready this client to start again after close.

Bot

classfrom Client

illest.ext.commands.Bot

class Bot(command_prefix: 'Any' = <object object>, *, help_command: 'HelpCommand | None' = Ellipsis, tree_cls: 'type' = <class 'illest.app_commands.tree.CommandTree'>, description: 'str | None' = None, intents=None, token: 'str | None' = None, server_url: 'str | None' = None, owner_id: 'int | None' = None, owner_ids: 'Any' = None, strip_after_prefix: 'bool' = False, case_insensitive: 'bool' = False, sync_commands: 'bool' = True, **options: 'Any')

A Client that also parses prefix commands out of message bodies.

commands

property

Every command once, aliases folded. By name (aliases too): all_commands.

help_command

property

tree

property

The bot's slash commands and context menus: @bot.tree.command(), then await bot.tree.sync().

add_command

add_command(command: 'Command', /) -> 'None'

remove_command

remove_command(name: 'str', /) -> 'Command | None'

walk_commands

walk_commands() -> 'Iterator[Command]'

hybrid_command

hybrid_command(name: 'str | None' = None, with_app_command: 'bool' = True, *args: 'Any', **options: 'Any')

A command used both as !name and as /name.

hybrid_group

hybrid_group(name: 'str | None' = None, with_app_command: 'bool' = True, *args: 'Any', **options: 'Any')

add_check

add_check(func: 'Check', /, *, call_once: 'bool' = False) -> 'None'

remove_check

remove_check(func: 'Check', /, *, call_once: 'bool' = False) -> 'None'

is_owner

async
async is_owner(user: 'Any', /) -> 'bool'

Whether user owns this bot: owner_id/owner_ids when given, else the account that made the bot (the server says).

get_prefix

async
async get_prefix(message: 'Any', /) -> 'Any'

load_extension

async
async load_extension(name: 'str', *, package: 'str | None' = None) -> 'None'

Import a module and run its async def setup(bot): await bot.load_extension("cogs.music").

unload_extension

async
async unload_extension(name: 'str', *, package: 'str | None' = None) -> 'None'

reload_extension

async
async reload_extension(name: 'str', *, package: 'str | None' = None) -> 'None'

get_command

get_command(name: 'str') -> 'Command | None'

A command by its name or an alias; "tag add" finds a subcommand.

command

command(name: 'str | None' = None, help: 'str | None' = None, **options: 'Any')

group

group(name: 'str | None' = None, help: 'str | None' = None, **options: 'Any')

check

check(predicate: 'Check') -> 'Check'

A check every command must pass.

before_invoke

before_invoke(hook: 'Callable')

after_invoke

after_invoke(hook: 'Callable')

add_cog

async
async add_cog(cog: 'Cog', /, *, override: 'bool' = False, guild: 'Any' = None, guilds: 'Any' = None) -> 'None'

remove_cog

async
async remove_cog(name: 'str') -> 'Cog | None'

get_cog

get_cog(name: 'str') -> 'Cog | None'

get_context

async
async get_context(message: 'Any') -> 'Context | None'

process_commands

async
async process_commands(message: 'Any', /) -> 'None'

Run the command a message names, if it names one. A message is processed once, however often this is called.

invoke

async
async invoke(ctx: 'Context') -> 'None'

on_command_error

async
async on_command_error(ctx: 'Context', error: 'CommandError') -> 'None'

What happens to a command's error when the bot has no on_command_error of its own.

The person's mistakes are answered with the sentence; a check that said no is answered quietly to them alone; an unknown command is silence; what the command itself raised is logged with its traceback and answered with one line.

menu

menu() -> 'list[dict[str, Any]]'

The / menu this bot would list: one row per visible command whose name the menu can show.

sync_menu

async
async sync_menu() -> 'list[dict[str, Any]]'

List this bot's commands in the app's / menu now, replacing what was listed. Returns what the server kept.

With slash commands in bot.tree, await bot.tree.sync() lists both (a sync replaces the whole menu).

AutoShardedBot

classfrom Bot

illest.ext.commands.AutoShardedBot

class AutoShardedBot(command_prefix: 'Any' = <object object>, *, help_command: 'HelpCommand | None' = Ellipsis, tree_cls: 'type' = <class 'illest.app_commands.tree.CommandTree'>, description: 'str | None' = None, intents=None, token: 'str | None' = None, server_url: 'str | None' = None, owner_id: 'int | None' = None, owner_ids: 'Any' = None, strip_after_prefix: 'bool' = False, case_insensitive: 'bool' = False, sync_commands: 'bool' = True, **options: 'Any')

A Bot: ILLEST has no shards, so this is the same bot under another name.