Переписать проект в личный MTProto-юзербот

Смена архитектуры с бизнес-бота на Bot API (команды со слешем) на
личный юзербот на GramJS/MTProto с управлением через компаньон-бота.

Возможности:
- antidelete — кэш входящих в личке, восстановление удалённых «у всех»
- onetime — перехват «просмотр один раз» фото/видео до истечения ссылки
- локальное хранилище node:sqlite + шифрование AES-256-GCM, чистка по сроку
- компаньон-бот (grammY): инлайн-панель, лента с пагинацией, выдача медиа,
  доступ только владельцу по OWNER_ID

Устройство:
- core/ — crypto, db, media, loader, registry, logger
- userbot/ — MTProto-клиент из строки сессии, подписка на события
- modules/ — фичи как модули с хуками setup/onMessage/onEdited/onDeleted
- bot/ — компаньон-бот (единственный UI)
- scripts/login.js — генерация строки сессии

Удалён старый код Bot API (commands/, handlers/, middlewares/, dispatcher,
store). Обновлены README и .env.example. Hcrgram/ (сторонний референс)
добавлен в .gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 19:16:52 +03:00
parent e92e0df644
commit 15a03a77fd
40 changed files with 1845 additions and 922 deletions
-20
View File
@@ -1,20 +0,0 @@
/**
* Проверка структуры без обращения к Telegram: грузит все команды,
* ловит конфликты триггеров и печатает таблицу. Токен не нужен.
*
* npm run check
*/
import { loadCommands } from '../src/core/loader.js';
const registry = await loadCommands();
const rows = registry.list().map((cmd) => ({
команда: `/${cmd.command}`,
алиасы: cmd.aliases.join(', ') || '—',
scope: cmd.scope,
admin: cmd.adminOnly ? 'да' : '',
hidden: cmd.hidden ? 'да' : '',
файл: cmd.source,
}));
console.table(rows);
console.log(`В меню Telegram уйдёт: ${registry.forTelegram().map((c) => `/${c.command}`).join(' ') || '—'}`);
+31
View File
@@ -0,0 +1,31 @@
import { TelegramClient } from 'telegram';
import { StringSession } from 'telegram/sessions/index.js';
import input from 'input';
/**
* Одноразовый интерактивный вход: вводите телефон/код (и пароль 2FA, если есть),
* скрипт печатает строку сессии — её нужно вставить в .env как SESSION=...
* Запуск: npm run login
*/
const apiId = Number(process.env.API_ID);
const apiHash = process.env.API_HASH;
if (!Number.isInteger(apiId) || !apiHash) {
console.error('Сначала задайте API_ID и API_HASH в .env (получить: https://my.telegram.org).');
process.exit(1);
}
const client = new TelegramClient(new StringSession(''), apiId, apiHash, { connectionRetries: 5 });
await client.start({
phoneNumber: () => input.text('Телефон (в формате +7...): '),
password: () => input.text('Пароль 2FA (если нет — Enter): '),
phoneCode: () => input.text('Код из Telegram: '),
onError: (err) => console.error(err),
});
console.log('\n✅ Готово. Вставьте строку в .env как SESSION=\n');
console.log(client.session.save());
console.log('\nНикому не передавайте её — это полный доступ к аккаунту.');
await client.disconnect();
process.exit(0);
-18
View File
@@ -1,18 +0,0 @@
/**
* Отправляет список команд в Telegram, не поднимая бота.
*
* npm run sync
*/
import { Bot } from 'grammy';
import { assertConfig, config } from '../src/config.js';
import { loadCommands } from '../src/core/loader.js';
assertConfig();
const registry = await loadCommands();
const bot = new Bot(config.token);
const commands = registry.forTelegram();
await bot.api.setMyCommands(commands);
console.log(`Готово. Отправлено команд: ${commands.length}`);