7.6 KiB
7.6 KiB
sechenov — Claude Chat + Stealth Portal + OpenAI-compat Endpoint
Express-сервер, совмещающий три роли:
- Stealth чат для студента на клоне портала Сеченовки (
https://s.akyra.ru/,https://student.sechen0v.ru/,https://dl.sechen0v.ru/) - OpenAI-совместимый endpoint
/v1/chat/completionsдля Chrome-расширенияext/(Moodle AI Solver) - Мост Anthropic через Claude Max OAuth с авто-рефрешем токена, HTTP-прокси на VPS и fallback Opus→Sonnet→Haiku
Stack
- Node.js + Express
- Anthropic API напрямую (
https://api.anthropic.com/v1/messages) через Claude Max OAuth (.credentials.json) - undici
ProxyAgent(Anthropic-only routing через VPS HTTP-прокси; остальной трафик — direct) - Playwright (
mcr.microsoft.com/playwright:v1.59.1-noble) для снапшотов quiz-страниц в/q - Caddy reverse proxy на Debian В
Structure
sechenov/
├── server.js — всё: /api/chat, /api/notify, /v1/chat/completions, /q, /auth.php, OAuth refresh
├── public/
│ ├── index.html — stealth portal + скрытый чат
│ ├── q/index.html — Playwright-снятый клон quiz-страницы со слотами чата
│ └── assets/... — зеркало статики с оригинала
├── scripts/
│ └── mirror.js — Playwright fullPage screenshot + инжект чат-слотов
└── package.json
Models
MODELS = {
opus: 'claude-opus-4-7',
sonnet: 'claude-sonnet-4-6',
haiku: 'claude-haiku-4-5-20251001'
}
THINKING_MODELS = new Set(['claude-opus-4-7'])
THINKING_BUDGET_TOKENS = 16000
/api/chat— defaultopus, fallback на Haiku при 429/v1/chat/completions— принимает OpenAI-совместимый payload, mapping модели по substring, конвертируетimage_url→ Anthropicimage/base64
Endpoints
| Путь | Назначение |
|---|---|
/ |
public/index.html (stealth portal) |
/q, /q.html, /mod/quiz/attempt.php |
public/q/index.html (клон quiz) |
/auth.php |
public/index.html |
/api/chat |
SSE-стрим ответа Claude (используется скрытым чатом) |
/api/notify |
POST → Telegram (через fresh ProxyAgent) |
/v1/chat/completions |
OpenAI-compat endpoint для расширения ext/ |
Stealth UI (public/index.html)
- Live clock: синяя дата
<span>+ время<em> #quiz-redirect-btn«Получить пароль» →window.location.href = 'https://dl.sechen0v.ru/mod/quiz/attempt.php?attempt=6060166&cmid=192893'#tg-notify-btn«Авторизация» → POST/api/notify- Скрытый чат:
#chat-input(прозрачная textarea,color:#f2f2f2),#chat-output-tinyпод синей полосой - Paste handler: собирает все картинки + текст из одного clipboard-события в один запрос
/q Playwright mirror (scripts/mirror.js)
- Запуск в docker:
mcr.microsoft.com/playwright:v1.59.1-noble+npm install playwright@1.59.1 --no-save - Viewport 1600×900, deviceScaleFactor 2,
fullPage: true - Инжект
.que + .que { margin-top: 180px !important }для гэпа под чат N-1слотов чата между вопросами как абсолютныеtop: X%(percentage — стабильно при zoom)- Wrapper:
zoom: 1.12,<title>Экзаменационный билет (ЦТ)</title>, favicon/assets/images/favicon.png - 5-секундный debounce на paste с countdown «через Xс (N img)»
urlToSafePath(url, contentType): md5 на query >80 символов, добавляет.css/.js/.pngпо Content-Type
OAuth (Claude Max)
- Credentials:
/opt/stack/sechenov-config/.credentials.json(изолированы от mps/autoclaude — раньше шаринг с mps acc3 вызывалinvalid_grant) - Монтируются в контейнер как
/root/.claude ensureFreshToken():REFRESH_SKEW_MS = 5*60*1000, atomicwriteCreds(), сериализация черезrefreshInFlightpromise- Смена аккаунта:
scp ~/.claude/.credentials.json aedes@192.168.1.20:/opt/stack/sechenov-config/
VPS Proxy (IPv4-only HTTP)
- VPS: 194.87.245.138:8889 (актуальный), скрипт
/opt/claude-proxy-8889.py, systemdclaude-proxy.service - Патч:
ipv4_connect()черезgetaddrinfo(..., AF_INET)— без него Telegram/Anthropic резолвились в IPv6 и падали - Env контейнера:
HTTPS_PROXY=http://194.87.245.138:8889(в/opt/stack/docker-compose.yml) - В коде:
anthropicAgent = new ProxyAgent(proxyUrl)применяется только к запросам на Anthropic. Глобально —directAgent. - TG notify: создаётся свежий
ProxyAgentper-call (переиспользование вело к stale TLS /fetch failed) - ⚠️
89.125.243.153— другой сервер (без SSH-доступа), не использовать
Telegram notify
TG_BOT_TOKEN = '8489078585:AAH3PrYNBiX-YMZA9XgHT2rE6yaK8BqwCOI'
TG_CHAT_ID = '833411630'
TG_MESSAGE = 'начинай решать через 5 мин'
Fresh ProxyAgent per call → api.telegram.org/bot<token>/sendMessage.
Chrome Extension integration (../ext/)
OR_URL = 'https://s.akyra.ru/v1/chat/completions'DEFAULT_MODEL = 'opus',FALLBACK_MODELS = ['sonnet', 'haiku']DEFAULT_KEY = 'sechenov-local'(сервер принимает любой bearer)- Расширение маскируется под uBlock Origin, активация Alt+w на quiz-странице
Local (machine B)
- Path:
C:\Users\aedes\REUNION\sync\scriptsAedes\sechenov
Remote (Debian В)
- Path:
/opt/stack/sechenov/ - URL:
https://s.akyra.ru+ алиасыstudent.sechen0v.ru,dl.sechen0v.ru - Port: 8108
- Caddy: блоки для всех трёх доменов →
127.0.0.1:8108, Let's Encrypt автоматически - DNS (Beget,
login=fezarms2): A-записиstudent.sechen0v.ru,dl.sechen0v.ru→94.141.253.12 - Deploy:
git push ssh aedes@192.168.1.20 "cd /opt/stack/sechenov && git pull && docker compose restart sechenov"
Известные грабли
- invalid_grant если шарить
.credentials.jsonс mps/autoclaude — держать изолированно вsechenov-config/. Авторефреш черезscripts/sync-creds.ps1(Windows Task Scheduler, смотрит~/.claude/.credentials.json) - TG 502 → IPv6 в proxy; фикс —
AF_INETв/opt/claude-proxy.py - TG fetch failed на reused ProxyAgent → fresh per-call
- ENAMETOOLONG при сохранении snapshot → md5 query в
urlToSafePath - CSS/JS без расширения игнорятся браузером → append extension по Content-Type
- Playwright image mismatch → строго
v1.59.1-noble+playwright@1.59.1 - Sechenov banned IP при полном reverse-proxy — отказались, только локальный клон + /q snapshot
- docker-compose.yml sed легко задевает mps/autoclaude mounts — править вручную
Update this file
После изменений в структуре, стеке, конфигах или инфре — обновить этот CLAUDE.md.