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
360 lines
11 KiB
Markdown
360 lines
11 KiB
Markdown
# 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
|