- A room opened with Play now never loads /join: the API's answer to POST /api/rooms is counted as rooms opened here. - Link previews (Slack, Discord, Facebook, iMessage, WhatsApp and the rest) are reported as where the link was shared, since the people who click them arrive with no referrer. WhatsApp's fetcher is a bot now. - An address that asks for a scanner's paths, or keeps coming back without opening a game, is a bot's all day; so is a browser that loads pages at a steady interval from a new address each time, never playing. A declared bot is still judged request by request. - The site's own addresses, sslip.io included, are not referrers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
31 lines
1.5 KiB
Bash
Executable File
31 lines
1.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Nightly rollup: one JSON line per day in /var/lib/gamehall/rollup.jsonl,
|
|
# the hall's counts for that day (people, views, bots, referrers, campaigns,
|
|
# and the people sent on to each game here). Counts only: no addresses are
|
|
# kept, so the trend outlives the self-rotating access log.
|
|
# gamehall-rollup.sh [YYYY-MM-DD] (default: yesterday, UTC)
|
|
# Cron: /etc/cron.d/gamehall, installed by gamehall/deploy.sh.
|
|
set -u
|
|
OUT="/var/lib/gamehall/rollup.jsonl"
|
|
LOG="/var/log/gamehall/rollup.log"
|
|
DAY="${1:-$(date -u -d 'yesterday' +%Y-%m-%d)}"
|
|
mkdir -p "$(dirname "$OUT")" "$(dirname "$LOG")"
|
|
python3 - "$DAY" "$OUT" <<'PY' >> "$LOG" 2>&1
|
|
import datetime, json, os, sys
|
|
sys.path.insert(0, "/usr/local/lib/gamehall")
|
|
import traffic
|
|
day, out = sys.argv[1], sys.argv[2]
|
|
t = traffic.scan(day)
|
|
row = dict(day=day, people=len(t["addresses"]), views=t["views"], botAddresses=len(t["botAddresses"]),
|
|
scanners=t["scanners"], monitors=t["monitors"], sharedOn=dict(t["shared"]),
|
|
referrers=dict(t["referrers"]), campaigns=dict(t["campaigns"]), sent=t["sent"],
|
|
at=datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"))
|
|
rows = [json.loads(l) for l in open(out) if l.strip()] if os.path.exists(out) else []
|
|
rows = sorted([r for r in rows if r.get("day") != day] + [row], key=lambda r: r["day"])
|
|
with open(out + ".tmp", "w") as fh:
|
|
for r in rows:
|
|
fh.write(json.dumps(r) + "\n")
|
|
os.replace(out + ".tmp", out)
|
|
print("%s rolled: %d people, %d views" % (day, row["people"], row["views"]))
|
|
PY
|