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}"
|
|
|
|
|
}
|