Telemax/tests/proxy.test.ts
Folist f28739d860 Прокси для Telegram (SOCKS5/HTTP/HTTPS) + уведомления об ошибках в ТГ
Фаза 1 — ядро прокси:
- src/telegram/proxy.ts: агент из TELEGRAM_PROXY (socks5/http/https), редакция
  кред в логах, override в ./data (перекрывает env), singleton на старте.
- app.ts: агент в Telegraf; upload.ts: то же для скачивания файлов с
  api.telegram.org/file (единственная точка мимо Telegraf). MAX всегда напрямую.
- setup.sh: вопрос про прокси до проверки связи; проверка Telegram, getUpdates и
  setChatPhoto идут через прокси; TELEGRAM_PROXY пишется в .env.

Фаза 2 — веб-панель:
- Эндпоинты GET/POST /api/proxy, /api/proxy/test, /api/system/restart.
- Карточка «Telegram-прокси» в Configuration: тест вживую + сохранить и
  перезапустить (persist в ./data, применение self-restart'ом).

Фаза 3 — ошибки моста в ТГ, без спама:
- src/bridge/errorReporter.ts: троттлинг (10 мин на ключ + 6/час потолок).
- Хуки: потеря/восстановление связи с MAX (дебаунс 60с), сбой доставки в
  Telegram, unhandled/uncaught (общий текст, без утечки токенов).
2026-08-16 20:06:05 +03:00

45 lines
1.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { buildTelegramProxyAgent, redactProxyUrl } from '../src/telegram/proxy.js';
describe('buildTelegramProxyAgent', () => {
it('returns undefined when no proxy is configured', () => {
expect(buildTelegramProxyAgent('')).toBeUndefined();
expect(buildTelegramProxyAgent(' ')).toBeUndefined();
});
it('builds a SOCKS agent for socks schemes', () => {
const agent = buildTelegramProxyAgent('socks5://user:pass@10.0.0.1:1080');
expect(agent).toBeDefined();
expect(agent?.constructor.name).toMatch(/Socks/i);
});
it('builds an HTTP(S) agent for http/https schemes', () => {
expect(buildTelegramProxyAgent('http://proxy:3128')?.constructor.name).toMatch(/Https/);
expect(buildTelegramProxyAgent('https://proxy:3128')?.constructor.name).toMatch(/Https/);
});
it('throws on an unsupported scheme so a typo fails loudly', () => {
expect(() => buildTelegramProxyAgent('ftp://proxy:21')).toThrow(/unsupported scheme/);
});
it('throws on a malformed URL', () => {
expect(() => buildTelegramProxyAgent('not a url')).toThrow(/valid URL/);
});
});
describe('redactProxyUrl', () => {
it('strips credentials from the logged form', () => {
const red = redactProxyUrl('socks5://user:secret@10.0.0.1:1080');
expect(red).not.toContain('secret');
expect(red).not.toContain('user');
expect(red).toContain('10.0.0.1:1080');
});
it('leaves a credential-free URL usable', () => {
expect(redactProxyUrl('http://proxy:3128')).toContain('proxy:3128');
});
it('returns a placeholder for garbage', () => {
expect(redactProxyUrl('not a url')).toBe('(invalid)');
});
});