Files
pokemon-radar-api/README.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

5.5 KiB
Raw Blame History

pokemon-radar-api

把 twpkinfo.com 的寶可夢雷達資料包成 Redis-backed 的 HTTP API給前端 / n8n 呼叫。

  • 上手操作:QUICKSTART.md
  • 設計脈絡與演進:SUMMARY.md
  • Claude Code 指引:CLAUDE.md

本檔為參考手冊組件一覽、指令、環境變數、HTTP API、Redis schema。


組件

檔案 角色
radar_fetcher.py 現行 fetcher:呼叫 Function Server 抓資料 → 篩選 → 寫入 RedisSETEX,預設 TTL 300s
pokemon_radar_api.py FastAPI 服務:8008/ping/scan;從 Redis 讀取,依 request 參數即時二次篩選
twpk_radar.mjs Function Server 上跑的 Puppeteer worker負責開瀏覽器拉 twpkinfo.com/ipoke.aspx 的資料
pokemon_location_fetcher.py 舊版 CLI:直接呼叫 Function Server輸出本地 pokemon_data.{json,csv} + screenshot.png。API 仍重用它的 PokemonRadarClient.postprocess 做二次篩選
pokemon_radar_example.py 舊 CLI 的 Python 範例程式(非 CLI argparse 介面)
reader.py 從 Redis 讀取並用 rich 表格顯示目前快取內容
check_redis.py 從 Redis 讀取並 dump 原始 JSON
fetch_and_upload.sh 生產環境 cronflock 鎖定,呼叫舊 CLIpokemon_data.jsonscp192.168.42.104:/opt/caddy/www/pokemon/spots.json
run_pokemon_radar_api.sh 啟動 FastAPIuvicornport 8008的 shell 腳本
state.json twpkinfo.com 登入後的 cookies / localStorage / UA / langs 快照,注入到 MJS 繞人機驗證
logging.ini uvicorn 的 logging 設定

執行指令

全部以 uvPython 3.12,見 .python-versionpyproject.toml)。

目的 指令
啟動 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寫入 Redis uv run python radar_fetcher.py
跑舊 CLI輸出本地檔案 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.py
查 Redis 內容raw JSON uv run python check_redis.py
生產排程(含 scp 上傳) ./fetch_and_upload.sh

本專案沒有 test / lint / build 流程。

環境變數(.env

變數 預設 誰用 說明
FUNCTION_URL http://192.168.42.124:13000/function radar_fetcher Function Server endpoint
FUNCTION_TOKEN (必填) radar_fetcher 未設會直接 raise
SCRIPT_PATH twpk_radar.mjs radar_fetcher JS worker 檔名
STATE_PATH state.json radar_fetcher 登入狀態快照路徑
UA_FROM_STATE true radar_fetcher 是否從 state 帶 UA / langs
RADAR_LAT / RADAR_LNG 25.0478 / 121.5170 radar_fetcher 掃描中心座標
RADAR_ZOOM 11 radar_fetcher 地圖縮放
RADAR_SHOT false radar_fetcher 是否擷取畫面base64
MIN_REMAINING 300 radar_fetcher 剩餘秒數門檻
MIN_IV radar_fetcher IV% 下限
PERFECT_ONLY false radar_fetcher 只保留 100% IV
SPECIES radar_fetcher 逗號分隔的 dex id 或名稱關鍵字(例:133,伊布
HTTP_TIMEOUT 160 radar_fetcher 呼叫 Function Server 的 HTTP timeout
REDIS_HOST localhostfetcher/ 192.168.42.211API、reader 全部 注意兩邊預設不同,統一在 .env 指定
REDIS_PORT 6379 全部
REDIS_DB 0 全部
REDIS_PASSWORD 全部 空字串視為無密碼
REDIS_TTL 300 radar_fetcher 寫入 TTL
REDIS_KEY pokemon:radar:latest 全部

HTTP API

GET /ping

200 → {"status":"ok","backend":"redis"}

POST /scan

從 Redis 讀取目前快取,依 body 篩選後回傳。永遠回 200Redis 連不上或空資料都回空陣列,不會 500。

Request body

欄位 型別 說明
lat, lng, zoom, shot, state_path, ua_from_state, save_files 相容性欄位Redis 模式下忽略
min_remaining int ≥ 0 剩餘秒數下限
min_iv int 0-100 IV% 下限
perfect_only bool 只保留 100% IV
species str 逗號分隔 dex id 或名稱關鍵字

Response

欄位 說明
source "redis" / "redis (empty)" / "redis (unreachable)"
ttl Redis key 剩餘秒數
count_raw Redis 內筆數
count_filtered 經 request 參數篩選後筆數
items 物件陣列,見下
debug notesMJS 輸出)、redis_ttlnote(錯誤訊息)

items[] 欄位 id / name / gender / remaining / expire_time / expire_at / latitude / longitude / iv_pct / iv_atk / iv_def / iv_sta / cp / level / is_perfect / fast_move / charge_move

Redis schema

項目
Key pokemon:radar:latest
型別 StringJSON
TTL REDIS_TTL(預設 300s
Writer radar_fetcher.py
Readers pokemon_radar_api.pyreader.pycheck_redis.py

Value 結構

{
  "source": "fetcher",
  "generated_at": "2026-04-20T09:06:36+08:00",
  "count_raw": 120,
  "count_filtered": 79,
  "items": [ /* 同上方 items[] */ ],
  "debug": { "notes": ["..."], "api_source": "Fresh from Function Server" }
}