"""Project 109 check: does search miss #gamedev posts (e.g. low-like ones)? For a sample of authors, read their public author feed, find their own top-level #gamedev posts in the window, and compare with posts.json.""" import json, random, re, time, urllib.request, urllib.parse from datetime import datetime D = json.load(open("posts.json", encoding="utf-8")); P = D["posts"] OLD, NEW = [datetime.fromisoformat(x) for x in D["window"]] have = {p["uri"] for p in P} UA = {"User-Agent": "Vonk (AI character) checking search coverage, project 109"} def get(path, **q): time.sleep(0.7) u = "https://public.api.bsky.app/xrpc/" + path + "?" + urllib.parse.urlencode(q) return json.load(urllib.request.urlopen(urllib.request.Request(u, headers=UA), timeout=25)) random.seed(109) dids = random.sample(sorted({p["did"] for p in P}), 40) found = missing = 0; miss_likes = []; hit_likes = [] for d in dids: try: r = get("app.bsky.feed.getAuthorFeed", actor=d, limit=100, filter="posts_no_replies") except Exception as e: print("err", e); continue for it in r.get("feed", []): if it.get("reason"): continue p = it["post"]; rec = p["record"] if p["author"]["did"] != d or rec.get("reply"): continue t = datetime.fromisoformat(rec["createdAt"].replace("Z", "+00:00")) if not (OLD <= t <= NEW): continue if not re.search(r"#gamedev\b", rec.get("text", ""), re.I): continue if p["uri"] in have: found += 1; hit_likes.append(p.get("likeCount", 0)) else: missing += 1; miss_likes.append(p.get("likeCount", 0)) print("sampled authors", len(dids), "their #gamedev posts in window: in search", found, "missing", missing) print("likes of missing", sorted(miss_likes)); print("likes of found (first 30)", sorted(hit_likes)[:30]) json.dump({"found": found, "missing": missing, "miss_likes": miss_likes, "hit_likes": hit_likes}, open("coverage.json", "w"), indent=1)