Files
2026-07-19 21:24:04 +00:00

114 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Telegram Call Service
REST-сервис: `POST /call` → делает настоящий **1-на-1 звонок** (p2p call,
такой же, как обычный звонок в приложении Telegram — с гудком и ожиданием
ответа) указанному пользователю под вашим аккаунтом и озвучивает переданный
текст через TTS сразу после того, как вызываемый принял звонок.
## Как это устроено
Telegram Bot API **не умеет** звонить — это принципиальное ограничение платформы,
никакой код это не обойдёт. Настоящий голосовой звонок доступен только через
MTProto-аккаунт обычного пользователя (Pyrogram-форк `pyrofork` + `py-tgcalls`,
низкоуровневый биндинг `ntgcalls`).
Библиотека `py-tgcalls` делает это через `phone.requestCall` / `phone.acceptCall`
с DH key exchange — ровно тот же путь, которым идёт обычный звонок из
приложения. `play()` блокирует выполнение, пока собеседник не ответит (или не
истечёт `CALL_RING_TIMEOUT`), бросает `TimedOutAnswer` / `CallDeclined` /
`CallBusy`, если не дозвонились.
## ⚠️ Важно понимать риски
- Это автоматизация **личного аккаунта**, а не бота. Telegram может ограничить
или заблокировать аккаунт за автоматизированные действия, особенно при
частом/массовом использовании. Используйте выделенный номер, не основной.
- API_ID/API_HASH и session-файл дают полный доступ к аккаунту — храните
`.env` и `sessions/` так же бережно, как пароль.
- Не используйте это для звонков посторонним людям без их согласия.
- Звонок реально дозвонится только если у вызываемого аккаунта в
**Settings → Privacy and Security → Calls** разрешены звонки от вашего
аккаунта (например, "Everybody", или вы у него в контактах). Иначе Telegram
тихо отклонит попытку на уровне privacy — это ограничение платформы, не бага
сервиса.
## Настройка
### 1. Получить API_ID / API_HASH
https://my.telegram.org → API development tools → создать приложение.
### 2. Настроить .env
```bash
cp .env.example .env
# заполнить API_ID, API_HASH, PHONE_NUMBER, CALL_TARGET, API_TOKEN
```
`CALL_TARGET` — кому звонить по умолчанию: `@username` вызываемого аккаунта
(или его numeric user id). Убедитесь, что у вызывающего аккаунта этот
пользователь виден (например, есть в контактах) — иначе `resolve_peer` не
сможет найти адресата по username при первом обращении.
### 3. Один раз залогиниться (интерактивно, вне обычного запуска)
```bash
docker compose build
docker compose run --rm callsvc python scripts/login.py
```
Введите код из Telegram (и пароль 2FA, если включён). Session-файл сохранится
в `./sessions/` на хосте и будет переиспользоваться при обычном запуске.
### 4. Запуск сервиса
```bash
docker compose up -d
```
## API
### `GET /health`
Проверка живости.
### `POST /call`
```bash
curl -X POST http://localhost:8000/call \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_TOKEN" \
-d '{"text": "Внимание! Сработал алерт на проде."}'
```
Поля тела запроса:
| поле | обязательное | описание |
|--------|--------------|---------------------------------------------------------------------------|
| text | да | текст, который будет озвучен (TTS, до 2000 символов) |
| target | нет | `@username` или numeric user id вызываемого. Если не задан — берётся `CALL_TARGET` из `.env` |
Если `API_TOKEN` в `.env` не задан — заголовок `Authorization` не требуется.
Ответ (после того, как собеседник принял звонок и TTS проигрался):
```json
{"status": "called", "target": "@monster1025", "duration": 4.2}
```
Ошибки:
- `409` — не дозвонились: не ответили за `CALL_RING_TIMEOUT` секунд, отклонили,
заняты, звонок сброшен, либо звонок на эту цель уже идёт, либо `target`
резолвится в группу/канал (сервис звонит только пользователям).
- `401` — неверный/отсутствующий Bearer-токен (если `API_TOKEN` задан).
- `500` — прочие ошибки (см. логи `docker compose logs -f`).
## Ограничения текущей версии
- Один одновременный звонок на цель (защищено локом), параллельные запросы
на разные `target` обрабатываются независимо.
- Озвучка через gTTS требует исходящего доступа в интернет из контейнера.
- `POST /call` синхронно ждёт ответа на звонок (до `CALL_RING_TIMEOUT` сек) —
учитывайте это в таймауте клиента, который дёргает ручку.