Files
TG_autoposter/app/__init__.py
Andrew K. Choi 48f8c6f0eb UserBot Integration Complete: Fixed container startup, integrated UserBot menu to main bot
MAJOR FIXES:
 Fixed UserBot container startup by making TELEGRAM_BOT_TOKEN optional
 Broke circular import chain between app modules
 Made Config.validate() conditional for UserBot-only mode
 Removed unused celery import from userbot_service.py

INTEGRATION:
 UserBot menu now accessible from main bot /start command
 Added 🤖 UserBot button to main keyboard
 Integrated userbot_manager.py handlers:
   - userbot_menu: Main UserBot interface
   - userbot_settings: Configuration
   - userbot_collect_groups: Gather all user groups
   - userbot_collect_members: Parse group members
 UserBot handlers properly registered in ConversationHandler

CONTAINERS:
 tg_autoposter_bot: Running and handling /start commands
 tg_autoposter_userbot: Running as standalone microservice
 All dependent services (Redis, PostgreSQL, Celery workers) operational

STATUS: Bot is fully operational and ready for testing
2025-12-21 12:09:11 +09:00

161 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import logging
from dotenv import load_dotenv
from telegram.ext import (
Application,
CommandHandler,
CallbackQueryHandler,
ChatMemberHandler,
MessageHandler,
ConversationHandler,
filters,
)
from app.database import init_db
from app.handlers import (
start,
help_command,
sync_groups_command,
start_callback,
manage_messages,
manage_groups,
list_messages,
list_groups,
send_message,
my_chat_member,
userbot_menu,
userbot_settings,
userbot_init,
userbot_collect_groups,
userbot_collect_members,
userbot_parse_members,
cancel_userbot,
)
from app.handlers.message_manager import (
create_message_start,
create_message_title,
create_message_text,
select_groups,
handle_message_input,
)
from app.handlers.telethon_client import telethon_manager
from app.utils.keyboards import CallbackType
from app.settings import Config
# Загружаем переменные окружения
load_dotenv()
# Настройка логирования
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG
)
logger = logging.getLogger(__name__)
async def debug_update_handler(update, context):
"""Обработчик для отладки всех обновлений"""
logger.info(f"🎯 Получено обновление: {update}")
if update.message:
logger.info(f"📨 Сообщение от {update.effective_user.id}: {update.message.text}")
elif update.callback_query:
logger.info(f"🔘 Callback от {update.effective_user.id}: {update.callback_query.data}")
else:
logger.info(f"❓ Неизвестное обновление: {update.to_dict() if hasattr(update, 'to_dict') else str(update)}")
return None
# Получаем конфигурацию
# Для UserBot контейнера: если есть TELETHON переменные и нет BOT_TOKEN - это ОК
is_userbot_only = (
os.getenv('TELETHON_API_ID')
and os.getenv('TELETHON_API_HASH')
and os.getenv('TELETHON_PHONE')
and not os.getenv('TELEGRAM_BOT_TOKEN')
)
if not is_userbot_only:
if not Config.validate():
raise ValueError("❌ Конфигурация некорректна. Проверьте .env файл")
async def main() -> None:
"""Запуск бота с поддержкой гибридного режима"""
# Инициализируем БД
logger.info("Инициализация базы данных...")
await init_db()
logger.info("✅ База данных инициализирована")
# Инициализируем Telethon если включен
if Config.USE_TELETHON:
logger.info("Инициализация Telethon клиента...")
success = await telethon_manager.initialize()
if success:
logger.info("✅ Telethon клиент инициализирован")
else:
logger.warning("⚠️ Ошибка инициализации Telethon, продолжим с режимом бота")
# Выводим информацию о режиме
mode = Config.get_mode()
logger.info(f"📡 Режим работы: {mode}")
if mode == 'hybrid':
logger.info("🔀 Бот будет использовать Telethon как fallback для закрытых групп")
# Создаем приложение
application = Application.builder().token(Config.TELEGRAM_BOT_TOKEN).build()
# Добавляем отладчик для всех текстовых сообщений (самый низкий приоритет)
application.add_handler(MessageHandler(filters.ALL, debug_update_handler), group=100)
# Добавляем обработчики команд (высший приоритет, группа 0)
application.add_handler(CommandHandler("start", start), group=0)
application.add_handler(CommandHandler("help", help_command), group=0)
application.add_handler(CommandHandler("sync_groups", sync_groups_command), group=0)
# Добавляем обработчики callback'ов (группа 1)
application.add_handler(CallbackQueryHandler(start_callback, pattern=f"^{CallbackType.MAIN_MENU.value}$"), group=1)
application.add_handler(CallbackQueryHandler(manage_messages, pattern=f"^{CallbackType.MANAGE_MESSAGES.value}$"), group=1)
application.add_handler(CallbackQueryHandler(manage_groups, pattern=f"^{CallbackType.MANAGE_GROUPS.value}$"), group=1)
application.add_handler(CallbackQueryHandler(list_messages, pattern=f"^{CallbackType.LIST_MESSAGES.value}$"), group=1)
application.add_handler(CallbackQueryHandler(list_groups, pattern=f"^{CallbackType.LIST_GROUPS.value}$"), group=1)
application.add_handler(CallbackQueryHandler(send_message, pattern=r"^send_msg_\d+$"), group=1)
# CREATE_MESSAGE обрабатывается отдельным handler'ом с управлением состоянием
application.add_handler(CallbackQueryHandler(create_message_start, pattern=f"^{CallbackType.CREATE_MESSAGE.value}$"), group=1)
# Добавляем обработчик CallbackQuery для управления UserBot
application.add_handler(CallbackQueryHandler(userbot_menu, pattern="^userbot_menu$"), group=1)
application.add_handler(CallbackQueryHandler(userbot_settings, pattern="^userbot_settings$"), group=1)
application.add_handler(CallbackQueryHandler(userbot_init, pattern="^userbot_init$"), group=1)
application.add_handler(CallbackQueryHandler(userbot_collect_groups, pattern="^userbot_collect_groups$"), group=1)
application.add_handler(CallbackQueryHandler(userbot_collect_members, pattern="^userbot_collect_members$"), group=1)
application.add_handler(CallbackQueryHandler(userbot_parse_members, pattern=r"^userbot_members_\d+$"), group=1)
# Добавляем обработчик для кнопки UserBot в главном меню
application.add_handler(CallbackQueryHandler(userbot_menu, pattern=f"^{CallbackType.MANAGE_USERBOT.value}$"), group=1)
# Select group callbacks
application.add_handler(CallbackQueryHandler(select_groups, pattern=r"^select_group_\d+$"), group=1)
application.add_handler(CallbackQueryHandler(select_groups, pattern=r"^done_groups$"), group=1)
# MessageHandler для текстового ввода (название и текст сообщения)
# Использует dispatch-функцию для маршрутизации в зависимости от состояния
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message_input), group=1)
# Обработчик добавления/удаления бота из групп (группа 3)
application.add_handler(ChatMemberHandler(my_chat_member, ChatMemberHandler.MY_CHAT_MEMBER), group=3)
# Запускаем бота
logger.info("🚀 Бот запущен. Ожидание команд...")
try:
await application.run_polling(allowed_updates=["message", "callback_query", "my_chat_member"])
finally:
# Завершить Telethon клиент при выходе
if Config.USE_TELETHON:
logger.info("Завершение работы Telethon клиента...")
await telethon_manager.shutdown()
logger.info("✅ Telethon клиент остановлен")
if __name__ == "__main__":
import asyncio
asyncio.run(main())