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:
2025-12-21 12:09:11 +09:00
parent b8136138dc
commit 48f8c6f0eb
48 changed files with 6593 additions and 113 deletions

View File

@@ -31,6 +31,46 @@ class GroupMemberRepository:
await self.session.flush()
return member
async def add_or_update_member(self, data: dict) -> GroupMember:
"""Добавить или обновить члена группы"""
group_id = data.get('group_id')
user_id = str(data.get('user_id'))
member = await self.get_member_by_user_id(group_id, user_id)
if member:
# Обновить существующего
if 'username' in data:
member.username = data['username']
if 'first_name' in data:
member.first_name = data['first_name']
if 'last_name' in data:
member.last_name = data['last_name']
if 'is_bot' in data:
member.is_bot = data['is_bot']
if 'is_admin' in data:
member.is_admin = data['is_admin']
if 'is_owner' in data:
member.is_owner = data['is_owner']
member.updated_at = datetime.utcnow()
else:
# Создать нового
member = GroupMember(
group_id=group_id,
user_id=user_id,
username=data.get('username'),
first_name=data.get('first_name'),
last_name=data.get('last_name'),
is_bot=data.get('is_bot', False),
is_admin=data.get('is_admin', False),
is_owner=data.get('is_owner', False),
joined_at=datetime.utcnow()
)
self.session.add(member)
await self.session.flush()
return member
async def get_member_by_user_id(self, group_id: int, user_id: str) -> Optional[GroupMember]:
"""Получить участника по user_id"""
result = await self.session.execute(

View File

@@ -24,6 +24,38 @@ class GroupRepository:
await self.session.refresh(group)
return group
async def add_or_update_group(self, data: dict) -> Group:
"""Добавить или обновить группу"""
chat_id = str(data.get('chat_id'))
group = await self.get_group_by_chat_id(chat_id)
if group:
# Обновить существующую
if 'title' in data:
group.title = data['title']
if 'description' in data:
group.description = data.get('description')
if 'members_count' in data:
group.members_count = data['members_count']
if 'slow_mode_delay' in data:
group.slow_mode_delay = data['slow_mode_delay']
group.updated_at = datetime.utcnow()
else:
# Создать новую
group = Group(
chat_id=chat_id,
title=data.get('title', ''),
slow_mode_delay=data.get('slow_mode_delay', 0)
)
if 'description' in data:
group.description = data['description']
if 'members_count' in data:
group.members_count = data['members_count']
self.session.add(group)
await self.session.flush()
return group
async def get_group_by_chat_id(self, chat_id: str) -> Optional[Group]:
"""Получить группу по ID чата"""
result = await self.session.execute(
@@ -38,6 +70,14 @@ class GroupRepository:
)
return result.scalars().all()
async def get_active_groups(self) -> List[Group]:
"""Получить все активные группы (alias)"""
return await self.get_all_active_groups()
async def get_group_by_id(self, group_id: int) -> Optional[Group]:
"""Получить группу по ID"""
return await self.session.get(Group, group_id)
async def update_group_slow_mode(self, group_id: int, delay: int) -> None:
"""Обновить slow mode задержку группы"""
group = await self.session.get(Group, group_id)
@@ -46,6 +86,17 @@ class GroupRepository:
group.updated_at = datetime.utcnow()
await self.session.commit()
async def update_group(self, group_id: int, title: str = None, slow_mode_delay: int = None) -> None:
"""Обновить информацию о группе"""
group = await self.session.get(Group, group_id)
if group:
if title is not None:
group.title = title
if slow_mode_delay is not None:
group.slow_mode_delay = slow_mode_delay
group.updated_at = datetime.utcnow()
await self.session.commit()
async def update_last_message_time(self, group_id: int) -> None:
"""Обновить время последнего сообщения"""
group = await self.session.get(Group, group_id)