Asynchronous Python tool for efficiently sending MAX messages, media, and inline keyboards with optional MongoDB logging.
Project description
max_sender: Asynchronous MAX Broadcast Sender
max_sender is an asynchronous Python package for bulk delivery through the MAX bot API. It keeps the original workflow intact where it matters: one async sender instance, batched delivery, retry handling for temporary failures, optional MongoDB logging, and support for text, media, and inline keyboards.
Features
- Async batch delivery over
aiohttp - One
run(...)call for text, media, or media plus inline keyboard - Explicit
recipient_type="user"orrecipient_type="chat" - Internal pacing guard that keeps delivery on the MAX-safe profile even if higher batch values are requested
- Automatic retry for temporary MAX failures:
- HTTP
429 - HTTP
503 - network exceptions
- MAX error code
attachment.not.ready
- HTTP
- Sender-level pause and retry queue: temporary failures pause the whole broadcast, retry the affected messages, and only then continue with later batches
- When MAX answers
429without aRetry-After, the sender falls back to a longer rate-limit cooldown instead of the generic short retry interval - Optional MongoDB logging for every send attempt
- MAX-compatible
HTMLandMarkdownformatting
Installation
pip install max_sender
uv add max_sender
Python 3.10+ is required.
MAX API mapping
- Text and media are sent through
POST /messages - Recipients are addressed with either
user_idorchat_id - Media helpers
Photo(...)andVideo(...)expect ready-to-use MAX media tokens reply_markup.inline_keyboardis converted into a MAXinline_keyboardattachment
Quick Start
Text broadcast
import asyncio
from max_sender import MaxSender
async def main() -> None:
sender = MaxSender(
token="YOUR_MAX_BOT_TOKEN",
batch_size=25,
delay_between_batches=1.1,
use_mongo=False,
parse_mode="HTML",
)
delivered, not_delivered = await sender.run(
[4600731, 4600732],
text="Hello from <b>MAX</b>.",
recipient_type="user",
)
print(f"Delivered: {delivered}, failed: {not_delivered}")
asyncio.run(main())
Text plus inline keyboard
import asyncio
from max_sender import MaxSender
async def main() -> None:
sender = MaxSender(token="YOUR_MAX_BOT_TOKEN", use_mongo=False)
reply_markup = {
"inline_keyboard": [
[
{"text": "Open docs", "url": "https://dev.max.ru/docs-api"},
{"text": "Ping", "callback_data": "ping"},
]
]
}
delivered, not_delivered = await sender.run(
[4600731],
text="Choose an action.",
reply_markup=reply_markup,
recipient_type="user",
)
print(f"Delivered: {delivered}, failed: {not_delivered}")
asyncio.run(main())
Media broadcast with ready MAX tokens
import asyncio
from max_sender import MaxSender, Photo, Video
async def main() -> None:
sender = MaxSender(token="YOUR_MAX_BOT_TOKEN", use_mongo=False)
delivered, not_delivered = await sender.run(
[4600731],
text="Media payload in original order.",
media_items=[
Photo("MAX_IMAGE_TOKEN"),
Video("MAX_VIDEO_TOKEN"),
Photo("MAX_IMAGE_TOKEN_2"),
],
recipient_type="user",
)
print(f"Delivered: {delivered}, failed: {not_delivered}")
asyncio.run(main())
MongoDB logging
When use_mongo=True, each attempt is stored in a collection named by the Moscow-time launch timestamp. Each document includes:
recipient_idrecipient_typeattemptdeliveredhttp_status- raw MAX response body
- exception details, if any
- compact payload summary
Notes
parse_modesupports onlyHTMLandMarkdowndisable_web_page_previewmaps to MAXdisable_link_previewPhoto(...)maps to MAX attachment typeimage- Delivery uses a conservative internal profile of up to 25 concurrent sends with at least 1.1 seconds between batch starts
- Temporary delivery errors are retried via a shared queue, so
429pauses the sender instead of immediately dropping later messages - Rate-limit retries use a stronger fallback cooldown than generic temporary errors because MAX often omits
Retry-Afteron429 - Local file upload is intentionally out of scope for v1; upload files separately through
POST /uploadsand reuse the returned tokens
MAX references
Project details
Release history Release notifications | RSS feed
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 max_sender-0.1.0.tar.gz.
File metadata
- Download URL: max_sender-0.1.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af7360a1e01b500fac6767b5f0b4dc58cd849ca4709682d304122cb47da38962
|
|
| MD5 |
41e306ba5716f00eb9a64b3b20868b2f
|
|
| BLAKE2b-256 |
7e9397db532a6166feb97445d8ad397c94964b9c7c886496b0cfdaf9dd3212dd
|
File details
Details for the file max_sender-0.1.0-py3-none-any.whl.
File metadata
- Download URL: max_sender-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9d9c1638249212e9186784d67b49e51641a3a5dff65669aa2961688bafa0c02
|
|
| MD5 |
89d28833204cec1e7d8e8e170b6b75a0
|
|
| BLAKE2b-256 |
e939a7bcae1a223c038281aa7c5a52e215613ace581c1d034599e902b3ebfaa1
|