Async Python client for the Polis Bot API
Project description
polis-bot
Async Python client for the Polis Bot API — build bots for the Polis messaging platform.
Requires Python 3.10+. Built on httpx and Pydantic v2.
Installation
pip install polis-bot
Quick Start
from polis_bot import PolisBot, CommandContext, MessageContext
bot = PolisBot("your-bot-token")
@bot.command("/start", description="Start the bot")
async def start(ctx: CommandContext):
await ctx.reply(f"Hello {ctx.user.display_name}! 🤖")
@bot.command("/help", description="Show help")
async def help_cmd(ctx: CommandContext):
await ctx.reply("**Commands:**\n- /start — Greet\n- /help — This message")
@bot.on_message
async def echo(ctx: MessageContext):
await ctx.reply(f"You said: {ctx.message.content}")
bot.run()
Commands are auto-registered with the server on startup. The bot long-polls for updates and dispatches them to the matching handler.
Command Arguments
Handler type hints drive automatic argument parsing — like FastAPI for bots:
@bot.command("/add", description="Add two numbers")
async def add(ctx: CommandContext, a: int, b: int):
await ctx.reply(f"{a + b}")
# /add 3 5 → "8"
The last str parameter absorbs remaining tokens:
@bot.command("/echo", description="Echo text")
async def echo_cmd(ctx: CommandContext, text: str):
await ctx.reply(text)
# /echo hello world → "hello world"
Supported types: str, int, float, bool, UUID, and Pydantic BaseModel subclasses. Invalid input returns a usage hint automatically.
File Handling
Sending files
# From a path
await bot.send_file(user_id, "image.png", content_type="image/png")
# From a Path object
from pathlib import Path
await bot.send_file(user_id, Path("report.pdf"), content_type="application/pdf")
# Via context
@bot.command("/cat", description="Send a cat picture")
async def cat(ctx: CommandContext):
await ctx.reply_file("cat.jpg", content_type="image/jpeg")
Receiving files
@bot.on_file
async def handle_file(ctx: MessageContext):
for att in ctx.message.attachments:
data = await bot.download_file(att.download_url)
# or save directly:
await bot.download_file_to(att.download_url, f"downloads/{att.file_name}")
await ctx.reply(f"Got **{att.file_name}** ({att.size_bytes} bytes)")
Lifecycle Events
from polis_bot import EventContext
@bot.on_event("BotStarted")
async def on_started(ctx: EventContext):
await bot.send_message(ctx.user.id, "Welcome! Send /help to get started.")
@bot.on_event("BotBlocked")
async def on_blocked(ctx: EventContext):
print(f"{ctx.user.display_name} blocked the bot")
Event types: BotStarted, BotBlocked, BotUnblocked, BotAdded, BotRemoved.
Startup Hook
@bot.on_startup
async def setup():
print(f"Running as @{bot.me.botname} ({bot.me.display_name})")
bot.me is populated before startup hooks run and returns cached BotInfo.
Error Handling
The SDK raises typed exceptions for API errors:
from polis_bot import PolisApiError, PolisAuthError, PolisRateLimitError
try:
await bot.send_message(user_id, "hello")
except PolisAuthError:
print("Invalid bot token")
except PolisRateLimitError as e:
print(f"Rate limited — retry after {e.retry_after}s")
except PolisApiError as e:
print(f"HTTP {e.status_code}: {e.message}")
| Exception | HTTP Status |
|---|---|
PolisAuthError |
401 |
PolisForbiddenError |
403 |
PolisNotFoundError |
404 |
PolisRateLimitError |
429 |
PolisApiError |
Any non-2xx |
Async Context Manager
async with PolisBot("token") as bot:
me = await bot.get_me()
await bot.send_message(user_id, "Hello!")
# client is automatically closed
Low-Level Polling
For full control over the update loop instead of using decorators:
async with PolisBot("token") as bot:
async for update in bot.poll(limit=20, timeout=30):
print(update.type, update.user.display_name)
if update.message and update.message.is_command:
await bot.send_message(update.user.id, "Got your command!")
Updates are automatically acknowledged after each batch. Disable with auto_ack=False:
async for update in bot.poll(auto_ack=False):
# manually acknowledge
await bot.acknowledge_updates([update.update_id])
API Reference
PolisBot(token, base_url="https://polis.krlv.org", *, timeout=30.0)
Properties
| Property | Description |
|---|---|
me |
Cached BotInfo (available after start() / run()) |
Decorators
| Decorator | Description |
|---|---|
@bot.command(name, *, description=None) |
Register a /command handler with auto-parsed args |
@bot.on_message |
Handle non-command text messages |
@bot.on_file |
Handle messages with file attachments |
@bot.on_event(event_type) |
Handle lifecycle events (BotStarted, etc.) |
@bot.on_startup |
Run a coroutine once on startup |
Methods
| Method | Description |
|---|---|
run(*, register_commands=True) |
Start polling and dispatch (blocking) |
start(*, register_commands=True) |
Async version of run() |
get_me() |
Get bot info |
send_message(user_id, content, *, reply_to_id=None) |
Send a text message |
send_file(user_id, file, *, filename=None, content_type=...) |
Upload a file |
download_file(download_url) |
Download file bytes |
download_file_to(download_url, dest) |
Download file to disk |
get_updates(*, limit, offset, timeout) |
Fetch pending updates |
acknowledge_updates(update_ids) |
Mark updates as delivered |
set_commands(commands) |
Register bot commands |
poll(*, limit=20, timeout=30, auto_ack=True) |
Async generator for long-polling |
close() |
Close the HTTP client |
Context Objects
| Class | Available On | Key Properties |
|---|---|---|
CommandContext |
@bot.command |
user, message, args, bot, reply(), reply_file() |
MessageContext |
@bot.on_message, @bot.on_file |
Same as CommandContext |
EventContext |
@bot.on_event |
user, bot |
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polis_bot-0.2.2.tar.gz.
File metadata
- Download URL: polis_bot-0.2.2.tar.gz
- Upload date:
- Size: 23.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9959cdf4ea23507e2c5978b3e9cb0eda8b3cf061cdc27d0a807a2f79644232e9
|
|
| MD5 |
cbe279e5eaeedf0609346fd84a2f3f68
|
|
| BLAKE2b-256 |
7793bbd36e7eb12e35c9a15724ada83354d7e9b8b2fed5b9e35095dbb1ed364b
|
Provenance
The following attestation bundles were made for polis_bot-0.2.2.tar.gz:
Publisher:
sdk-release.yml on roman-right/Polis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polis_bot-0.2.2.tar.gz -
Subject digest:
9959cdf4ea23507e2c5978b3e9cb0eda8b3cf061cdc27d0a807a2f79644232e9 - Sigstore transparency entry: 1008262710
- Sigstore integration time:
-
Permalink:
roman-right/Polis@495b431849dd9486ba6df405a7fc84fc1f65578d -
Branch / Tag:
refs/tags/sdk-v0.2.2 - Owner: https://github.com/roman-right
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
sdk-release.yml@495b431849dd9486ba6df405a7fc84fc1f65578d -
Trigger Event:
push
-
Statement type:
File details
Details for the file polis_bot-0.2.2-py3-none-any.whl.
File metadata
- Download URL: polis_bot-0.2.2-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddfe9f33e3ee72484231c054758ff6e2bcb888844bd7320cd610063b3921c721
|
|
| MD5 |
f698e7c9d2e79357ab77d679ace2540d
|
|
| BLAKE2b-256 |
00dff4459babb1fe9cbc9a2a5194153d6e6c0eb8064ceea8e754399c13932349
|
Provenance
The following attestation bundles were made for polis_bot-0.2.2-py3-none-any.whl:
Publisher:
sdk-release.yml on roman-right/Polis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polis_bot-0.2.2-py3-none-any.whl -
Subject digest:
ddfe9f33e3ee72484231c054758ff6e2bcb888844bd7320cd610063b3921c721 - Sigstore transparency entry: 1008262713
- Sigstore integration time:
-
Permalink:
roman-right/Polis@495b431849dd9486ba6df405a7fc84fc1f65578d -
Branch / Tag:
refs/tags/sdk-v0.2.2 - Owner: https://github.com/roman-right
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
sdk-release.yml@495b431849dd9486ba6df405a7fc84fc1f65578d -
Trigger Event:
push
-
Statement type: