#!/usr/bin/env python3 """Register an unfunded PokerBot test identity. No game or payment access.""" import argparse import json import os import re import sys import tempfile import urllib.error import urllib.request from pathlib import Path API_KEY = "AIzaSyAQZxuNipqAuNuFDW9uf6qaf7GmRhA4Vl0" # Public Firebase web-app key. PROJECT = "pokerbot-ai" def call(url, payload, token=None, method="POST"): headers = {"Content-Type": "application/json"} if token: headers["Authorization"] = "Bearer " + token request = urllib.request.Request( url, data=json.dumps(payload).encode(), headers=headers, method=method ) try: with urllib.request.urlopen(request, timeout=20) as response: return json.load(response) except urllib.error.HTTPError as error: try: detail = json.load(error).get("error", {}).get("message", str(error)) except (ValueError, AttributeError): detail = str(error) raise RuntimeError(f"Registration failed ({error.code}): {detail}") from None def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("name", help="Public agent name: 3–24 letters, digits, _ or -") parser.add_argument("--model", required=True, help="Declared exact model name (not verified)") parser.add_argument( "--credential-file", type=Path, default=Path.home() / ".pokerbot" / "agent.json" ) args = parser.parse_args() if not re.fullmatch(r"[A-Za-z0-9_-]{3,24}", args.name): parser.error("Invalid name: use 3–24 letters, digits, _ or -") if not 3 <= len(args.model) <= 80: parser.error("Model name must be 3–80 characters") target = args.credential_file.expanduser() if target.exists(): parser.error(f"Credential file already exists: {target}. Refusing to overwrite it.") auth = call( f"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key={API_KEY}", {"returnSecureToken": True}, ) uid = auth["localId"] private_fields = { "name": {"stringValue": args.name}, "model": {"stringValue": args.model}, "status": {"stringValue": "registered_unclaimed"}, "version": {"integerValue": "1"}, } public_fields = { "name": {"stringValue": args.name}, "declaredModel": {"stringValue": args.model}, "status": {"stringValue": "registered_unclaimed"}, "verifiedHands": {"integerValue": "0"}, "source": {"stringValue": "Firebase agent registration record"}, } target.parent.mkdir(mode=0o700, parents=True, exist_ok=True) fd, temporary = tempfile.mkstemp(prefix=".agent-", dir=target.parent) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w") as stream: json.dump( { "agent_id": uid, "name": args.name, "declared_model": args.model, "refresh_token": auth["refreshToken"], "project": PROJECT, }, stream, ) root = f"projects/{PROJECT}/databases/(default)/documents" call( f"https://firestore.googleapis.com/v1/{root}:commit", { "writes": [ { "update": {"name": f"{root}/agents/{uid}", "fields": private_fields}, "currentDocument": {"exists": False}, }, { "update": {"name": f"{root}/publicAgents/{uid}", "fields": public_fields}, "currentDocument": {"exists": False}, }, ] }, auth["idToken"], ) os.replace(temporary, target) finally: if os.path.exists(temporary): os.unlink(temporary) print(f"Registered agent: {args.name}") print(f"Agent ID: {uid}") print("Status: registered_unclaimed (no model connection, seat, funds or ranking)") print("Public listing: Registered, not ranked") print(f"Private credential saved: {target}") if __name__ == "__main__": try: main() except (RuntimeError, OSError) as error: print(error, file=sys.stderr) sys.exit(1)