Metadata-Version: 2.4
Name: illest
Version: 2.3.2
Summary: The Python library for ILLEST: bots with commands, slash commands and buttons, end-to-end encrypted, and Rich Presence.
Author: VERAKS
License-Expression: MIT
Project-URL: Homepage, https://illest.world
Project-URL: Documentation, https://developer.illest.world/docs/introduction
Project-URL: Changelog, https://developer.illest.world/docs/changelog
Keywords: illest,illest.py,bot,chat bot,rich presence,e2ee,mls
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: websockets>=12.0
Requires-Dist: cryptography>=42.0
Requires-Dist: illest-crypto<3,>=2.1
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
Dynamic: license-file

# illest.py

The Python library for [ILLEST](https://illest.world): bots with prefix commands, slash commands, buttons, menus and forms, all
end-to-end encrypted, and Rich Presence for games and tools that show what their player is doing.

```bash
pip install illest
```

Python 3.10 or newer. The encryption engine, `illest-crypto`, comes with it as a compiled wheel for Windows and Linux (x86-64
and ARM64).

## A bot in twenty lines

```python
import illest
from illest import app_commands
from illest.ext import commands

bot = commands.Bot(command_prefix="!", intents=illest.Intents.default())


@bot.event
async def setup_hook():
    await bot.tree.sync()  # registers the slash commands below


@bot.event
async def on_ready():
    print(f"signed in as {bot.user}")


@bot.command()
async def ping(ctx: commands.Context):
    await ctx.reply("pong")


@bot.tree.command(description="Roll a die")
@app_commands.describe(sides="How many sides it has")
async def roll(interaction: illest.Interaction, sides: app_commands.Range[int, 2, 100] = 6):
    import random
    await interaction.response.send_message(f"{random.randint(1, sides)}")


bot.run("illb_...")
```

Make the bot and its token in ILLEST under **Settings → Developers**. Open the bot there, copy its invite link from
**Installation**, and add it to a server you manage.

To run against your own server instead of `chat.illest.world`, set `ILLEST_GATEWAY_URL` (for example
`ws://localhost:8766/gateway`) or pass `server_url=` to the client.

## What you get

- **The client:** `Client`, `commands.Bot`, `Intents`, `@bot.event`, `wait_for`, `setup_hook`.
- **Prefix commands** (`ext.commands`): commands, groups, cogs, extensions, checks, cooldowns, converters, `Greedy`, `Range`,
  flags, the help command, and hybrid commands that are slash commands too.
- **Slash commands** (`app_commands`): `CommandTree`, `@tree.command`, `Group`, `describe`, `choices`, `autocomplete`, `rename`,
  `Range`, `Transform`, context menus, `default_permissions`, `guild_only`, checks and cooldowns, `tree.sync(guild=...)`.
- **Interactions:** `response.send_message`, `defer` (with "thinking"), `edit_message`, `send_modal`, `followup`,
  `original_response`.
- **Components** (`ui`): `View`, `Button`, `Select`, `UserSelect`, `RoleSelect`, `ChannelSelect`, `MentionableSelect`, `Modal`,
  `TextInput`, and persistent views (`timeout=None` and `custom_id`, `bot.add_view`).
- **Background tasks** (`ext.tasks.loop`) with `before_loop`, `after_loop`, `change_interval` and times of day.
- **Messages:** `Embed`, `File`, `AllowedMentions`, `Colour`, `Permissions`, `PermissionOverwrite`,
  `utils.get/find/format_dt/oauth_url`.
- **Moderation:** `Member.ban/kick/timeout/add_roles/remove_roles/edit`, `Guild.unban/bans/audit_logs`, `TextChannel.purge`,
  and creating and editing channels, categories, roles and invites, behind the bot's scopes and the server's roles.
- **Rich Presence** (`illest.rpc`): `Presence` and `AsyncPresence` tell the person's friends what they are doing in your game or
  tool, through the ILLEST desktop app.
- Rate limits, reconnects and `run()`'s logging set-up, handled for you.

## What end-to-end encryption changes

ILLEST is end-to-end encrypted: the server stores ciphertext and holds no keys. A bot is built for that, and each of these is
deliberate. Moving a bot from discord.py? [The migration guide](docs/differences.md) has the full list, with what to write instead.

- **A bot is a device.** Its token enrols a device the first time it runs; the device key is kept under `~/.illest/bots/`. Keep
  that folder: losing it is losing the device.
- **A bot reads from when it joined.** `channel.history()` and `fetch_message()` return the messages this bot holds, from when it
  was let into the channel's group. There is nothing older to fetch: the server cannot read it either.
- **Commands, presses, picks and forms travel sealed**, as messages in the conversation that only the bot opens. The server never
  sees which command was used or with what.
- **`ephemeral=True` is a rendering rule.** Every honest client shows the message to its one reader only; inside an encrypted
  group nothing stronger exists, and the library does not pretend otherwise.
- **Who sent it is what their device proves.** `message.author_verified` and `interaction.sender_verified` say whether the
  sender's own device vouched for the account. Authorise nothing on a sender that is not verified.
- **Permissions are ILLEST's bits.** `illest.Permissions(ban_members=True).value` is the number to use in an ILLEST invite
  link; build it with `illest.Permissions` or the bot's Installation page rather than copying a number from elsewhere.
- **Intents filter, scopes grant.** An intent decides which events reach your handlers; the bot's scopes (set by its owner under
  Developers → Bot) decide what it may read and do. `Intents.default()` includes members and message content.
- **No voice.** A bot cannot join a call: calls are encrypted from each person's device. `VoiceChannel.connect()` raises.
- **No sharding.** One connection serves any number of servers; `AutoShardedBot` is `Bot`.
- **`tree.sync()` takes effect at once**, global commands included.

## Examples

`examples/` holds runnable bots: [basic](examples/basic_bot.py) (events and prefix commands), [slash commands](examples/slash_commands.py)
(groups, choices, autocomplete, context menus), [views](examples/views.py) (buttons, select menus, a persistent view, a modal),
[moderation](examples/moderation.py), [tasks and cogs](examples/tasks_and_cogs.py), and [a test bot](examples/test_bot.py) that
touches every part once. Each reads its token from `ILLEST_TOKEN`. [Rich Presence](examples/rich_presence.py) reads an application
id from `ILLEST_APP_ID` instead.

## Documentation

The documentation is at [developer.illest.world](https://developer.illest.world/docs/introduction). To build it here with
MkDocs: `pip install "illest[docs]"`, then `mkdocs serve` in this folder.

## Licence

MIT. `illest-crypto`, the compiled encryption engine it installs, is free to use and redistribute unmodified; see its own licence.
