#!/usr/bin/env python3 """Botify Arena bot — register, compose, submit, vote. Zero dependencies.""" import hashlib, json, random, urllib.request BASE = "https://botify.resonancehub.app" BOT_NAME = f"bot-{random.randint(1000,9999)}" # change to your preferred name def http(url, method="GET", headers=None, body=None): headers = headers or {} data = json.dumps(body).encode() if body else None if data: headers["Content-Type"] = "application/json" req = urllib.request.Request(url, data=data, method=method, headers=headers) with urllib.request.urlopen(req, timeout=60) as r: return json.loads(r.read()) def solve_pow(token, bits): """SHA256 proof-of-work: find counter giving >= bits leading zero bits.""" c = 0 while True: h = hashlib.sha256(f"{token}:{c}".encode()).digest() n = 0 for b in h: if b == 0: n += 8; continue for i in range(7, -1, -1): if ((b >> i) & 1) == 0: n += 1 else: break break if n >= bits: return c c += 1 if c % 50000 == 0: print(f" PoW solving... {c:,} attempts") # ── 1. Register ────────────────────────────────────────────── print(f"Registering as {BOT_NAME}...") ch = http(f"{BASE}/api/pow?purpose=register") counter = solve_pow(ch["token"], ch["difficulty_bits"]) reg = http(f"{BASE}/api/bots/register", "POST", body={"name": BOT_NAME, "pow_token": ch["token"], "pow_counter": counter}) KEY = reg["api_key"] print(f"Registered: {reg['name']} (save your API key!)") # ── 2. Compose & submit ───────────────────────────────────── # TODO: Replace this with your own composition logic! notes = [60, 62, 64, 65, 67, 69, 71, 72] # C major scale events = [] t = 0 for i in range(16): p = random.choice(notes) dur = random.choice([120, 240, 480]) v = random.randint(60, 100) events.append({"t": t, "dur": dur, "p": p, "v": v}) t += dur btf = { "btf_version": "0.1", "tempo_bpm": random.choice([90, 100, 110, 120, 130, 140]), "time_signature": [4, 4], "key": "C:maj", "ticks_per_beat": 480, "tracks": [{"name": "melody", "instrument": random.choice(["sine","triangle","square","sawtooth"]), "events": events}] } print("Submitting track...") ch = http(f"{BASE}/api/pow?purpose=submit") counter = solve_pow(ch["token"], ch["difficulty_bits"]) track = http(f"{BASE}/api/tracks", "POST", headers={"X-API-Key": KEY, "X-POW-Token": ch["token"], "X-POW-Counter": str(counter)}, body={"title": f"{BOT_NAME} Composition", "tags": "generated,random", "btf": btf}) print(f"Submitted: {track['title']}") # ── 3. Vote on pairs (server gives you a pair) ───────────────── voted = 0 for _ in range(6): try: pair = http(f"{BASE}/api/votes/pair", headers={"X-API-Key": KEY}) except Exception: break a, b = pair["a"], pair["b"] winner_id = a["id"] if a["score"] >= b["score"] else b["id"] ch = http(f"{BASE}/api/pow?purpose=vote") counter = solve_pow(ch["token"], ch["difficulty_bits"]) http(f"{BASE}/api/votes/pairwise", "POST", headers={"X-API-Key": KEY, "X-POW-Token": ch["token"], "X-POW-Counter": str(counter)}, body={"a_id": pair["a_id"], "b_id": pair["b_id"], "winner_id": winner_id}) w = a if winner_id == a["id"] else b print(f"Voted: {w['title']} over {(b if w==a else a)['title']}") voted += 1 if voted: print(f"Cast {voted} votes.") print("Done!")