Broadcast example

broadcast_example.py
 1import asyncio
 2import logging
 3
 4from aiogram import Bot, Dispatcher, types
 5from aiogram.utils import exceptions, executor
 6
 7API_TOKEN = 'BOT TOKEN HERE'
 8
 9logging.basicConfig(level=logging.INFO)
10log = logging.getLogger('broadcast')
11
12bot = Bot(token=API_TOKEN, parse_mode=types.ParseMode.HTML)
13dp = Dispatcher(bot)
14
15
16def get_users():
17    """
18    Return users list
19
20    In this example returns some random ID's
21    """
22    yield from (61043901, 78238238, 78378343, 98765431, 12345678)
23
24
25async def send_message(user_id: int, text: str, disable_notification: bool = False) -> bool:
26    """
27    Safe messages sender
28
29    :param user_id:
30    :param text:
31    :param disable_notification:
32    :return:
33    """
34    try:
35        await bot.send_message(user_id, text, disable_notification=disable_notification)
36    except exceptions.BotBlocked:
37        log.error(f"Target [ID:{user_id}]: blocked by user")
38    except exceptions.ChatNotFound:
39        log.error(f"Target [ID:{user_id}]: invalid user ID")
40    except exceptions.RetryAfter as e:
41        log.error(f"Target [ID:{user_id}]: Flood limit is exceeded. Sleep {e.timeout} seconds.")
42        await asyncio.sleep(e.timeout)
43        return await send_message(user_id, text)  # Recursive call
44    except exceptions.UserDeactivated:
45        log.error(f"Target [ID:{user_id}]: user is deactivated")
46    except exceptions.TelegramAPIError:
47        log.exception(f"Target [ID:{user_id}]: failed")
48    else:
49        log.info(f"Target [ID:{user_id}]: success")
50        return True
51    return False
52
53
54async def broadcaster() -> int:
55    """
56    Simple broadcaster
57
58    :return: Count of messages
59    """
60    count = 0
61    try:
62        for user_id in get_users():
63            if await send_message(user_id, '<b>Hello!</b>'):
64                count += 1
65            await asyncio.sleep(.05)  # 20 messages per second (Limit: 30 messages per second)
66    finally:
67        log.info(f"{count} messages successful sent.")
68
69    return count
70
71
72if __name__ == '__main__':
73    # Execute broadcaster
74    executor.start(dp, broadcaster())