Files
PuGa/puga/prunplanner.py
dodoxandClaude Sonnet 5 7a538cb300 Initial PuGa toolkit: data layer, econ, depth-aware scan, state sync, plan push
- puga/: cached FIO + PRUNplanner clients, market view with order-book walk,
  econ formulas ported from PRUNplanner (tested against its suite and live FIO),
  saturation model v1 (reviewed by Opus)
- tools/: scan (depth-aware), price, book, chain, state sync, plan_push
  (dry run default, [PuGa]-prefixed plans only), legacy prun_scan/prun_cxarb
- docs/: mechanics (PRUNplanner is source of truth), roadmap, decisions,
  saturation design, archived handoff
- secrets stay in .env (gitignored); ref/ holds PRUNplanner source (ignored)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-18 23:00:21 +02:00

37 lines
1.5 KiB
Python

"""api.prunplanner.org. Public data endpoints need no auth; planning endpoints use `Authorization: Api-Key <key>`."""
from .cache import get_json
from . import config
BASE = "https://api.prunplanner.org"
MARKET, STATIC = 15 * 60, 24 * 3600
def _g(path: str, ttl: int, refresh: bool = False):
return get_json(BASE + path, ttl, refresh=refresh)
def exchanges(refresh=False):
"""Per ticker.CX: ask/bid/supply/demand, vwap_daily/7d/30d, traded_daily, sum/avg_traded_7d/30d, exchange_status."""
return _g("/data/exchanges/", MARKET, refresh)
def materials(refresh=False): return _g("/data/materials/", STATIC, refresh)
def recipes(refresh=False): return _g("/data/recipes/", STATIC, refresh)
def buildings(refresh=False): return _g("/data/buildings/", STATIC, refresh)
def api_key() -> str | None:
return config.get("PRUNPLANNER_API_KEY")
def request(method: str, path: str, body: dict | None = None):
"""Authenticated call (Api-Key). Callers must enforce write guardrails (see tools/plan_push.py)."""
import json, urllib.request
key = api_key()
if not key:
raise RuntimeError("PRUNPLANNER_API_KEY missing in .env")
data = json.dumps(body).encode() if body is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method, headers={
"Authorization": "Api-Key " + key, "Content-Type": "application/json", "User-Agent": "PuGa/0.1"})
with urllib.request.urlopen(req, timeout=60) as r:
raw = r.read()
return json.loads(raw) if raw else None