382 lines
11 KiB
Markdown
382 lines
11 KiB
Markdown
# Телетон (Telethon) - Справочник
|
||
|
||
## Обзор
|
||
|
||
**Telethon** - это Python библиотека для взаимодействия с Telegram API как обычный пользователь (клиент), а не как бот.
|
||
|
||
Это позволяет отправлять сообщения в группы, где боты не имеют прав на отправку.
|
||
|
||
## Установка и Настройка
|
||
|
||
### 1. Получение API Credentials
|
||
|
||
Перейти на https://my.telegram.org/apps и:
|
||
- Войти в свой аккаунт Telegram
|
||
- Создать приложение (или использовать существующее)
|
||
- Скопировать `API ID` и `API HASH`
|
||
|
||
### 2. Обновление .env
|
||
|
||
```env
|
||
USE_TELETHON=true
|
||
TELETHON_API_ID=123456
|
||
TELETHON_API_HASH=abcdef1234567890
|
||
TELETHON_PHONE=+79991234567
|
||
```
|
||
|
||
### 3. Первый Запуск
|
||
|
||
При первом запуске бота Telethon создаст сессию и попросит ввести код подтверждения:
|
||
|
||
```
|
||
Telethon需要验证您的帐户...
|
||
Введите код подтверждения из Telegram: ______
|
||
```
|
||
|
||
Код придет в Telegram личные сообщения.
|
||
|
||
## Гибридный Режим
|
||
|
||
Когда `USE_TELETHON=true`, бот работает в **гибридном режиме**:
|
||
|
||
1. **Сначала** пытается отправить как бот
|
||
2. **При ошибке** (бот заблокирован) пытается отправить как Telethon клиент
|
||
3. **Автоматически** отслеживает какой способ работает и его использует
|
||
|
||
```python
|
||
# Автоматическое переключение
|
||
success, method = await hybrid_sender.send_message(
|
||
chat_id="-1001234567890",
|
||
message_text="Привет!"
|
||
)
|
||
|
||
if method == "bot":
|
||
print("Отправлено как бот ✅")
|
||
elif method == "client":
|
||
print("Отправлено как Telethon клиент ✅")
|
||
```
|
||
|
||
## Основной API
|
||
|
||
### Инициализация
|
||
|
||
```python
|
||
from app.handlers.telethon_client import telethon_manager
|
||
|
||
# Инициализировать
|
||
await telethon_manager.initialize()
|
||
|
||
# Проверить подключение
|
||
if telethon_manager.is_connected():
|
||
print("Telethon подключен")
|
||
|
||
# Завершить
|
||
await telethon_manager.shutdown()
|
||
```
|
||
|
||
### Отправка Сообщений
|
||
|
||
```python
|
||
# Простая отправка
|
||
message_id = await telethon_manager.send_message(
|
||
chat_id=-1001234567890,
|
||
text="Привет мир!",
|
||
parse_mode="html",
|
||
disable_web_page_preview=True
|
||
)
|
||
|
||
if message_id:
|
||
print(f"Сообщение отправлено: {message_id}")
|
||
```
|
||
|
||
### Получение Информации о Группе
|
||
|
||
```python
|
||
# Получить информацию
|
||
info = await telethon_manager.get_chat_info(chat_id)
|
||
|
||
if info:
|
||
print(f"Название: {info['title']}")
|
||
print(f"Описание: {info['description']}")
|
||
print(f"Участников: {info['members_count']}")
|
||
```
|
||
|
||
### Получение Участников
|
||
|
||
```python
|
||
# Получить список участников
|
||
members = await telethon_manager.get_chat_members(
|
||
chat_id=-1001234567890,
|
||
limit=100
|
||
)
|
||
|
||
for member in members:
|
||
print(f"{member['first_name']} (@{member['username']})")
|
||
```
|
||
|
||
### Поиск Сообщений
|
||
|
||
```python
|
||
# Найти сообщения
|
||
messages = await telethon_manager.search_messages(
|
||
chat_id=-1001234567890,
|
||
query="python",
|
||
limit=50
|
||
)
|
||
|
||
for msg in messages:
|
||
print(f"[{msg['date']}] {msg['text']}")
|
||
```
|
||
|
||
### Редактирование и Удаление
|
||
|
||
```python
|
||
# Отредактировать
|
||
msg_id = await telethon_manager.edit_message(
|
||
chat_id=-1001234567890,
|
||
message_id=123,
|
||
text="Новый текст"
|
||
)
|
||
|
||
# Удалить
|
||
success = await telethon_manager.delete_message(
|
||
chat_id=-1001234567890,
|
||
message_id=123
|
||
)
|
||
```
|
||
|
||
## Массовая Отправка
|
||
|
||
```python
|
||
from app.handlers.hybrid_sender import HybridMessageSender
|
||
|
||
sender = HybridMessageSender(bot, db_session)
|
||
|
||
# Отправить с retry логикой
|
||
success, method = await sender.send_message_with_retry(
|
||
chat_id="-1001234567890",
|
||
message_text="Важное сообщение",
|
||
max_retries=3
|
||
)
|
||
|
||
# Массовая отправка
|
||
results = await sender.bulk_send(
|
||
chat_ids=chat_ids,
|
||
message_text="Привет всем!",
|
||
use_slow_mode=True
|
||
)
|
||
|
||
print(f"Успешно: {results['success']}")
|
||
print(f"Через бот: {results['via_bot']}")
|
||
print(f"Через клиент: {results['via_client']}")
|
||
```
|
||
|
||
## Парсинг Групп
|
||
|
||
```python
|
||
from app.handlers.group_parser import GroupParser
|
||
|
||
parser = GroupParser(db_session)
|
||
|
||
# Парсить группу по ключевым словам
|
||
result = await parser.parse_group_by_keywords(
|
||
keywords=["Python", "Django"],
|
||
chat_id=-1001234567890
|
||
)
|
||
|
||
if result['matched']:
|
||
print(f"✅ Группа соответствует! Найдено: {result['keywords_found']}")
|
||
|
||
# Загрузить участников
|
||
members_result = await parser.parse_group_members(
|
||
chat_id=-1001234567890,
|
||
member_repo=member_repo,
|
||
limit=1000
|
||
)
|
||
|
||
print(f"Загружено участников: {members_result['members_added']}")
|
||
```
|
||
|
||
## Обработка Ошибок
|
||
|
||
### FloodWait
|
||
|
||
Telegram ограничивает частоту операций. Telethon автоматически обрабатывает:
|
||
|
||
```python
|
||
from telethon.errors import FloodWaitError
|
||
|
||
try:
|
||
await telethon_manager.send_message(chat_id, text)
|
||
except FloodWaitError as e:
|
||
print(f"Нужно ждать {e.seconds} секунд")
|
||
# Гибридный отправитель автоматически ждет и повторяет
|
||
```
|
||
|
||
### ChatAdminRequired
|
||
|
||
Клиент не администратор в этой группе:
|
||
|
||
```python
|
||
from telethon.errors import ChatAdminRequiredError
|
||
|
||
try:
|
||
members = await telethon_manager.get_chat_members(chat_id)
|
||
except ChatAdminRequiredError:
|
||
print("Клиент не администратор")
|
||
```
|
||
|
||
### UserNotParticipant
|
||
|
||
Клиент не участник группы:
|
||
|
||
```python
|
||
from telethon.errors import UserNotParticipantError
|
||
|
||
try:
|
||
info = await telethon_manager.get_chat_info(chat_id)
|
||
except UserNotParticipantError:
|
||
print("Клиент не в этой группе")
|
||
```
|
||
|
||
## Статистика и Мониторинг
|
||
|
||
Система автоматически отслеживает:
|
||
|
||
- Какие группы работают с ботом
|
||
- Какие требуют Telethon клиента
|
||
- Сколько сообщений отправлено каждым методом
|
||
- Ошибки и ограничения
|
||
|
||
```python
|
||
stats = await stats_repo.get_statistics(group_id)
|
||
|
||
if stats:
|
||
print(f"Всего участников: {stats.total_members}")
|
||
print(f"Отправлено сообщений: {stats.messages_sent}")
|
||
print(f"Через клиент: {stats.messages_via_client}")
|
||
print(f"Может отправлять как бот: {'✅' if stats.can_send_as_bot else '❌'}")
|
||
print(f"Может отправлять как клиент: {'✅' if stats.can_send_as_client else '❌'}")
|
||
```
|
||
|
||
## Лучшие Практики
|
||
|
||
### 1. Используйте Гибридный Режим
|
||
|
||
Всегда включайте оба метода доставки:
|
||
|
||
```env
|
||
USE_TELETHON=true
|
||
USE_CLIENT_WHEN_BOT_FAILS=true
|
||
```
|
||
|
||
### 2. Минимизируйте Частоту Запросов
|
||
|
||
```python
|
||
# Плохо
|
||
for group_id in groups:
|
||
info = await telethon_manager.get_chat_info(group_id)
|
||
|
||
# Хорошо - кэшируйте информацию
|
||
info_cache = {}
|
||
for group_id in groups:
|
||
if group_id not in info_cache:
|
||
info_cache[group_id] = await telethon_manager.get_chat_info(group_id)
|
||
```
|
||
|
||
### 3. Обработайте FloodWait
|
||
|
||
```python
|
||
# Гибридный отправитель уже это делает, но вы можете добавить свою логику
|
||
success, method = await sender.send_message_with_retry(
|
||
chat_id=chat_id,
|
||
message_text=text,
|
||
max_retries=5 # Увеличить количество попыток
|
||
)
|
||
```
|
||
|
||
### 4. Логируйте Действия
|
||
|
||
```python
|
||
import logging
|
||
logger = logging.getLogger(__name__)
|
||
|
||
logger.info(f"Загружаю участников группы {chat_id}...")
|
||
members = await telethon_manager.get_chat_members(chat_id)
|
||
logger.info(f"✅ Загружено {len(members)} участников")
|
||
```
|
||
|
||
## Переменные Конфигурации
|
||
|
||
| Переменная | По умолчанию | Описание |
|
||
|---|---|---|
|
||
| `USE_TELETHON` | false | Включить Telethon |
|
||
| `TELETHON_API_ID` | - | API ID с my.telegram.org |
|
||
| `TELETHON_API_HASH` | - | API HASH с my.telegram.org |
|
||
| `TELETHON_PHONE` | - | Номер телефона с кодом (+7...) |
|
||
| `TELETHON_FLOOD_WAIT_MAX` | 60 | Макс. ждать при FloodWait (сек) |
|
||
| `MIN_SEND_INTERVAL` | 0.5 | Интервал между отправками (сек) |
|
||
|
||
## Отладка
|
||
|
||
### Проверить подключение
|
||
|
||
```python
|
||
# В Python REPL или скрипте
|
||
python -c "
|
||
import asyncio
|
||
from app.handlers.telethon_client import telethon_manager
|
||
|
||
async def test():
|
||
await telethon_manager.initialize()
|
||
if telethon_manager.is_connected():
|
||
print('✅ Telethon подключен')
|
||
else:
|
||
print('❌ Telethon не подключен')
|
||
await telethon_manager.shutdown()
|
||
|
||
asyncio.run(test())
|
||
"
|
||
```
|
||
|
||
### Логи
|
||
|
||
Logирование выполняется автоматически:
|
||
|
||
```python
|
||
import logging
|
||
logging.basicConfig(level=logging.DEBUG)
|
||
```
|
||
|
||
Смотрите `app/handlers/telethon_client.py` для деталей логирования.
|
||
|
||
## Важные Замечания
|
||
|
||
⚠️ **Безопасность Аккаунта**
|
||
|
||
- Никогда не делитесь `TELETHON_API_HASH`
|
||
- Сессия сохраняется в `app/sessions/telethon_session`
|
||
- Защитите файл сессии доступом (не добавляйте в git!)
|
||
|
||
⚠️ **Ограничения Telegram**
|
||
|
||
- Частые отправки могут привести к временной блокировке (FloodWait)
|
||
- Используйте `MIN_SEND_INTERVAL` для управления частотой
|
||
- Не превышайте лимиты Telegram API
|
||
|
||
⚠️ **Первый Запуск**
|
||
|
||
Потребуется интерактивный ввод кода подтверждения. Для production используйте:
|
||
|
||
```python
|
||
# Генерировать заранее в безопасном окружении
|
||
await telethon_manager.initialize()
|
||
```
|
||
|
||
## Полезные Ссылки
|
||
|
||
- [Telethon Документация](https://docs.telethon.dev/)
|
||
- [Telegram Bot API](https://core.telegram.org/bots/api)
|
||
- [Получить API Credentials](https://my.telegram.org/apps)
|
||
- [Типы Ошибок Telethon](https://docs.telethon.dev/en/stable/modules/errors.html)
|