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.1.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.1-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file max_sender-0.1.1.tar.gz.

File metadata

  • Download URL: max_sender-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 c04246344a7a7ec30b7025f72ad0c30f08d0b17c7cf187760ae942091b39b253
MD5 ef5a06f0a4d76a7b8c69caf95b03415b
BLAKE2b-256 3cc4b948f657a52eb3d16eed6f26e95bcf123d943023776a24794c2acc324812

See more details on using hashes here.

File details

Details for the file max_sender-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: max_sender-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d20c6fc78213b4fafc1608f520e7519c0c83b2d593dbd38c706189455608bc4e
MD5 ad3e2dcecb29bdf1892af40c1678346b
BLAKE2b-256 475531bcfded178537722a127534296f01ea07364f6a6e46c125eeb8eec8baf5

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