import logging import re from aiogram import Router, F from aiogram.types import Message from aiogram.filters import Command from services.personal_inbox_service import PersonalInboxService import config logger = logging.getLogger(__name__) router = Router() # Регулярка для поиска URL URL_REGEX = re.compile(r'(https?://[^\s]+)') @router.message(F.chat.type == 'private', Command('digest')) @router.message(F.chat.type == 'private', Command('digest_send')) async def cmd_send_digest(message: Message): """Ручной запуск отправки дайджеста""" if message.from_user.id != config.ADMIN_USER_ID: return await message.answer("🔄 Собираю еженедельный дайджест...", parse_mode='HTML') success = await PersonalInboxService.send_weekly_digest(message.bot) if not success: await message.answer("ℹ️ Нет активных (неотправленных) записей в вашем инбоксе.") @router.message(F.chat.type == 'private', Command('digest_list')) async def cmd_list_digest(message: Message): """Показать список текущих записей в инбоксе""" if message.from_user.id != config.ADMIN_USER_ID: return items = await PersonalInboxService.get_pending_items(config.ADMIN_USER_ID) if not items: await message.answer("📥 Ваш инбокс дайджеста пуст.") return lines = [f"📥 Текущие записи в инбоксе ({len(items)}):\n"] for idx, item in enumerate(items, 1): date_str = item.created_at.strftime('%d.%m %H:%M') line = f"{idx}. [{date_str}] " if item.url: line += f'Ссылка' else: line += "Текст" if item.message_text: # Обрезаем длинный текст short_text = item.message_text[:60] + "..." if len(item.message_text) > 60 else item.message_text line += f": {short_text}" lines.append(line) lines.append("\n✍️ Для ручной отправки дайджеста введите /digest. Для очистки - /digest_clear.") await message.answer("\n".join(lines), parse_mode='HTML', disable_web_page_preview=True) @router.message(F.chat.type == 'private', Command('digest_clear')) async def cmd_clear_digest(message: Message): """Очистить инбокс""" if message.from_user.id != config.ADMIN_USER_ID: return success = await PersonalInboxService.clear_pending_items(config.ADMIN_USER_ID) if success: await message.answer("🧹 Ваш инбокс успешно очищен (все записи помечены как отправленные).") else: await message.answer("❌ Произошла ошибка при очистке инбокса.") @router.message(F.chat.type == 'private') async def handle_private_inbox(message: Message): """Обработчик всех входящих личных сообщений от админа для сохранения в инбокс""" if message.from_user.id != config.ADMIN_USER_ID: # Для других пользователей пропускаем или выдаем стандартный ответ return # Игнорируем команды, которые могли проскочить if message.text and message.text.startswith('/'): return # Собираем текст text = message.text or message.caption or "" # Пытаемся вытащить URL из сущностей aiogram urls = [] entities = message.entities or message.caption_entities or [] for entity in entities: if entity.type == 'url': urls.append(text[entity.offset:entity.offset+entity.length]) elif entity.type == 'text_link': urls.append(entity.url) # Если aiogram не нашел сущностей, ищем регуляркой if not urls: found = URL_REGEX.findall(text) if found: urls.extend(found) # Определяем тип медиа media_type = 'text' if message.photo: media_type = 'photo' elif message.video: media_type = 'video' elif message.document: media_type = 'document' primary_url = urls[0] if urls else None # Добавляем в инбокс success = await PersonalInboxService.add_to_inbox( user_id=config.ADMIN_USER_ID, text=text, url=primary_url, media_type=media_type ) if success: items = await PersonalInboxService.get_pending_items(config.ADMIN_USER_ID) count = len(items) reply_msg = "📥 Добавлено в инбокс дайджеста!" if primary_url: reply_msg += f"\n🔗 Распознана ссылка: {primary_url}" reply_msg += f"\n\n📂 Всего записей в очереди: {count}" await message.answer(reply_msg, parse_mode='HTML', disable_web_page_preview=True) else: await message.answer("❌ Произошла ошибка при сохранении сообщения в инбокс.")