ILLEST Developers

Release notes

2.3.1

Uploads on chat.illest.world. Every request the library makes over HTTP names itself (illest.py/<version>), where it said Python-urllib/3.x. The edge in front of chat.illest.world refused that with a 403 before the server saw it, so a bot's files and an embed's fetched pictures were never uploaded there, and a picture stayed a link.

Status. change_presence shows the bot's status and activity to everybody who shares a server or a conversation with it, in the member list, on its profile and in direct messages. An activity and custom words replace each other, status takes the words "online", "idle", "dnd" and "invisible" too, and bot.activity and bot.status say what it last showed. A bot's team can set what it shows on connecting without code, on the developer portal's Bot page. See Status and activity.

2.3.0

Layouts. ui.LayoutView with Container, Section, TextDisplay, Thumbnail, MediaGallery, File, Separator and ActionRow. Buttons and select menus inside it work as a View's do, and editing the message replaces the layout.

Pictures. An embed's image, thumbnail and icons, and a layout's pictures, are fetched once by the bot's server and sealed with the message (Client.fetch_media), so no reader's app fetches an outside address. attachment://name works everywhere a picture does.

Answers. interaction.response.send_toast(text, alert=False) for a short notice to the person who pressed. send(..., ask_reply=True) or illest.AskReply(placeholder=..., user=...) to open the reply box on a message.

Forms. ui.NumberInput, ui.RadioGroup, ui.CheckboxGroup, ui.Checkbox and ui.FileUpload; select menus and ui.TextDisplay inside a form; ui.Label(text=, description=, component=) titles any of them. Every answer is checked against its field, and a refused one is explained to the person privately.

Commands. The app lists every bot's commands in its / menu as soon as tree.sync() runs, on every device of everyone who can use them.

Fixes.

  • A picture whose upload the server refuses stays an address, offered to readers as a link, and the message is still sent. It used to fail the whole message, so a command that sent an embed showed nothing at all. The reason is logged as a warning.
  • A slash command or context menu that raises before answering, or a check that refuses it, now tells the person privately: "Something went wrong running /name.", or what the check said. A command or error handler that answered is left alone.
  • An upload refused with no reason now says its status ("That file could not be uploaded (HTTP 401)."), and a bot that could not get an upload ticket logs why before trying its session token.
  • A mention of a server member the bot had not met as a user (ctx.author.mention, say) went out as <@1> and notified nobody. It is now written as their name and notifies them: members of the bot's servers are named, and anybody else is looked up once. A message's author is looked up the same way before on_message, so it is no longer user-1.
  • A bot whose token holds no messages scope stopped at start with a traceback. It now says in one line which scope its token lacks and where to give it, and run() ends with exit code 1. A bot that listens for no message carries on without it.

2.2.0

Rich Presence (illest.rpc, D-354). A game, a tool or a script tells the person's friends what they are doing in it, through the ILLEST desktop app on the same computer. See Rich Presence.

  • Presence blocks and AsyncPresence is the same for asyncio: connect(), update(), clear(), close() and ping(), and both work as context managers.
  • update() takes two lines, a start and an end, a large and a small picture (an application's image key or an https:// address) with their hover text, a party count, up to two link buttons and the kind: playing, listening, watching or competing. Every argument is checked before it is sent.
  • Both reconnect by themselves when the desktop app restarts and send the last activity again.
  • Errors name what happened: NotRunning, HandshakeRefused, Blocked, UnknownApplication, InvalidActivity, NotConnected and ConnectionLost, all RPCError.
  • The local protocol is documented in full, for clients in other languages.

Needs ILLEST desktop 2.17.0 or newer, and an application registered under Settings → Developers.

Connecting holds up on more networks. Every address the server has is tried, the next a quarter of a second after the first (happy eyeballs), so a network that lists an IPv6 address it cannot route connects over IPv4 instead of timing out. Signing in tries four times before giving up, and then raises GatewayNotFound with a sentence saying what happened, not a traceback.

The package is illest now: pip install illest. illest.py, the name 2.1.0 went out under, installs it, so nothing that used it breaks; change it when convenient. The library's name, illest.py, and import illest are unchanged.

Smaller things:

  • latency is known a round trip after signing in: the first heartbeat goes on connecting. Before, a !ping answered straight after start said nan ms.
  • A bot's handle ends in .bot (music.bot, D-370), so it never takes a name a person could have. name and str(bot.user) are the handle; display_name is the name it is shown by.

2.1.0 (first published release)

The first release of the library for ILLEST bots (D-339). Moving a bot from discord.py: the migration guide lists every difference and why.

Install. pip install illest.py (since 2.2.0, pip install illest), with import illest in your code. It brings in illest-crypto, the compiled encryption engine, built for Windows and for Linux on x86-64 and ARM64. Python 3.10 or newer.

Client and Bot

  • Client and commands.Bot take their token at run() or start(), set logging up as they run, and reconnect by themselves.
  • Intents, @client.event for any coroutine (setup_hook included), wait_for, on_error(event, *args), wait_until_ready.
  • Events carry their objects as arguments. Among them: on_message_edit(before, after), on_reaction_add(reaction, user), on_member_update(before, after), on_voice_state_update, on_typing(channel, user, when), the raw events, and the guild channel and role events.
  • Requests are paced per action, under the limits the server sets.

Models. Users, members, servers, channels, roles, messages, embeds, colours, Permissions, and errors for each way a call can fail.

ext.commands

  • Prefix commands, groups, cogs and extensions; bot.commands as a set, bot.all_commands as a dict.
  • Converters for members, users, roles, channels and colours, plus Greedy, Range and flag converters.
  • Checks for permissions and roles; cooldowns and max_concurrency.
  • The help command, with hooks to change what it says.
  • Hybrid commands, which work as both prefix and slash commands.

app_commands

  • bot.tree and CommandTree.sync(), everywhere or for one server.
  • Options, choices (Choice[str] hands over the picked Choice), ranges and autocomplete.
  • Groups and subcommands.
  • User and message context menus, which appear under "Apps" on a member or a message.
  • default_permissions, guild_only (a command used outside servers), and checks and cooldowns.
  • Interaction with response, defer (shows "thinking"), followup, edit_original_response, and ephemeral answers that only the user sees.

ui

  • View with buttons and select menus: strings, users, roles, channels.
  • Persistent views, which keep answering after a restart.
  • Modal with TextInput.

ext.tasks. @tasks.loop with seconds, minutes, hours, or times of day.

Inviting a bot. illest.utils.oauth_url(client_id, permissions=...) gives the invite link. The person who opens it picks a server they manage and the permissions to grant. The bot then joins with a role of its own holding those permissions. A private bot can be added only by its owner.

Examples. examples/ has five bots:

  • prefix commands and events;
  • slash commands;
  • buttons, menus and forms;
  • moderation;
  • tasks and cogs.

Each one runs unchanged against a real server in the conformance suite.

Tokens. A rotated token, started on the machine where the bot already ran, keeps the bot's device, its identity key and its conversations. On a machine that never ran the bot, it starts as a new device and says how to carry identity.json over.

Channel ids. A channel's id is found whether or not it has its leading zeros, so a bot always answers in the conversation it was let into.

2.0.0

The first library: a Client with on_message, commands set from the developer portal, and sealed replies. Never published.