Reports are threads, and every turn of one rings the desk's bell
A player answers the desk under its reply from their lobby, proven by the seat the report was filed from; the lobby shows the exchange in order and says whose word is pending. A new report, a player's answer, and a desk reply each raise a Sentry issue on the keeper's phone — the first two from the server, the last from the reply script itself, straight to Sentry from the droplet. The Desktop digest lists the answers, and the desk's rule reads a report as reopened when the last word is the player's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
ffbca5bfb9
commit
11e9f950c6
@@ -17,3 +17,20 @@ console.log(JSON.stringify({
|
||||
text: process.env.TEXT,
|
||||
}));')
|
||||
printf '%s\n' "$LINE" | ssh "root@$HOST" 'cat >> /var/lib/wizwar/feedback.jsonl && tail -1 /var/lib/wizwar/feedback.jsonl'
|
||||
# The desk's bell rings for the reply too, so Eric sees the exchange move:
|
||||
# an event straight to Sentry from the droplet, with the DSN the service holds.
|
||||
ssh "root@$HOST" "REPORT_ID='$REPORT_ID' STATUS='$STATUS' TEXT=\"\$(cat)\" python3 - <<'PY'
|
||||
import json, os, re, uuid, urllib.request, datetime
|
||||
svc = open('/etc/systemd/system/wizwar.service').read()
|
||||
m = re.search(r'SENTRY_DSN=https://([0-9a-f]+)@([^/]+)/(\\d+)', svc)
|
||||
if not m: raise SystemExit(0)
|
||||
key, host, project = m.groups()
|
||||
text = os.environ['TEXT']; rid = os.environ['REPORT_ID']; status = os.environ['STATUS']
|
||||
event = {'event_id': uuid.uuid4().hex, 'timestamp': datetime.datetime.now(datetime.UTC).isoformat(), 'level': 'error', 'platform': 'other',
|
||||
'message': {'formatted': f'Desk replies on report {rid} ({status}): {text[:100]}'}, 'fingerprint': ['report-reply', rid, datetime.datetime.now(datetime.UTC).isoformat()],
|
||||
'tags': {'report': rid, 'status': status}, 'extra': {'text': text}}
|
||||
body = json.dumps({'event_id': event['event_id'], 'sent_at': event['timestamp']}) + '\\n' + json.dumps({'type': 'event'}) + '\\n' + json.dumps(event)
|
||||
req = urllib.request.Request(f'https://{host}/api/{project}/envelope/', data=body.encode(), headers={'Content-Type': 'application/x-sentry-envelope', 'X-Sentry-Auth': f'Sentry sentry_version=7, sentry_client=wizwar-desk/1, sentry_key={key}'})
|
||||
try: urllib.request.urlopen(req, timeout=10); print('bell rung')
|
||||
except Exception as e: print('bell failed:', e)
|
||||
PY" <<< "$TEXT"
|
||||
|
||||
@@ -20,7 +20,7 @@ for raw in open(os.path.join(out, "feedback.jsonl"), encoding="utf8"):
|
||||
r = reports.get(line["reportId"])
|
||||
if not r: continue
|
||||
if "image" in line: r["image"] = line["image"]
|
||||
else: r.setdefault("replies", []).append(line)
|
||||
else: r.setdefault("replies", []).append(line) # desk replies and player answers alike, in order
|
||||
continue
|
||||
rid = line.get("id") or line.get("at")
|
||||
reports[rid] = dict(line, replies=[]); order.append(rid)
|
||||
@@ -33,8 +33,9 @@ for rid in reversed(order):
|
||||
if r.get("expected","").strip(): lines.append(f"**What they expected:** {r['expected'].strip()}")
|
||||
if r.get("image"): lines.append(f"**Picture:** ![{r['image']}](images/{r['image']})")
|
||||
for rep in r["replies"]:
|
||||
lines.append(f"> **{rep.get('status','')}** ({rep.get('at','')[:16].replace('T',' ')}): {rep.get('text','').strip()}")
|
||||
if not r["replies"]: lines.append("> _unanswered_")
|
||||
who = f"{r.get('player','the player')} answers" if rep.get("from") == "player" else f"**{rep.get('status','')}**"
|
||||
lines.append(f"> {who} ({rep.get('at','')[:16].replace('T',' ')}): {rep.get('text','').strip()}")
|
||||
if not r["replies"] or r["replies"][-1].get("from") == "player": lines.append("> _awaiting the desk_")
|
||||
lines.append("")
|
||||
open(os.path.join(out, "reports.md"), "w", encoding="utf8").write("\n".join(lines))
|
||||
print(f"{len(order)} reports, {sum(1 for r in reports.values() if r.get('image'))} with pictures -> {out}/reports.md")
|
||||
|
||||
Reference in New Issue
Block a user