Traffic counts what matters: rooms opened from the site, where links were shared, scanners and monitors as bots
- 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
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
cc71ee4421
commit
151d82e747
+6
-44
@@ -25,50 +25,12 @@ print("live sockets: %s | rooms touched in the last hour: %s" % (
|
||||
sh("find /var/lib/waving-hands/rooms -name '*.jsonl' -mmin -60 2>/dev/null | wc -l")))
|
||||
|
||||
# --- traffic: Caddy's access log, people and bots apart ---
|
||||
BOT = re.compile(r"bot|crawl|spider|slurp|facebookexternalhit|preview|fetch|curl|python|go-http|headless|scan|monitor|uptime", re.I)
|
||||
PAGES = {"/": "hall", "/play": "play", "/rules": "rules"}
|
||||
addresses, bots = set(), set()
|
||||
pages, joins, referrers, campaigns, agents = Counter(), Counter(), Counter(), Counter(), Counter()
|
||||
requests = 0
|
||||
for path in sorted(glob.glob("/var/lib/caddy/waving-hands-access*.log*")):
|
||||
try:
|
||||
with open(path) as f:
|
||||
for line in f:
|
||||
try:
|
||||
x = json.loads(line)
|
||||
except Exception:
|
||||
continue
|
||||
ts = datetime.datetime.fromtimestamp(x["ts"], datetime.timezone.utc)
|
||||
if ts.strftime("%F") != day:
|
||||
continue
|
||||
req = x["request"]
|
||||
ua = " ".join(req.get("headers", {}).get("User-Agent", [""]))
|
||||
ip = req.get("remote_ip") or req.get("client_ip", "?")
|
||||
uri = req.get("uri", "")
|
||||
path_only = uri.split("?")[0]
|
||||
if BOT.search(ua) or not ua:
|
||||
bots.add(ip)
|
||||
continue
|
||||
if path_only.startswith("/_app/") or path_only.startswith("/api/") or path_only == "/ws" or path_only.endswith((".png", ".ico", ".txt")):
|
||||
continue
|
||||
requests += 1
|
||||
addresses.add(ip)
|
||||
if path_only in PAGES:
|
||||
pages[PAGES[path_only]] += 1
|
||||
elif path_only.startswith("/join/"):
|
||||
joins[path_only.split("/")[2].upper()] += 1
|
||||
ref = " ".join(req.get("headers", {}).get("Referer", [""]))
|
||||
if ref and "hands.kestrelsnest.social" not in ref:
|
||||
referrers[re.sub(r"^https?://", "", ref).split("/")[0]] += 1
|
||||
m = re.search(r"[?&](ref|utm_source|fbclid)=([^&]*)", uri)
|
||||
if m:
|
||||
campaigns[m.group(1) + "=" + m.group(2)[:24]] += 1
|
||||
agents[re.sub(r"\(.*?\)", "", ua)[:40].strip()] += 1
|
||||
except OSError:
|
||||
continue
|
||||
print("traffic: %d addresses of people, %d page requests (%d bot addresses); hall %d, play %d, rules %d, room links %s; referrers %s; campaigns %s" % (
|
||||
len(addresses), requests, len(bots), pages["hall"], pages["play"], pages["rules"],
|
||||
dict(joins) or "none", dict(referrers) or "none", dict(campaigns) or "none"))
|
||||
sys.path.insert(0, "/usr/local/lib/waving-hands")
|
||||
import traffic
|
||||
t = traffic.scan(day)
|
||||
print("traffic: %d addresses of people, %d page requests (%d bot addresses, of them %d scanners, %d monitors); hall %d, play %d, rules %d; rooms opened here %d, room links %s; shared on %s; referrers %s; campaigns %s" % (
|
||||
len(t["addresses"]), t["human"], len(t["botAddresses"]), t["scanners"], t["monitors"], t["pages"]["hall"], t["pages"]["play"], t["pages"]["rules"],
|
||||
t["opened"], dict(t["joins"]) or "none", dict(t["shared"]) or "none", dict(t["referrers"]) or "none", dict(t["campaigns"]) or "none"))
|
||||
|
||||
# --- rooms: every ledger, today's in detail ---
|
||||
first_seen = {}
|
||||
|
||||
Reference in New Issue
Block a user