da5a36e8add2544edb9d92c2692d1a2003ced412
- pokemon_location_fetcher.py:DEFAULT_URL/TOKEN 改走 os.getenv,並補 load_dotenv() 讓 fetch_and_upload.sh 能從 .env 取值 - run_pokemon_radar_api.sh:POKER_* 改為可由環境覆蓋(實務上未被 API 使用,保留結構) - pyproject.toml:補宣告 python-dotenv(專案已使用但原本未列) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 抓資料 → 篩選 → 寫入 Redis(SETEX,預設 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 |
生產環境 cron:以 flock 鎖定,呼叫舊 CLI產 pokemon_data.json 後 scp 到 192.168.42.104:/opt/caddy/www/pokemon/spots.json |
run_pokemon_radar_api.sh |
啟動 FastAPI(uvicorn,port 8008)的 shell 腳本 |
state.json |
twpkinfo.com 登入後的 cookies / localStorage / UA / langs 快照,注入到 MJS 繞人機驗證 |
logging.ini |
uvicorn 的 logging 設定 |
執行指令
全部以 uv 跑(Python 3.12,見 .python-version、pyproject.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 |
localhost(fetcher)/ 192.168.42.211(API、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 篩選後回傳。永遠回 200,Redis 連不上或空資料都回空陣列,不會 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 |
含 notes(MJS 輸出)、redis_ttl、note(錯誤訊息) |
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 |
| 型別 | String(JSON) |
| TTL | REDIS_TTL(預設 300s) |
| Writer | radar_fetcher.py |
| Readers | pokemon_radar_api.py、reader.py、check_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" }
}
Description
Languages
Python
70.4%
JavaScript
25.4%
Shell
4.2%