slimbots
Shared plumbing for slim-m bot templates in this repo.
This is not a typed model of slim-m's API. There is no Channel class, no
Message object, no cache, no event hierarchy - the kind of thing a
discord.js-shaped SDK would give you for a few hundred endpoints. slim-m's
entire bot surface is: log in with a token, call REST, hold one websocket,
track a per-scope seq. That is what this package covers:
- authentication (
Authorization: Bearer, a realUser-Agent,GET /me) - a REST helper,
Client.call, for any route a template needs, including a raw (non-JSON) body and extra headers for an attachment upload - an idempotent
sendthat keeps the message id fixed across a retry, retries only a genuinely uncertain failure - a network error, a 5xx, or a 429 - never a rejected 4xx, and can carryattachment_ids - the websocket connect and hello handshake (
Connection) - the reconnect loop with exponential backoff, and treating a
401as terminal rather than retryable (run_forever) - a
seqcursor in sqlite and the/synccatch-up call (cursor) - refusing to carry a token over plain
ws://to anything but a loopback address (socket_url)
It deliberately does not give you a typed route client, a cache, or an
event-object hierarchy. See docs/bots/building-bots.md in slim-m for the
protocol this wraps, and bot-ping/ in this repo for the same protocol
written out with nothing hidden - it stays free of this package on purpose,
so there is always one template that shows the whole thing in one file.
Testing a bot built on this
slimbots.testing.FakeClient is a Client that never touches the network,
for unit-testing a bot's command handlers - the thing every template but
this package's own tests had no way to do without a live deployment. It
records every call in .calls, auto-answers a message send and records it
separately in .sent (the one route every template calls on every command),
and raises immediately on anything else the bot under test calls that was
not stubbed with respond(method, path, response), so a forgotten stub
fails the test loudly instead of hanging.
from slimbots.testing import FakeClient
client = FakeClient(me_id="bot-1")
handle_message(client, conn, "bot-1", "chan-1", {"author_id": "u1", "content": "!ping", "id": "m1"})
assert client.sent[0]["content"] == "pong"
It is not imported by slimbots/__init__.py, so it costs nothing for a
template that never writes a test. bot-reminders/test_bot.py is a worked
example against a real template's handlers. It is not a mock of slim-m's
API - concurrency and money-safety still need a real sqlite connection and
real threads racing it, the way bot-casino/test_concurrency.py does.
Hand-written, not generated
slim-m's wire contract is schema/openapi.yaml, and
crates/slimm-server/tests/openapi_contract.rs already fails CI on drift, so
a generated client would stay honest automatically. This package is
hand-written anyway. What it wraps is not route-shaped: auth, a socket, and
a retry policy, not a set of typed request/response pairs. A generator
produces that badly, and slim-m already prefers hand-written DTOs and models
on both the server and the client for the same reason. If somebody wants a
fully typed route client later, generating one from openapi.yaml is a
reasonable project - it just is not this one.
Installing
The distribution is named slim-m on PyPI; the import stays slimbots.
pip install slim-m
To run against unreleased changes, install from git instead:
pip install "slim-m @ git+https://github.com/NC1107/slim-bots.git@main#subdirectory=slimbots"
Each template's requirements.txt pins one of those two lines.
Releasing
.github/workflows/publish.yml builds and uploads on a published GitHub
release, using PyPI trusted publishing - it exchanges the workflow's own
OIDC identity for an upload token, so there is no API token stored in this
repo. The publisher on PyPI must name this repository, publish.yml, and
the pypi environment, or the exchange is refused.
Bump version in pyproject.toml, then publish a release.
Tests
pip install -e ".[dev]"
pytest
Covers the retry policy (which errors retry, which do not, and that the
message id and content never change across a retry), the reconnect loop's
backoff and its terminal handling of a 401, and socket_url's loopback-only
refusal of plaintext ws://.
Release files for slim-m 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| slim_m-0.2.0.tar.gz | 13.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| slim_m-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.0 kB
Release files / slim_m-0.2.0.tar.gz
| Download URL | slim_m-0.2.0.tar.gz |
|---|---|
| Size | 13.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
80aef72e98ce35cc1a6df65e37d75de74c31fd5a4017d74ebd4eee4ca0ae170c
|
|
BLAKE2b-256 checksum How to use checksums |
33196210ad9f9d156083f52b70e4f4bc7460eabce7e0b252e01e48ef82e120cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / slim_m-0.2.0-py3-none-any.whl
| Download URL | slim_m-0.2.0-py3-none-any.whl |
|---|---|
| Size | 12.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
16de509aa3896f1484627b5bad3fb77bd6a83756eeee6649a9d6aa786ad3595f
|
|
BLAKE2b-256 checksum How to use checksums |
62de24a6d9498ff7269647aefbf13823bc66f9cea199fd84fb3f72cef7da2a64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log