import logging from aiogram import Bot from aiogram.enums import ParseMode from aiogram.client.default import DefaultBotProperties from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from aiogram.exceptions import TelegramAPIError, TelegramBadRequest, TelegramNetworkError from config import Config from typing import Dict, Any, List, Optional logger = logging.getLogger(__name__) class NotificationBot: def __init__(self, config: Config): self.config = config try: self.bot: Bot = Bot( token=config.bot_token, default=DefaultBotProperties( parse_mode=ParseMode.HTML, disable_notification=True, link_preview_is_disabled=True, ), ) logger.info( "Бот для уведомлений инициализирован (admin_id=%s)", config.admin_id ) except (TelegramAPIError, ValueError, TypeError) as e: logger.error(f"Не удалось инициализировать Бот для уведомлений: {e}") raise async def _notify(self, message: str, reply_to: int = None, link: str = None) -> Optional[int]: try: logger.debug("Отправка уведомления (reply_to=%s, link=%s)", reply_to, link) keyboard = None if link: keyboard = InlineKeyboardMarkup( inline_keyboard=[[InlineKeyboardButton(text=f"Перейти", url=link)]] ) if not reply_to: sent_message = await self.bot.send_message( chat_id=self.config.admin_id, text=message, reply_markup=keyboard ) else: sent_message = await self.bot.send_message( chat_id=self.config.admin_id, text=message, reply_to_message_id=reply_to, reply_markup=keyboard, ) logger.debug( "Уведомление отправлено (message_id=%s)", sent_message.message_id ) return sent_message.message_id except TelegramBadRequest as e: logger.error("Bad request sending notification: %s", e) return None except TelegramNetworkError as e: logger.error("Network error sending notification: %s", e) return None except TelegramAPIError as e: logger.error("Telegram API error sending notification: %s", e) return None except Exception as e: logger.error("Unexpected error sending notification: %s", e) return None async def new_post(self, post: Dict[str, Any], links: List[str]) -> Optional[int]: try: thread = post.get("thread") thread_title = thread.get("thread_title") permalink = post.get("links").get("permalink") thread_link = f'{thread_title}' poster_username = post.get("poster_username") poster_user_id = post.get("poster_user_id") poster_link = f"https://lolz.team/members/{poster_user_id}" user_link = f'{poster_username}' logger.info( "Новый пост: пользователь=%s (id=%s), тема=%r, ссылок=%d", poster_username, poster_user_id, thread_title, len(links), ) links_msg = f"
" for idx, link in enumerate(links): links_msg += f'Ссылка №{idx + 1}\n' links_msg += "
" message = ( f"🚩 Новый ответ в теме {thread_link}:\n\n" f"▪️ Пользователь: {user_link}\n" f"▪️ Ссылки: {links_msg}" ) post_message_id = await self._notify(message=message, link=permalink) logger.debug( "Уведомление о новом посте отправлено (message_id=%s)", post_message_id ) return post_message_id except (KeyError, AttributeError, TypeError) as e: logger.error(f"Неверная структура поста в new_post: {e}") return None except Exception as e: logger.error(f"Неожиданная ошибка в new_post: {e}") return None async def success(self, link: str, post_message_id: int) -> Optional[int]: try: logger.info( "Звезда успешно отправлена: link=%s, stars=%s", link, self.config.stars_count, ) message = ( f"🌟 Звезда отправлена:\n\n" f"▪️ Количество: {self.config.stars_count}\n" f'▪️ Ссылка на сообщение: тык' ) success_message_id = await self._notify( message=message, reply_to=post_message_id, link=link ) logger.debug( "Уведомление об успехе отправлено (message_id=%s)", success_message_id ) return success_message_id except Exception as e: logger.error(f"Неожиданная ошибка в success: {e}") return None async def failure(self, post: Dict[str, Any], reason: str, post_message_id: int) -> Optional[int]: try: permalink = post.get("links", {}).get("permalink") logger.warning( "Не удалось отправить звезду: reason=%r, link=%s", reason, permalink ) message = ( f"❌ Не удалось отправить звезду:\n\n" f"▪️ Причина: {reason}" ) failure_message_id = await self._notify( message=message, reply_to=post_message_id, link=permalink ) logger.debug( "Уведомление об ошибке отправлено (message_id=%s)", failure_message_id ) return failure_message_id except (KeyError, AttributeError, TypeError) as e: logger.error(f"Неверная структура поста в failure: {e}") return None except Exception as e: logger.error(f"Неожиданная ошибка в failure: {e}") return None