shopbot/bot/services/broadcast.py

70 lines
2.4 KiB
Python
Raw Permalink Normal View History

2024-12-24 18:08:03 +00:00
import asyncio
import logging
2024-12-25 01:30:33 +00:00
from aiogram.exceptions import (
TelegramAPIError,
TelegramForbiddenError,
TelegramRetryAfter,
)
2024-12-24 18:08:03 +00:00
from aiogram_dialog import DialogManager
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
2024-12-25 01:30:33 +00:00
from shopbot.bot.database.db import async_session
from shopbot.bot.database.models import UserModel
2024-12-24 18:08:03 +00:00
2024-12-25 01:30:33 +00:00
async def _send_message_with_retry(
bot, user_id: int, message_text: str, max_retries=3, delay=1
) -> bool:
2024-12-24 18:08:03 +00:00
for attempt in range(max_retries):
try:
await bot.send_message(user_id, message_text)
return True
except TelegramRetryAfter as e:
2024-12-25 01:30:33 +00:00
logging.warning(
f"Retry after {e.retry_after} for user {user_id}, attempt {attempt + 1}"
)
2024-12-24 18:08:03 +00:00
await asyncio.sleep(e.retry_after)
except TelegramForbiddenError:
logging.warning(f"User {user_id} blocked bot")
return False
except TelegramAPIError as e:
logging.error(f"Error sending message to user {user_id}: {e}")
return False
logging.error(f"Max retries exceeded for user {user_id}")
return False
async def broadcast_message(dialog_manager: DialogManager, **kwargs):
message_text = dialog_manager.find("message_input").get_value()
bot = dialog_manager.event.bot
try:
async with async_session() as session:
async with session.begin():
result = await session.execute(select(UserModel.tg_id))
user_ids = [row[0] for row in result]
total_users = len(user_ids)
tasks = [
_send_message_with_retry(bot, user_id, message_text)
for user_id in user_ids
]
results = await asyncio.gather(*tasks)
total_sent = sum(results)
total_failed = total_users - total_sent
except SQLAlchemyError as e:
logging.error(f"Database error: {e}")
2024-12-25 01:30:33 +00:00
return {"progress": f"❌ Ошибка при работе с базой данных: {e}"}
2024-12-24 18:08:03 +00:00
except Exception as e:
logging.error(f"An unexpected error occurred: {e}")
2024-12-25 01:30:33 +00:00
return {"progress": f"❌ Непредвиденная ошибка: {e}"}
2024-12-24 18:08:03 +00:00
return {
"progress": f"✅ Рассылка завершена!\n"
2024-12-25 01:30:33 +00:00
f"📨 Всего отправлено: {total_sent}/{total_users}\n"
f"❌ Ошибок: {total_failed}"
}