Skip to content

fix(steam-sniper): URL slug authoritative resolver (Tiger Tooth → Scorched fix)#52

Merged
NickStr11 merged 1 commit intomainfrom
claude/sad-tesla-40593c
May 5, 2026
Merged

fix(steam-sniper): URL slug authoritative resolver (Tiger Tooth → Scorched fix)#52
NickStr11 merged 1 commit intomainfrom
claude/sad-tesla-40593c

Conversation

@NickStr11
Copy link
Copy Markdown
Owner

Summary

  • Главный фикс: URL slug приоритезирован над DOM-именем в /api/lists. Решает Лёхин баг "добавляю Tiger Tooth — попадает Scorched" (карусели похожих скинов в DOM путали getItemName()).
  • Extension v1.5: 8s timeout вместо silent void; toast показывает канонический name от сервера.
  • Cases double-list: in-flight lock в toggleListItem (палиатив, ждём логи на повтор жалобы).
  • Observability: лог DOM/URL mismatch + лог каждого Steam-API fallback (по фидбэку Codex).

Что изменено

Файл Что
tools/steam-sniper/server.py _slug_to_name индекс (3 формы slug на item: generated + URL-encoded + URL-decoded), _resolve_from_source_url, Шаг 0 в /api/lists, WARNING-логи на mismatch + Steam-API fallback
tools/steam-sniper/extension/{background,content,manifest}.js timeout 8s через AbortController, canonical name в toast/PATCH, bump 1.4→1.5
tools/steam-sniper/static/js/lists.js _inFlight lock на toggleListItem
tools/steam-sniper/tests/test_source_url_resolution.py 17 кейсов, главный регресс test_tiger_tooth_url_resolves_to_tiger_tooth

Smoke на production (уже задеплоено)

POST /api/lists item_name="★ Karambit | Scorched" + URL=tiger-tooth-factory-new/
→ "★ Karambit | Tiger Tooth (Factory New)" via source_url ✓

Что НЕ сделано (по решению пользователя)

  • Steam-API fallback ослабить — оставлен log-only. Решение по refuse'у — после недели наблюдения логов.
  • Cases policy "в один список" — ждём серверных логов на повтор жалобы, чтобы определить кто шлёт левый list_type (UI или event-double-fire).
  • Security findings (CORS *, /api без auth, HTTP) — deferred пока инструмент использует только Лёха+Никита.

Test plan

  • uv run pytest tests/133/133 passed (16 новых тестов на slug resolver, 1 на decoded variant)
  • Pre-commit hook прогнал тесты + secrets + lint автоматом
  • Production smoke: encoded URL (%E2%98%85-...) и decoded URL (★-...) — оба резолвятся в canonical name
  • Production smoke: DOM шлёт левое имя — URL побеждает, resolved_via: "source_url"
  • Лёхе передан extension v1.5 zip → проверить добавление 5+ ножей подряд (включая Tiger Tooth, Scorched, Glock-18 Water Elemental)

🤖 Generated with Claude Code

…Tooth → Scorched' skin mix-up

Лёхин feedback по extension v1.4: при добавлении ножей через расширение
вместо Tiger Tooth попадал Scorched (та же модель, другой скин). Stволы
аналогично. Из всех ножей только 1-2 добавились правильно.

Корень: extension шлёт item_name парсенный из DOM h1, но lis-skins-страницы
содержат карусели похожих скинов — первый h1 с wear-маркером может быть
related-item, а не главный. Сервер доверял DOM-имени, exact-match'ил его
в каталоге и писал левый скин. URL же всегда правильный.

Фикс — приоритезировать URL slug над DOM-именем в /api/lists:

- _slugify_name(): генерирует канонический slug из имени каталога
  (drops ★/™, lowercase, non-alphanumeric → dash)
- _slug_from_source_url(): извлекает последний path-сегмент URL
- _rebuild_slug_index(): индексирует 3 формы slug на каждый item:
    1. generated (ASCII-only fallback)
    2. lis-skins-provided URL slug (percent-encoded — authoritative)
    3. URL-decoded variant (если location.href декодирован браузером)
- _resolve_from_source_url(): O(1) lookup, возвращает canonical name
- /api/lists добавлен Шаг 0 — URL-резолвер выше DOM-резолва
- WARNING лог при DOM/URL mismatch — диагностика когда DOM врёт

Дополнительно:

- extension/background.js: 8s timeout через AbortController + явное
  сообщение "сервер не ответил, проверь дашборд" вместо silent void
- extension/content.js: toast показывает canonical name из ответа сервера
  ("Добавлено → ★ Karambit | Tiger Tooth (Field-Tested)") — юзер видит
  что улетело до закрытия страницы; PATCH таргета идёт по canonical name
- extension manifest: bump 1.4 → 1.5
- static/js/lists.js: in-flight lock в toggleListItem — палиатив против
  дубль-кликов на cases-карточках с двумя toggle-кнопками
- _resolve_item_name: WARNING лог на каждый Steam-API fallback (по фидбэку
  Codex) — observability для решения нужно ли refuse'ать вместо silent
  first-match. Время + chosen hash_name + resolved name.
- /api/lists endpoint: structured лог received → resolve path → resolved

Тесты: tests/test_source_url_resolution.py — 17 кейсов, главный регресс
test_tiger_tooth_url_resolves_to_tiger_tooth (URL Tiger Tooth + DOM Scorched
→ Tiger Tooth). Encoded/decoded slug variants. StatTrak namespace isolation.
133/133 passed.

Smoke на проде:
  POST /api/lists item_name="★ Karambit | Scorched" + URL=tiger-tooth/
  → "★ Karambit | Tiger Tooth (Factory New)" via source_url ✓

Не сделано (осознанно):
- Steam-API fallback оставлен по поведению (только лог) — после URL-резолвера
  он хитится только для items не в каталоге; решение по refuse — после
  недели наблюдения логов
- Cases policy "в один список" — ждём serverных логов на повтор жалобы
  чтобы понять кто шлёт левый list_type (UI или event-double-fire)
- Security findings (CORS, /api без auth, HTTP) остаются deferred —
  юзер использует только с Лёхой

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NickStr11 NickStr11 merged commit b970aa5 into main May 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant