Files
pokemon-radar-api/CLAUDE.md
Timmy f7ef105436 init: Redis-backed Pokémon 雷達 API
- radar_fetcher.py:呼叫 Function Server 抓 twpkinfo.com 資料後寫入 Redis (TTL 300s)
- pokemon_radar_api.py:FastAPI /scan,從 Redis 讀取並依 request 即時二次篩選;Redis 不可用時回 200 空結果,不再 500
- pokemon_location_fetcher.py:舊版 CLI,仍由 fetch_and_upload.sh 使用
- 文件:README (參考手冊)、QUICKSTART (操作指南)、SUMMARY (故事線)、CLAUDE.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 09:13:59 +08:00

4.5 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

常用指令

套件管理使用 uv(見 pyproject.tomluv.lock.python-version = 3.12)。所有 Python 進入點都透過 uv run 執行。

  • 啟動 API./run_pokemon_radar_api.sh(內含 uv run uvicorn pokemon_radar_api:app --host 0.0.0.0 --port 8008 --log-config logging.ini
  • 執行新版 fetcher寫入 Redisuv run python radar_fetcher.py
  • 執行舊版 fetcher產生本地 JSON/CSV/截圖)uv run python pokemon_location_fetcher.py --script twpk_radar.mjs --lat 25.0478 --lng 121.5170 --zoom 16 --state state.json --ua-from-state --min-remaining 300 --min-iv 90
  • 檢視 Redis 快取內容uv run python reader.pyrich 表格)或 uv run python check_redis.pyraw JSON dump
  • 生產環境排程腳本./fetch_and_upload.sh(使用 flock 鎖定 /var/lock/poke_radar.lock;呼叫舊版 pokemon_location_fetcher.py,然後 scp192.168.42.104:/opt/caddy/www/pokemon/spots.json

本專案沒有測試、linter、build 流程。

架構

這是一個兩階段的 pipeline被一個 FastAPI 即時查詢層所包裝。有兩條共存的 fetch pipeline,修改時務必了解各自的用途:

資料流

twpkinfo.com (ipoke.aspx)
      ▲
      │ browser automation (Puppeteer)
      │
Function Server (192.168.42.124:13000/function)
      ▲
      │ POST {code: <injected twpk_radar.mjs>}, 150s timeout
      │
┌─────┴─────────────────────────────┐
│                                   │
│ (Pipeline A寫入 Redis)          │  (Pipeline B寫入本地檔)
│ radar_fetcher.py                  │  pokemon_location_fetcher.py (CLI)
│  └─→ Redis SETEX                  │   └─→ pokemon_data.{json,csv}
│       pokemon:radar:latest        │       + screenshot.png
│       TTL 300s                    │
└─────┬─────────────────────────────┘
      │
      ▼
pokemon_radar_api.py (FastAPI, :8008)
  POST /scan → 即時篩選 Redis 內容回傳

關鍵設計

  • twpk_radar.mjs 是 Function Server 上跑的 worker不是本地執行的模組。Python 端透過 regex 在字串層級注入變數,這個契約不能壞:

    • const TARGET = {...}; → 由 _inject_target_and_shot 覆寫
    • const DO_SCREENSHOT = true|false; → 同上
    • globalThis.__POKE_STATE__ → 由 _inject_state 前置插入(含 cookies/localStorage/UA/langs
    • 修 MJS 時,上述 3 個錨點的形狀必須維持,否則 regex 會失效
  • pokemon_radar_api.py 重用舊 client 的 postprocess 方法,但透過它去抓資料:_filter_helper = PokemonRadarClient(url="", token="")。Redis 存的是已篩選過一次(由 fetcher但仍保留較寬原始集的資料API 再依 request 參數做即時二次篩選(min_remaining / min_iv / perfect_only / species)。ScanRequest 裡的 lat/lng/zoom/shot/... 欄位在 Redis 模式下是忽略的,純粹保留給前端/n8n 相容。

  • 兩個 fetcher 的篩選邏輯重複實作了兩次radar_fetcher._postprocessPokemonRadarClient.postprocess),修改篩選規則時要同步兩邊。

  • fetch_and_upload.sh 目前走的是 Pipeline B本地檔 + scp不是 Pipeline ARedis。這是生產環境仍在使用的路徑;若改 fetcher 行為要確認影響哪一邊。

設定

  • .env(本地)驅動 radar_fetcher.pypokemon_radar_api.pyreader.pycheck_redis.py。注意 radar_fetcher.py 預設 REDIS_HOST=localhost,但 API / reader / .env192.168.42.211 — fetcher 跑在 Redis 本機、API 跑遠端。
  • state.json 是使用者登入後的 cookies/localStorage/UA 快照;用於繞過 twpkinfo.com 的人機驗證。過期時整條 pipeline 會靜默產 0 筆。radar_fetcher._postprocess 有一個診斷:當 raw_items 非空但篩完為 0 時會 log remaining/perfect 的分佈,優先看這個。
  • FUNCTION_TOKEN 必填radar_fetcher 會直接 raise舊 CLI 則有 hard-coded default 6R0W53R135510

專案慣例

  • 全專案以**繁體中文(台灣用語)**溝通與註解。
  • log 訊息不要使用 emoji現存檔案中的 emoji 是歷史遺留,新寫或修改時改成純文字。
  • repo 根目錄的 *_BACKUP_YYYYMMDDHHMMSS 檔案是舊備份,可以清掉。