Skip to main content
Glama
README.md
# Юзербот

MCP-сервер, который даёт агенту (Claude Code, Codex и любому MCP-клиенту) руки
в вашем Telegram: не бот с отдельным именем и кнопкой «Start», а ваш обычный
аккаунт-человек. Агент читает те же чаты, что видите вы, пишет от вашего имени,
жмёт кнопки чужих ботов, качает вложения, ставит реакции, ведёт очередь рассылки
с человеческими паузами. Плюс, в том же сервере, тулы для YouTube, Reddit и
Instagram: ресёрч и переписка живут в одном месте.

Работает на Telethon (MTProto). 68 инструментов, из них 45 про Telegram.

## Чем это отличается от обычного бота

| Что | Bot API | Юзербот |
| --- | --- | --- |
| Кто пишет | бот с суффиксом `_bot` | вы, обычный аккаунт |
| Кому может написать первым | только тем, кто нажал Start | кому угодно |
| Что видит в группе | сообщения по privacy-настройке | всё, что видите вы |
| Читает историю чата | нет | да, всю |
| Жмёт кнопки других ботов | нет | да |
| Риск | бан бота | бан аккаунта, поэтому аккаунт отдельный |

## Что умеет

**Читать.** `get_messages` (с пагинацией, топиками форума, метаданными медиа,
просмотрами и реакциями), `search_messages` по истории, `get_message_by_id`,
`export_channel` — выгрузка канала целиком, `list_chats`, `list_forum_topics`,
`get_chat_info`, `get_pinned_message`, `get_chat_member_count`, `get_me`.

**Писать.** `send_message` (в том числе ответом на конкретное сообщение),
`send_file`, `send_album`, `send_contact`, `edit_message`, `delete_message`,
`pin_message`, `unpin_message`, `forward_message`, `copy_message` — репост чужого
поста без плашки «переслано от», `react` — реакции, `set_typing` — «печатает…».

**Рассылать не под баном.** `queue_messages` кладёт серию в фоновую очередь и
шлёт по одному с паузой 25–45 секунд, `queue_status` показывает, где она.
Это не украшение: см. раздел про PeerFlood ниже.

**Отложенное.** `send_message(..., schedule="+2h")` или `schedule="2026-09-10 09:00"`,
дальше `get_scheduled_messages`, `reschedule_scheduled`, `delete_scheduled`,
`send_scheduled_now`. Годится и как отложенный постинг, и как напоминалка себе.

**Общаться с чужими ботами как человек.** `list_inline_buttons`,
`press_inline_button`, `list_reply_buttons`, `press_reply_button`,
`read_bot_response`, `get_bot_info`. Отсюда же берётся трюк «создай себе бота
сам»: агент идёт в @BotFather, проходит диалог, ставит аватарку и команды.

**Медиа.** `download_media` (фото приходит картинкой прямо в контекст, видео и
файлы — на диск), `download_album`, `download_profile_photo`,
`get_sticker_set_emojis`.

**Администрировать.** `join_group`, `join_chatlist` — вступить во все чаты из
папки-ссылки, `add_chat_member`, `promote_admin` — выдать боту админку,
`create_folder`, `mute_chat`, `unmute_chat`.

**Ресёрч рядом.** YouTube (`yt_search`, `yt_video_info`, `yt_comments`,
`yt_captions`, `yt_channel_info`, `yt_playlist`, `yt_quota`), Reddit
(`reddit_search`, `reddit_hot`, `reddit_post`, `reddit_comments`,
`reddit_subreddit_info`, `reddit_user_posts`), Instagram (`ig_profile`,
`ig_posts`, `ig_reels`, `ig_post_comments`, `ig_hashtag`, `ig_search`),
плюс `browse_page`, `gdoc_read`, `gsheet_read` и `rate_limit_status`.

## Прежде чем ставить: как не потерять аккаунт

1. **Отдельный аккаунт и отдельный номер.** Не личный. Бан прилетает аккаунту
   целиком, вместе с перепиской.
2. **Прогрейте его.** Заведите, залогиньтесь с телефона и просто поживите на нём
   неделю: переписки, чтение каналов. Свежий аккаунт, который на второй день
   начинает писать незнакомым, улетает быстро.
3. **Один IP — один юзербот.** Два аккаунта с одного адреса Telegram связывает
   между собой: заблокируют один, найдут второй.
4. **Массовая отправка незнакомым — главный способ поймать бан.** Не FloodWait
   (это секундная пауза, сервер её пересиживает сам), а PeerFlood: блокировка
   отправки на сутки-двое всему аккаунту. Ловится объёмом плюс одинаковым текстом
   встык. Поэтому серии — только `queue_messages`, тексты — разные.
5. **Реакции безопаснее слов.** `react` не считается рассылкой и годится как
   прогрев активности.

Что сервер делает за вас: случайная пауза 2–5 секунд между вызовами, потолок
15 вызовов в минуту с автоматическим торможением, FloodWait пережидается со
сдвигом, entity кэшируются (без лишних resolve), fingerprint клиента — TDesktop
на Windows.

## Установка

Нужен свой сервер (проверено на Ubuntu 22.04 и 24.04, Python 3.10+; хватит
1 CPU и 1 ГБ памяти), Telegram-аккаунт из предыдущего раздела и телефон, на
котором этот аккаунт залогинен.

**1. Ключи приложения.** Зайти на `https://my.telegram.org` тем самым аккаунтом,
раздел API development tools, создать приложение. Оттуда `api_id` и `api_hash`.
Пара привязана к аккаунту, чужую не переиспользовать.

**2. Разложить код.**

