Skip to main content

Broadcast/newsletter library for aiogram 3.x

Project description

aiogram-broadcast

Broadcast/newsletter library for Telegram bots built with aiogram 3.x.

Features

  • Automatic subscriber registration via middleware
  • Rate-limited broadcasting to avoid Telegram API limits
  • Scheduled broadcasts with APScheduler
  • Redis subscriber storage
  • Progress callbacks for monitoring
  • Automatic tracking of users who blocked the bot

Installation

pip install aiogram-broadcast

With scheduled broadcast support:

pip install aiogram-broadcast[scheduler]

Quick Start

import asyncio
from aiogram import Bot, Dispatcher, Router, F
from aiogram.filters import Command
from aiogram.types import Message
from redis.asyncio import Redis

from aiogram_broadcast import (
    BroadcastMiddleware,
    BroadcastService,
    RedisBroadcastStorage,
)

BOT_TOKEN = "YOUR_BOT_TOKEN"
ADMIN_ID = 123456789  # Your Telegram ID

router = Router()


@router.message(Command("broadcast"), F.from_user.id == ADMIN_ID)
async def broadcast_handler(
    message: Message,
    broadcast_service: BroadcastService,
) -> None:
    """Broadcast a message to all subscribers."""
    if not message.reply_to_message:
        await message.reply("Reply to the message you want to broadcast")
        return

    status_msg = await message.reply("Starting broadcast...")

    result = await broadcast_service.broadcast_copy(
        from_chat_id=message.chat.id,
        message_id=message.reply_to_message.message_id,
    )

    await status_msg.edit_text(
        f"Broadcast completed\n\n"
        f"Successful: {result.successful}/{result.total}\n"
        f"Failed: {result.failed}\n"
        f"Blocked: {len(result.blocked_users)}"
    )


@router.message(Command("stats"), F.from_user.id == ADMIN_ID)
async def stats_handler(
    message: Message,
    broadcast_service: BroadcastService,
) -> None:
    """Subscriber statistics."""
    total = await broadcast_service.get_subscriber_count(only_active=False)
    active = await broadcast_service.get_subscriber_count(only_active=True)

    await message.reply(
        f"Total subscribers: {total}\n"
        f"Active: {active}\n"
        f"Blocked: {total - active}"
    )


async def main() -> None:
    redis = Redis(host="localhost", port=6379, db=0)
    storage = RedisBroadcastStorage(redis)

    bot = Bot(token=BOT_TOKEN)
    dp = Dispatcher()

    broadcast_service = BroadcastService(bot, storage)

    # Register middleware for automatic subscriber tracking
    dp.update.outer_middleware.register(BroadcastMiddleware(storage))

    # Make broadcast_service available in handlers
    dp["broadcast_service"] = broadcast_service

    dp.include_router(router)
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

Usage

Middleware

BroadcastMiddleware automatically:

  • Registers new users as subscribers
  • Updates subscriber info on each interaction
  • Tracks subscribe/unsubscribe events
from aiogram_broadcast import BroadcastMiddleware, RedisBroadcastStorage

storage = RedisBroadcastStorage(redis)
dp.update.outer_middleware.register(BroadcastMiddleware(storage))

Injected into handler data:

  • subscriberSubscriber instance (or None for non-private chats)
  • broadcast_storage — storage instance

BroadcastService

Main service for sending broadcasts:

from aiogram_broadcast import BroadcastService

service = BroadcastService(
    bot=bot,
    storage=storage,
    rate_limit=0.05,  # 20 messages per second
)

# Text broadcast
result = await service.broadcast_text(
    text="Hello everyone!",
    parse_mode="HTML",
)

# Photo broadcast
result = await service.broadcast_photo(
    photo="AgACAgIAAxk...",  # file_id
    caption="Photo caption",
)

# Copy message broadcast
result = await service.broadcast_copy(
    from_chat_id=admin_chat_id,
    message_id=message_id,
)

Scheduled Broadcasts

from datetime import datetime, timedelta
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from aiogram_broadcast import BroadcastScheduler

scheduler = AsyncIOScheduler()
broadcast_scheduler = BroadcastScheduler(
    service=broadcast_service,
    scheduler=scheduler,
)

# Schedule a broadcast in 1 hour
task_id = await broadcast_scheduler.schedule_text(
    text="Reminder!",
    run_date=datetime.now() + timedelta(hours=1),
)

# Cancel a scheduled broadcast
await broadcast_scheduler.cancel(task_id)

# List pending broadcasts
pending = broadcast_scheduler.get_pending_tasks()

Progress Callback

async def progress_callback(current: int, total: int, result: BroadcastResult) -> None:
    print(f"Progress: {current}/{total} ({result.successful} successful)")

result = await service.broadcast_text(
    text="Message",
    progress_callback=progress_callback,
)

BroadcastResult

result = await service.broadcast_text("Hello!")

print(f"Total: {result.total}")
print(f"Successful: {result.successful}")
print(f"Failed: {result.failed}")
print(f"Blocked: {result.blocked_users}")
print(f"Success rate: {result.success_rate:.1f}%")

API Reference

Models

  • Subscriber — subscriber model
  • SubscriberState — subscriber state (MEMBER/KICKED)
  • BroadcastResult — broadcast result
  • BroadcastTask — scheduled broadcast task

Storage

  • BaseBroadcastStorage — abstract storage class
  • RedisBroadcastStorage — Redis implementation

Middleware

  • BroadcastMiddleware — main middleware
  • BroadcastChatMemberMiddleware — for handling chat member updates only

Service

  • BroadcastService — broadcast service
  • BroadcastScheduler — broadcast scheduler

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

aiogram_broadcast-0.1.0.tar.gz (28.3 kB view details)

Uploaded Source

Built Distribution

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

aiogram_broadcast-0.1.0-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file aiogram_broadcast-0.1.0.tar.gz.

File metadata

  • Download URL: aiogram_broadcast-0.1.0.tar.gz
  • Upload date:
  • Size: 28.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for aiogram_broadcast-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ce1308d243e9452aa35fb06eb14b9a895ca2ee169aad4d0d4e53f1b16d5ebfb9
MD5 a87c1cddba72fd3cb6d8955e7675d99a
BLAKE2b-256 34fe2818ffae4ed5b6ae44d8c7918d149b2d41b005b0f37a09e06fa00d08c2a7

See more details on using hashes here.

File details

Details for the file aiogram_broadcast-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for aiogram_broadcast-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02e499085e7635c32b4c8beac4e77e962ec21321bf5d2de45ba6bd437aeb1d91
MD5 7b03d6a0afd2c8f1de1db4c99f2f39ad
BLAKE2b-256 e5a934af14df3e4afe60442efcc58d0402b330928eb5e26c548d2807f817a7c7

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