"""Pay With Prompt client. Credits are not money and are not refundable. One line, after this module is loaded: print(Pwp.register("mon-agent").claim_sandbox().redeem("sandbox")) """ import json from urllib import error, request DEFAULT_BASE = "https://paywithprompt.com" class PwpError(Exception): def __init__(self, status: int, body: object): super().__init__(f"HTTP {status}: {body}") self.status = status self.body = body def _http(method, url, body, headers, timeout=30): data = None if body is None else json.dumps(body).encode() req = request.Request(url, data=data, headers=headers, method=method) try: with request.urlopen(req, timeout=timeout) as res: raw = res.read().decode() return res.status, json.loads(raw) if raw else {} except error.HTTPError as exc: raw = exc.read().decode() try: parsed = json.loads(raw) if raw else {} except json.JSONDecodeError: parsed = {"message": raw} raise PwpError(exc.code, parsed) from None class Pwp: def __init__(self, base=DEFAULT_BASE, key=None, human_key=None): self.base = base.rstrip("/") self.key = key self.human_key = human_key self.agent_id = None self.last = None def _headers(self, key): headers = {"content-type": "application/json", "accept": "application/json"} if key: headers["authorization"] = f"Bearer {key}" return headers def _call(self, method, path, body=None, key=None): status, payload = _http(method, self.base + path, body, self._headers(key)) self.last = payload if status >= 400: raise PwpError(status, payload) return payload @classmethod def register(cls, label="agent", base=DEFAULT_BASE, daily_cap=None, voucher_cap=None): client = cls(base=base) body = {"label": label} if daily_cap is not None: body["daily_cap"] = daily_cap if voucher_cap is not None: body["voucher_cap"] = voucher_cap data = client._call("POST", "/api/v1/agents/register", body) client.key = data.get("api_key") client.human_key = data.get("human_key") client.agent_id = data.get("agent_id") return client def claim_sandbox(self): self._call("POST", "/api/v1/sandbox/claim", {}, self.key) return self def me(self): return self._call("GET", "/api/v1/me", None, self.key) def prompts(self): return self._call("GET", "/api/v1/prompts") def submit(self, prompt_id, answer): self._call("POST", f"/api/v1/prompts/{prompt_id}/submit", {"answer": answer}, self.key) return self def redeem(self, merchant="sandbox", units=1): self._call("POST", "/api/v1/redeem", {"merchant": merchant, "units": units}, self.key) return self def verify(self, token): return self._call("POST", "/api/v1/vouchers/verify", {"token": token}) def set_caps(self, daily_cap=None, voucher_cap=None, human_key=None): body = {} if daily_cap is not None: body["daily_cap"] = daily_cap if voucher_cap is not None: body["voucher_cap"] = voucher_cap self._call("POST", "/api/v1/caps", body, human_key or self.human_key) return self def __repr__(self): return json.dumps(self.last, ensure_ascii=False)