```bash
mkdir -p /opt/tg-userbot && cd /opt/tg-userbot
git clone <репозиторий> app
python3 -m venv venv
venv/bin/pip install -r app/requirements.txt
```

**3. Войти в аккаунт.** Только на этом же сервере: логин с одного адреса и
работа с другого — повод для проверки со стороны Telegram.

```bash
cd /opt/tg-userbot/app && ../venv/bin/python scripts/login.py
```

Скрипт спросит `api_id`, `api_hash`, телефон и код. **Код приходит в само
приложение Telegram, а не по SMS, и живёт около пяти минут** — если провозились,
запустите заново. Есть двухфакторный пароль — спросит и его. В конце печатает
строку сессии.

**4. Настроить окружение.**

```bash
cp app/.env.example /opt/tg-userbot/.env
chmod 600 /opt/tg-userbot/.env
# заполнить TELEGRAM_API_ID, TELEGRAM_API_HASH, TELEGRAM_SESSION_STRING
```

Строка сессии равнозначна полному доступу к аккаунту: не в git, не в переписку,
права на файл 600. YouTube, Reddit и Instagram — по желанию, без ключей эти
тулы просто вернут понятную ошибку, Telegram работает.

**5. Политика исходящих** (подробности в следующем разделе). Пока файла нет,
переписка с людьми закрыта, а чтение и боты работают. Копируются оба файла:

```bash
cp app/policy.example.yaml /opt/tg-userbot/policy.yaml
cp app/assistant-gate.example.yaml /opt/tg-userbot/assistant-gate.yaml
```

Два места, куда стоит посмотреть сразу, а не потом:

- `live_channels` в примере пуст. Пока он пуст, агент может опубликовать в любой
  ваш канал мгновенно. Есть канал с живой аудиторией — впишите его id сейчас.
- `human_gate.mode` в примере стоит `enforced`, стоп-лист берётся из
  `assistant-gate.yaml`. Правьте копию под себя; правила в примере — заготовка,
  а не канон. Осознанно не хотите проверки — ставьте `disabled` руками.

**6. Поднять сервисом.**

```bash
cp app/deploy/tg-userbot.service /etc/systemd/system/
systemctl daemon-reload && systemctl enable --now tg-userbot
systemctl status tg-userbot
```

**7. Подключить агента.** Сервер слушает `127.0.0.1:8765` и наружу не смотрит.
С рабочей машины пробрасывается туннель, поверх него подключается MCP:

```bash
ssh -N -L 8765:localhost:8765 root@ваш-сервер     # держать поднятым
claude mcp add userbot --transport http http://127.0.0.1:8765/mcp -s user
```

Проверка живости: `claude mcp list`, затем попросить агента вызвать `get_me`.

## Политика исходящих

Агент, который пишет живым людям от вашего имени, рано или поздно пообещает
что-нибудь лишнее. Поэтому проверка отправки живёт в самом сервере
(`common/outbound_policy.py`), а не в клиентском хуке: её нельзя обойти
переключением approvals или другой моделью.

`policy.yaml` рядом с рабочей копией (не внутри неё — `git pull` не должен её
трогать) задаёт три вещи:

- `self.extra_targets` — ваши собственные аккаунты; сообщения туда не считаются
  перепиской с посторонним. Аккаунт самого юзербота добавляется автоматически;
- `live_channels` — боевые каналы: туда разрешена только отложенная публикация
  в будущее, мгновенная запрещена;
- `human_gate.mode` — `disabled` (писать людям свободно) или `enforced`
  (тексты проходят через стоп-лист `assistant-gate.yaml`, пример лежит рядом).

Поведение при поломке — закрытое: файла нет вообще, значит переписка с людьми
блокируется с объяснением, что это разовая настройка; файл битый или режим
незнакомый, значит блокируется всё охраняемое. `delete_scheduled` работает
всегда: инструмент остановки отправки нельзя терять вместе с конфигом.

Фразы из `requires_confirmation` уходят только после вашего явного решения —
повтором того же вызова с `approved_by_owner=true`. Флаг не отменяет
`forbidden_phrases` и не разрешает мгновенную публикацию в боевой канал.

## Что этот предохранитель не закрывает

Честный список, чтобы не полагаться на него больше, чем он стоит:

- **Агент с shell-доступом на этом же хосте обходит политику несколькими
  командами** — правит `policy.yaml`, подменяет путь, останавливает сервис.
  Гейт защищает от неудачной формулировки и спешки, а не от агента,
  которому вы дали root там же.
- `forward_message` и `send_scheduled_now` выпускают контент без проверки текста.
- Часть действий аккаунта (`join_group`, `mute_chat`, `set_typing` и ещё
  несколько) вне политики вовсе.
- Очередь рассылки проверяет политику при постановке, а не в момент отправки.
- Строка сессии на диске сервера — это весь аккаунт. Хост держите свой.

## Эксплуатация

```bash
systemctl status tg-userbot        # жив ли
journalctl -u tg-userbot -f        # логи
systemctl restart tg-userbot       # перезапуск
/opt/tg-userbot/app/deploy/update.sh   # git pull, зависимости, рестарт
```

Несколько аккаунтов на одной машине: свой каталог, свой `USERBOT_PORT`, своя
копия юнита. Помнить про пункт «один IP — один юзербот».

Квота YouTube (10 000 единиц в сутки) считается на ключ, а не на инстанс: два
сервера с одним ключом делят её, а счётчики ведут раздельно и оба думают, что
она целая.

## Лицензия и здравый смысл

Юзербот-API не запрещён, но политика Telegram запрещает спам и массовые
рассылки. Всё, что вы отправите этим сервером, отправлено вашим аккаунтом и
вашими руками. Ответственность тоже ваша.