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

@@ -0,0 +1,359 @@
# Telethon UserBot Microservice
Отдельный микросервис для парсинга Telegram групп и каналов от имени пользователя (UserBot).
## Архитектура
```
Основной бот (Python-Telegram-Bot)
├─→ Celery задачи (Async парсинг)
│ ↓
│ Telethon UserBot Microservice
│ ↓
│ PostgreSQL БД
└─→ HTTP API для управления
```
## Возможности
### 1. Парсинг групп и каналов
- Получение информации о группе (название, описание, кол-во членов)
- Парсинг списка участников с информацией:
- User ID
- Username
- Имя и фамилия
- Статус (бот/пользователь)
- Роль (администратор/участник)
### 2. Сохранение в БД
- Автоматическое сохранение информации о группах
- Кэширование списков участников
- Отслеживание изменений
### 3. Celery интеграция
- Асинхронные задачи для парсинга
- Очередь задач для управления нагрузкой
- Мониторинг через Flower
## Установка и запуск
### 1. Конфигурация
Добавьте в `.env`:
```bash
# Telethon Configuration
USE_TELETHON=true
TELETHON_API_ID=your_api_id
TELETHON_API_HASH=your_api_hash
TELETHON_PHONE=+1234567890
TELETHON_FLOOD_WAIT_MAX=60
```
Получить API ID и HASH:
1. Перейти на https://my.telegram.org/auth
2. Войти с номером телефона
3. Выбрать "API development tools"
4. Скопировать `api_id` и `api_hash`
### 2. Первый запуск (Авторизация)
```bash
# Запустить userbot в интерактивном режиме
python userbot_service.py
# Следовать инструкциям для авторизации через SMS код
```
Сессия будет сохранена в `sessions/userbot_session.session`
### 3. Запуск в Docker
```bash
# Собрать контейнер
docker-compose build userbot
# Запустить вместе с другими сервисами
docker-compose up -d userbot
# Просмотр логов
docker-compose logs -f userbot
```
### 4. Запуск как Celery воркер
```bash
# В отдельном терминале
python userbot_service.py --celery
# Или через Docker
docker-compose run --rm userbot python userbot_service.py --celery
```
## API / Использование
### Programmatically
```python
from app.userbot.parser import userbot_parser
# Инициализировать
await userbot_parser.initialize()
# Парсить группу
group_info = await userbot_parser.parse_group_info(chat_id=-1001234567890)
members = await userbot_parser.parse_group_members(chat_id=-1001234567890)
# Синхронизировать в БД
await userbot_parser.sync_group_to_db(chat_id=-1001234567890)
```
### Celery задачи
```python
from app.userbot.tasks import parse_group_task, sync_all_groups_task
# Парсить одну группу
result = parse_group_task.delay(chat_id=-1001234567890)
# Синхронизировать все группы
result = sync_all_groups_task.delay()
# Парсить только участников
result = parse_group_members_task.delay(chat_id=-1001234567890, limit=5000)
```
### Через Flower UI
1. Откройте http://localhost:5555
2. Перейдите на вкладку "Tasks"
3. Найдите и запустите нужную задачу:
- `app.userbot.tasks.parse_group` - парсить группу
- `app.userbot.tasks.sync_all_groups` - синхронизировать все
- `app.userbot.tasks.parse_group_members` - парсить участников
## Структура данных
### Group (в БД)
```python
{
'id': int, # ID в БД
'chat_id': str, # Telegram chat ID
'title': str, # Название группы
'description': str, # Описание
'members_count': int, # Кол-во членов
'is_active': bool, # Активна ли
'created_at': datetime, # Дата добавления
'updated_at': datetime, # Дата обновления
}
```
### GroupMember (в БД)
```python
{
'id': int, # ID в БД
'group_id': int, # ID группы
'user_id': str, # Telegram user ID
'username': str, # Username (@username)
'first_name': str, # Имя
'last_name': str, # Фамилия
'is_bot': bool, # Это бот?
'is_admin': bool, # Администратор?
'is_owner': bool, # Владелец?
'joined_at': datetime, # Когда присоединился
'created_at': datetime, # Дата добавления в БД
'updated_at': datetime, # Дата обновления в БД
}
```
## Обработка ошибок
### FloodWaitError
При большом кол-ве запросов Telegram может ограничить доступ. Парсер автоматически:
- Перехватывает ошибку FloodWaitError
- Записывает в логи время ожидания
- Возвращает частично загруженные данные
### PeerIdInvalidError
Неверный ID группы - проверьте chat_id
### UserNotParticipantError
Бот не участник группы - добавьте его в группу предварительно
### ChatAdminRequiredError
Нужны права администратора для парсинга - добавьте бота администратором
## Примеры использования
### Пример 1: Парсить группу через кнопку в боте
```python
# В обработчике кнопки
from app.userbot.tasks import parse_group_task
async def handle_parse_button(update, context):
chat_id = -1001234567890
# Отправить в Celery
task = parse_group_task.delay(chat_id)
await update.callback_query.edit_message_text(
f"📊 Парсинг группы запущен (Task ID: {task.id})"
)
```
### Пример 2: Синхронизировать все группы по расписанию
```python
# В celery_tasks.py
from celery.schedules import crontab
app.conf.beat_schedule = {
'sync-all-groups-daily': {
'task': 'app.userbot.tasks.sync_all_groups',
'schedule': crontab(hour=0, minute=0), # Каждый день в 00:00
},
}
```
### Пример 3: Получить участников группы
```python
from app.userbot.tasks import parse_group_members_task
# Запустить задачу
task = parse_group_members_task.delay(
chat_id=-1001234567890,
limit=10000
)
# Дождаться результата
result = task.get() # {'status': 'success', 'members_count': 5432}
```
## Мониторинг
### Через логи
```bash
docker-compose logs -f userbot | grep "✅\|❌\|⏳"
```
### Через Flower
http://localhost:5555/dashboard
Отслеживайте:
- Active tasks
- Task history
- Worker stats
- Pool size
### Метрики
```python
# Получить статистику парсинга
from app.database.repository import GroupRepository
async with AsyncSessionLocal() as session:
repo = GroupRepository(session)
groups = await repo.get_all_active_groups()
for group in groups:
print(f"{group.title}: {group.members_count} членов")
```
## Troubleshooting
### UserBot не авторизован
```
❌ UserBot не авторизован. Требуется повторный вход.
```
**Решение:**
1. Удалить `sessions/userbot_session.session`
2. Запустить интерактивно: `python userbot_service.py`
3. Следовать инструкциям авторизации
### FloodWait ошибки
```
⏳ FloodWait на 3600с при парсинге участников
```
**Решение:**
- Это нормально - Telegram ограничивает быстрые запросы
- Парсер автоматически ждет и продолжает после перерыва
- Можно уменьшить `limit` параметр для меньшего нагрузки
### Задача зависает
```python
# Проверить статус задачи
from celery.result import AsyncResult
task_id = "xxx"
result = AsyncResult(task_id)
print(result.status) # PENDING, PROGRESS, SUCCESS, FAILURE
```
### Нет доступа к группе
```
⚠️ Нет доступа к группе -1001234567890
```
**Решение:**
- Добавить UserBot в группу
- Дать права администратора если нужен доступ к приватным данным
## Производительность
### Рекомендуемые настройки для разных размеров групп
| Размер | Limit | Timeout | Celery workers |
|--------|-------|---------|-----------------|
| <1K | 1000 | 30s | 1-2 |
| 1K-10K | 5000 | 60s | 2-4 |
| >10K | 10000 | 120s | 4-8 |
### Оптимизация
```python
# Парсить в части если много участников
from math import ceil
total_members = 50000
batch_size = 5000
for i in range(ceil(total_members / batch_size)):
offset = i * batch_size
members = await userbot_parser.parse_group_members(
chat_id,
limit=batch_size,
offset=offset
)
```
## Лимиты Telegram
- **Rate limit**: ~33 запроса в секунду на одно соединение
- **FloodWait**: автоматически триггерится при превышении
- **Размер результата**: до 100K членов в одной группе
## Безопасность
⚠️ **Важно!**
- Не делитесь сессионными файлами (`sessions/userbot_session.session`)
- API ID и HASH - это не для публичного доступа
- Используйте отдельный аккаунт Telegram для UserBot
- Хранить в .env.local (не коммитить!)
## Лицензия
Внутренний микросервис проекта TG Autoposter