# telegrambusiness Личный Telegram-**юзербот** на Node.js + MTProto (GramJS). Работает от вашего аккаунта и сохраняет то, что Bot API недоступно: - **antidelete** — сообщения, которые собеседник удалил в личке; - **onetime** — одноразовые («просмотр один раз») фото и видео. Всё управление и все перехваты приходят в **компаньон-бота** — отдельного бота от [@BotFather](https://t.me/BotFather), в личку владельца. Наружу юзербот ничего не пишет, слеш-команд в чатах нет. > ⚠️ **Дисклеймер.** Инструмент для личного использования на **своём** аккаунте и своей переписке. Юзерботы нарушают ToS Telegram и аккаунт могут заблокировать — держите его на отдельном номере, не на основном. Одноразовые медиа отправляются с расчётом на удаление; сохраняя их, вы берёте ответственность на себя. ## Как устроено (важно понимать до запуска) MTProto в событии удаления присылает **только id сообщений** — без текста и без медиа. Поэтому «сохранить удалённое» реактивно невозможно: юзербот **заранее кэширует каждое входящее** в личке, а при удалении достаёт его из своего кэша. То же с медиа — файл качается **в момент прихода**, после удаления ссылка мертва. Отсюда следствия: - тексты и метаданные пишутся в локальную БД (`node:sqlite`), **зашифрованы** (AES-256-GCM); - медиа лежат отдельными **зашифрованными** файлами в `data/media/`; - всё чистится по `RETENTION_DAYS`. ## Установка Нужен Node.js ≥ 22.5 (для встроенного `node:sqlite`). ```bash npm install cp .env.example .env ``` Заполните `.env`: 1. **API_ID / API_HASH** — [my.telegram.org](https://my.telegram.org) → API development tools. 2. **BOT_TOKEN** — новый бот у [@BotFather](https://t.me/BotFather) (это и есть панель). 3. **OWNER_ID** — ваш id (напишите [@userinfobot](https://t.me/userinfobot)). 4. **ENCRYPTION_KEY** — сгенерируйте: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`. Затем одноразовый вход в аккаунт (телефон, код, при наличии — пароль 2FA): ```bash npm run login ``` Скрипт напечатает строку сессии — вставьте её в `.env` как `SESSION=...` и запускайте: ```bash npm run dev ``` Откройте своего бота, нажмите **Start** — появится панель. При удалении сообщения собеседником или получении одноразового медиа бот пришлёт уведомление с кнопкой «Открыть». `npm run dev` — с автоперезапуском, `npm start` — обычный запуск. ## Как добавить модуль Модуль — файл в `src/modules/`. Загрузчик обходит папку рекурсивно; файлы на `_` игнорируются. Объявляйте только нужные хуки: ```js // src/modules/keywords.js export default { name: 'keywords', description: 'Уведомлять, если во входящем есть ключевое слово', async onMessage(message, ctx) { if (message.out) return; // не своё if (/срочно/i.test(message.text ?? '')) { await ctx.capture('deleted', { // переиспользуем ленту перехватов chatId: message.chatId, senderId: message.senderId, sender: (await message.getSender().catch(() => null))?.username ?? '', text: message.text, }); } }, }; ``` | Хук | Когда вызывается | | --- | --- | | `setup(_, ctx)` | Один раз при старте | | `onMessage(message, ctx)` | Новое сообщение (`NewMessage`) | | `onEdited(message, ctx)` | Правка (`EditedMessage`) | | `onDeleted(event, ctx)` | Удаление; `event.deletedIds` — массив id | `ctx` даёт: `client` (GramJS), `me`, `registry` и `capture(kind, data)` — сохранить перехват и уведомить владельца. Ошибка в одном модуле не роняет остальные ([registry.js](src/core/registry.js) — `runHook`). ## Устройство ``` src/ index.js сборка: юзербот + бот + модули + чистка config.js .env, проверка на старте core/ crypto.js AES-256-GCM (шифр текста и медиа) db.js node:sqlite: кэш входящих + лента перехватов media.js тип медиа, детект one-time, скачать+шифровать loader.js обход src/modules registry.js реестр модулей, runHook logger.js userbot/ client.js MTProto-клиент из строки сессии events.js подписка NewMessage/Edited/Deleted → модули context.js ctx.capture — мост модуль↔БД↔бот modules/ cache.js кэширует входящие (основа antidelete) antidelete.js удаление → достать из кэша → перехват onetime.js one-time медиа → скачать → перехват bot/ panel.js компаньон-бот: инлайн-панель, лента, выдача медиа scripts/ login.js генерация строки сессии ``` Поток: входящее → `cache`/`onetime` (кэш и/или скачивание) → при удалении `antidelete` поднимает из кэша → `ctx.capture` пишет в БД и шлёт уведомление → панель показывает и отдаёт расшифрованный файл. ## Что стоит учесть - Перехватываются только **входящие в личных диалогах**. Группы, каналы и свои сообщения — нет (см. `isPrivateIncoming` в [events.js](src/userbot/events.js)). - «Удалить у себя» на стороне собеседника юзерботу не приходит — ловится только «удалить у всех». - `CACHE_MEDIA=1` качает медиа каждого входящего, чтобы восстанавливать удалённые картинки. Это ест диск — при `=0` останется только текст и пометка о типе медиа. - Ключ шифрования — в `.env`. Потеряете ключ — расшифровать хранилище нельзя. - Хранилище локальное; `data/` в `.gitignore`. ```