Skip to main content

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" or recipient_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
  • 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 429 without a Retry-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 HTML and Markdown formatting

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_id or chat_id
  • Media helpers Photo(...) and Video(...) expect ready-to-use MAX media tokens
  • reply_markup.inline_keyboard is converted into a MAX inline_keyboard attachment

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_id
  • recipient_type
  • attempt
  • delivered
  • http_status
  • raw MAX response body
  • exception details, if any
  • compact payload summary

Notes

  • parse_mode supports only HTML and Markdown
  • disable_web_page_preview maps to MAX disable_link_preview
  • Photo(...) maps to MAX attachment type image
  • 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 429 pauses 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-After on 429
  • Local file upload is intentionally out of scope for v1; upload files separately through POST /uploads and reuse the returned tokens

MAX references

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

max_sender-0.1.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

max_sender-0.1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

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

Hashes for max_sender-0.1.0.tar.gz
Algorithm Hash digest
SHA256 af7360a1e01b500fac6767b5f0b4dc58cd849ca4709682d304122cb47da38962
MD5 41e306ba5716f00eb9a64b3b20868b2f
BLAKE2b-256 7e9397db532a6166feb97445d8ad397c94964b9c7c886496b0cfdaf9dd3212dd

See more details on using hashes here.

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

Hashes for max_sender-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c9d9c1638249212e9186784d67b49e51641a3a5dff65669aa2961688bafa0c02
MD5 89d28833204cec1e7d8e8e170b6b75a0
BLAKE2b-256 e939a7bcae1a223c038281aa7c5a52e215613ace581c1d034599e902b3ebfaa1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page