scanner/AGENTS.md
2026-07-29 21:03:59 +03:00

8.7 KiB
Raw Blame History

PoE 2 Scanner — Session Summary (27 Jul 2026)

Hardening work log (29 Jul 2026)

  • Удалены реальные POESESSID из bat-файлов, config.json очищен.
  • Удалён startup.json и код, который записывал в него полный конфиг.
  • Добавлены .gitignore и config.example.json.
  • Сервер слушает только 127.0.0.1; CORS wildcard удалён.
  • Все POST-эндпоинты защищены случайным токеном Web UI.
  • /api/config больше не возвращает секреты и абсолютный путь.
  • Исправлены конфликт DOM id для league и затенение модуля path в /sound.mp3.
  • Добавлены валидация конфигурации, лимит тела запроса и безопасный текстовый вывод UI.
  • Запросы к PoE сериализованы через общую очередь с паузой 1,2 секунды.
  • Live сначала кеширует текущие ID, затем открывает WebSocket.
  • Обработка live-ID и WS reconnect сериализована; старый сокет не может затереть новый.
  • Сервер больше не завершает произвольный процесс на порту 3999.
  • Добавлены node:test, npm test и npm run check.

Что было сделано / починено

WGAP work log (27 Jul 2026 — Nachmittagssitzung)

  • Referer header — добавлен "Referer": "https://www.pathofexile.com/trade2/" в headers() (строка 100). Без него Cloudflare мог ебать.
  • WS message format fix — PoE 2 Live WS шлёт {"message":{"result":["id1","id2"]}}, а не {"new":[...]}. Пофикшено в двух местах:
    • Сервер connectLiveWs (строка 613): теперь разбирает m.new || m.message?.result || [].
    • CLI runLive (строка 253): то же самое.
  • cacheReady выпилен с фронтенда — переменная блокировала показ новых лотов до прихода "Cached N items" из SSE. Убрана целиком (строка 487, 494, 497).
  • Secure / Whisper работает — подтверждено: POST /api/trade2/whisper возвращает {"success":true}, PoE телепортит в зайдаут продавца. Работает только когда персонаж в игре.

Open issues (27 Jul 2026)

  • Full Scan (🔍) в serve-mode — зависает на "Scanning..." или возвращает пустой результат (не тестили при чистом рейт-лимите).
  • Live не показывает реаль-time лоты — фикс WS message формата должен починить, но не тестили (рейт-лимит).

Auth & API

  • POETOKEN (JWT) auth: headers() шлёт POETOKEN в Cookie вместе с POESESSID.
  • hideout_token extraction: extractPrice() возвращает listing.hideout_token как hideoutToken.
  • /api/secure: прокси POST /api/trade2/whisper с JWT и полными куками — PoE возвращает code:2 (нужно быть в игре).
  • WS headers: wsHeaders() шлёт POESESSID+POETOKEN в Cookie, Origin, User-Agent, Cache-Control, Pragma. Без Accept, Content-Type, Referer, X-Requested-With.
  • PoE 2 Live WebSocket: URL wss://.../api/trade2/live/poe2/{league}/{qid}. Подтверждён кодом POEFlip (Swift, URLSessionWebSocketTask). Не требует пингов — PoE не шлёт пинг/понг, сервер дропает через ~10с (1006).

Rate limit (НОВОЕ)

  • Рейт-лимит PoE: возвращает HTTP 429 с {"error":{"code":3,"message":"Rate limit exceeded; Please wait N seconds before trying again."}}.
  • fetchRetry() переписана:
    • Читает wait N seconds из ответа и ждёт реальное время.
    • Если N > 300 (5 мин) — сразу кидает Rate limit: Ns. Подожди X мин...
    • Если N ≤ 300 — ждёт и ретраит (до 10 попыток).
    • На 5xx — exponential backoff до 60s.
    • Глобальный cooldown 1.2с между любыми запросами к PoE API.
  • curl.exe Cloudflare block: curl без cf_clearance получает Cloudflare 403/429. Node.js fetch() работает нормально.

Live mode (НОВОЕ)

  • Кнопка Live больше не виснет на "⏳": fetchItems() с начальными 200 ID вынесен ПОСЛЕ res.end(). Ответ приходит сразу, кача начальных предметов идёт в фоне.
  • SSE стрим: шлёт статусы (Live!, Cached N known items, ошибки).
  • Autoreconnect: exponential backoff (3s×1.5^attempt, max 30s), рефреш qid при 404.

Фронтенд

  • Double-click fix: кнопка Live дизейблится сразу на клик — ⏳ + Starting....
  • Secure button: fetch('/api/secure', {token}) вместо мёртвого poe2://.
  • Ошибки: отображаются в статус-баре (красный текст).
  • Sound: new Audio('/sound.mp3').play() вместо \x07.

Баги

  • CORS: переменная переименована headers→corsHeaders чтоб не затенять глобальную headers().
  • WS: убран пинг (PoE дропает сам), добавлен автоматический реконнект.
  • JSON parse on server: исправлена отправка Content-Length (предыдущий баг с curl был из-за отсутствия req.end()).

Как это работает

  1. Search → PoE API возвращает listing.hideout_token (JWT) только когда в запросе есть POESESSID + POETOKEN.
  2. User жмёт Secure → фронтенд шлёт POST /api/secure {token}.
  3. Сервер проксит POST /api/trade2/whisper {token} с полными куками.
  4. PoE API отвечает {"error":{"code":2,"message":"Your account must be in-game..."}} — ожидаемо, работает только в игре.
  5. Live: WS wss://.../api/trade2/live/poe2/{league}/{qid} + polling fallback 30s.

Известные проблемы

  • Рейт-лимит PoE (~1 req/s на аккаунт). При превышении — ждать N минут. После долгого тестирования может быть 25-30 мин.
  • WS дропается через ~10с (код 1006) — сервер PoE сам закрывает. Autoreconnect держит соединение. Если WS не взлетает (Cloudflare), работает polling раз в 30с.
  • curl.exe к PoE API не работает — Cloudflare блокирует. Только через Node.js fetch() или браузер.
  • cf_clearance кука в WS не передаётся — если Cloudflare начинает дропать WSS, переходим на polling.

Config

  • config.json: poeSessionId (POESESSID) + poeToken (POETOKEN JWT)
  • seen.json: cache of seen item IDs
  • Никакого startup.json — удалён, не нужен

Как запускать

# Full scan (консоль)
node scanner.mjs

# Serve mode (http://localhost:3999)
node scanner.mjs --serve

# Live mode (консоль)
node scanner.mjs --live

Ключевые файлы

  • scanner.mjs — main scanner + HTTP server (всё в одном)
  • config.json — настройки + авторизация
  • launch.vbs — скрытый запуск через полные пути
  • AGENTS.md — этот файл
  • sound.mp3 — звук уведомления

Сессионный ритуал

При старте сессии с агентом в первую очередь читать папку C:\Users\shama\Desktop\skills\pohuy\:

  • SKILL.md — базовый режим
  • references/slovar.md — словарь
  • references/sceny.md — шкала и сцены

Вести себя в стиле ultra-режима скилла pohuy (идиоматический русский мат, инженерная лексика, плотность ultra). Не сползать обратно в вежливость. Выключение: «нормальный режим» / «хватит материться».