✅ 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
This commit is contained in:
139
app/userbot/tasks.py
Normal file
139
app/userbot/tasks.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
Celery задачи для UserBot микросервиса
|
||||
Запускает парсинг групп в фоновом режиме
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from celery import shared_task
|
||||
from app.userbot.parser import userbot_parser
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.database.repository import GroupRepository
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run_async(coro):
|
||||
"""Вспомогательная функция для запуска async функций в Celery"""
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
return loop.run_until_complete(coro)
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
|
||||
@shared_task(name='app.userbot.tasks.initialize_userbot')
|
||||
def initialize_userbot_task():
|
||||
"""Инициализировать UserBot при запуске"""
|
||||
logger.info("🚀 Инициализация UserBot...")
|
||||
result = run_async(userbot_parser.initialize())
|
||||
|
||||
if result:
|
||||
logger.info("✅ UserBot успешно инициализирован")
|
||||
return {'status': 'success', 'message': 'UserBot initialized'}
|
||||
else:
|
||||
logger.error("❌ Ошибка инициализации UserBot")
|
||||
return {'status': 'error', 'message': 'UserBot initialization failed'}
|
||||
|
||||
|
||||
@shared_task(name='app.userbot.tasks.parse_group')
|
||||
def parse_group_task(chat_id: int):
|
||||
"""
|
||||
Парсить группу и сохранить в БД
|
||||
|
||||
Args:
|
||||
chat_id: ID группы для парсинга
|
||||
"""
|
||||
logger.info(f"📊 Парсинг группы {chat_id}...")
|
||||
|
||||
result = run_async(userbot_parser.sync_group_to_db(chat_id))
|
||||
|
||||
if result:
|
||||
logger.info(f"✅ Группа {chat_id} успешно спарсена")
|
||||
return {'status': 'success', 'chat_id': chat_id, 'message': 'Group parsed successfully'}
|
||||
else:
|
||||
logger.error(f"❌ Ошибка парсинга группы {chat_id}")
|
||||
return {'status': 'error', 'chat_id': chat_id, 'message': 'Group parsing failed'}
|
||||
|
||||
|
||||
@shared_task(name='app.userbot.tasks.sync_all_groups')
|
||||
def sync_all_groups_task():
|
||||
"""Синхронизировать все активные группы из БД"""
|
||||
logger.info("🔄 Начало синхронизации всех групп...")
|
||||
|
||||
async def _sync_all():
|
||||
try:
|
||||
async with AsyncSessionLocal() as session:
|
||||
repo = GroupRepository(session)
|
||||
groups = await repo.get_all_active_groups()
|
||||
|
||||
if not groups:
|
||||
logger.info("ℹ️ Нет активных групп для синхронизации")
|
||||
return {'status': 'success', 'groups_synced': 0}
|
||||
|
||||
synced = 0
|
||||
failed = 0
|
||||
|
||||
for group in groups:
|
||||
success = await userbot_parser.sync_group_to_db(group.chat_id)
|
||||
if success:
|
||||
synced += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
logger.info(f"✅ Синхронизировано {synced} групп (ошибок: {failed})")
|
||||
return {'status': 'success', 'groups_synced': synced, 'groups_failed': failed}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Ошибка при синхронизации групп: {e}")
|
||||
return {'status': 'error', 'message': str(e)}
|
||||
|
||||
return run_async(_sync_all())
|
||||
|
||||
|
||||
@shared_task(name='app.userbot.tasks.parse_group_members')
|
||||
def parse_group_members_task(chat_id: int, limit: int = 10000):
|
||||
"""
|
||||
Парсить участников группы
|
||||
|
||||
Args:
|
||||
chat_id: ID группы
|
||||
limit: максимум участников
|
||||
"""
|
||||
logger.info(f"👥 Парсинг участников группы {chat_id} (лимит: {limit})...")
|
||||
|
||||
async def _parse_members():
|
||||
try:
|
||||
members = await userbot_parser.parse_group_members(chat_id, limit)
|
||||
|
||||
if not members:
|
||||
return {'status': 'error', 'chat_id': chat_id, 'members_count': 0}
|
||||
|
||||
# Сохранить в БД
|
||||
async with AsyncSessionLocal() as session:
|
||||
from app.database.repository import GroupMemberRepository
|
||||
|
||||
member_repo = GroupMemberRepository(session)
|
||||
|
||||
for member in members:
|
||||
member_data = {
|
||||
'group_id': chat_id,
|
||||
'user_id': int(member['user_id']),
|
||||
'username': member['username'],
|
||||
'first_name': member['first_name'],
|
||||
'last_name': member['last_name'],
|
||||
'is_bot': member['is_bot'],
|
||||
}
|
||||
await member_repo.add_or_update_member(member_data)
|
||||
|
||||
await session.commit()
|
||||
|
||||
logger.info(f"✅ {len(members)} участников группы {chat_id} сохранено в БД")
|
||||
return {'status': 'success', 'chat_id': chat_id, 'members_count': len(members)}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Ошибка при парсинге участников {chat_id}: {e}")
|
||||
return {'status': 'error', 'chat_id': chat_id, 'message': str(e)}
|
||||
|
||||
return run_async(_parse_members())
|
||||
Reference in New Issue
Block a user