Godstrument/workers/world_wiki.py
monsterrobotparty 8deb65b4fe Godstrument: a multi-modal sensor-fusion instrument
Everything — your hand, the room, a satellite, the markets, the sky — becomes an
OSC control signal fused through a modulation matrix. Includes:
- hub + normalize (One-Euro) + matrix (curves/gates/quantize) + transform (tweaks/groups)
- 20+ workers: sim sensors, 8 keyless world feeds, ephemeris/almanac/clock (computed),
  time-warp replay (quakes/weather/db), and the dealgod market warehouse feed
- planetary orbital LFOs, SQLite recorder, city targeting
- live browser console: mute, group macros, drag-to-patch, inspector, Web MIDI

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 02:13:05 +10:00

107 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Every human edit to Wikipedia on Earth, right now, as one live pulse.
The Wikimedia recentchange SSE firehose is a chaotic global stream of edits;
each edit's byte-delta becomes a percussive glitch and the edits/sec is a
breathing tempo — the collective heartbeat of humanity writing itself down.
"""
import argparse
import json
import time
import urllib.request
from collections import deque
from pythonosc.udp_client import SimpleUDPClient
STREAM_URL = "https://stream.wikimedia.org/v2/stream/recentchange"
USER_AGENT = "Godstrument/1.0 (live instrument; monsterrobotparty@gmail.com)"
MAX_EVENTS_PER_SEC = 30 # throttle emitted /event messages
RATE_EMIT_INTERVAL = 1.0 # emit /gs/wiki/rate about once per second
RATE_WINDOW = 5.0 # rolling window (s) for edits-per-second
def run(host, port):
client = SimpleUDPClient(host, port)
print(f"[world_wiki] emitting /gs/wiki/... every ~1s", flush=True)
backoff = 1.0
# rolling timestamps of ALL counted edits (for edits-per-second)
edit_times = deque()
# timestamps of emitted /event messages within the current second (throttle)
emit_window = deque()
last_rate_emit = time.monotonic()
while True:
try:
req = urllib.request.Request(STREAM_URL, headers={"User-Agent": USER_AGENT})
with urllib.request.urlopen(req, timeout=60) as resp:
backoff = 1.0 # connected cleanly, reset backoff
for raw in resp:
line = raw.decode("utf-8", "replace").rstrip("\n")
# SSE: a "data: " line carries the JSON payload.
if line.startswith("data: "):
payload = line[6:]
try:
change = json.loads(payload)
except (ValueError, TypeError):
continue
if change.get("type") in ("edit", "new"):
length = change.get("length") or {}
new = length.get("new")
old = length.get("old")
if new is not None and old is not None:
edit_size = abs(int(new) - int(old))
else:
edit_size = 0
now = time.monotonic()
edit_times.append(now)
# Throttle emitted events to ~MAX_EVENTS_PER_SEC.
while emit_window and now - emit_window[0] >= 1.0:
emit_window.popleft()
if len(emit_window) < MAX_EVENTS_PER_SEC:
try:
client.send_message("/gs/wiki/edit/event", float(edit_size))
emit_window.append(now)
except OSError as exc:
print(f"[world_wiki] OSC send failed: {exc}", flush=True)
# A blank line ends an SSE event; use this beat to
# trim the rolling window and emit the rate.
now = time.monotonic()
while edit_times and now - edit_times[0] >= RATE_WINDOW:
edit_times.popleft()
if now - last_rate_emit >= RATE_EMIT_INTERVAL:
span = min(RATE_WINDOW, max(now - last_rate_emit, 1e-6))
rate = len(edit_times) / span if edit_times else 0.0
try:
client.send_message("/gs/wiki/rate", float(rate))
except OSError as exc:
print(f"[world_wiki] OSC send failed: {exc}", flush=True)
last_rate_emit = now
# Stream ended without error; loop to reconnect.
print("[world_wiki] stream closed, reconnecting...", flush=True)
except Exception as exc: # noqa: BLE401 — never die on a transient error
print(f"[world_wiki] stream error: {exc}; retrying in {backoff:.0f}s", flush=True)
time.sleep(backoff)
backoff = min(backoff * 2, 30.0)
def main():
parser = argparse.ArgumentParser(description="Wikipedia recentchange SSE -> OSC")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=9000)
args = parser.parse_args()
run(args.host, args.port)
if __name__ == "__main__":
main()