diff --git a/.github/scripts/accumulate-traffic.py b/.github/scripts/accumulate-traffic.py index 3edff9d..86c30e3 100644 --- a/.github/scripts/accumulate-traffic.py +++ b/.github/scripts/accumulate-traffic.py @@ -92,6 +92,44 @@ def fetch_star_count(): print(f"Star fetch failed: {e}") return None +def fetch_star_windows(): + """Real stars gained in rolling 1d / 7d / 30d windows, counted from live + starredAt timestamps (GraphQL, newest-first). Matches GitHub's own numbers + and is independent of snapshot timing. Returns None on failure.""" + token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") + if not token: + return None + now = datetime.now(timezone.utc) + bounds = {"d1": now.timestamp() - 86400, "d7": now.timestamp() - 7*86400, "d30": now.timestamp() - 30*86400} + counts = {"d1": 0, "d7": 0, "d30": 0} + cursor, pages = None, 0 + try: + while pages < 60: + after = f', after: "{cursor}"' if cursor else '' + query = ('{ repository(owner:"asgeirtj", name:"system_prompts_leaks"){ stargazers(first:100%s, ' + 'orderBy:{field:STARRED_AT, direction:DESC}){ pageInfo{endCursor hasNextPage} edges{starredAt} } } }') % after + body = json.dumps({"query": query}).encode() + req = urllib.request.Request("https://api.github.com/graphql", data=body, + headers={"Authorization": f"Bearer {token}", "User-Agent": "traffic-dashboard", "Content-Type": "application/json"}) + with urllib.request.urlopen(req, timeout=30) as r: + s = json.load(r)["data"]["repository"]["stargazers"] + oldest = now.timestamp() + for e in s["edges"]: + t = datetime.fromisoformat(e["starredAt"].replace("Z", "+00:00")).timestamp() + oldest = t + for k, b in bounds.items(): + if t >= b: + counts[k] += 1 + pages += 1 + if oldest < bounds["d30"] or not s["pageInfo"]["hasNextPage"]: + break + cursor = s["pageInfo"]["endCursor"] + print(f"Star windows: today={counts['d1']} 7d={counts['d7']} 30d={counts['d30']} ({pages} pages)") + return counts + except Exception as e: + print(f"Star windows fetch failed: {e}") + return None + def accumulate_stars(publish_dir): today = datetime.now(timezone.utc).strftime("%Y-%m-%d") data_dir = os.path.join(publish_dir, TRAFFIC_DIR) @@ -115,9 +153,9 @@ def accumulate_stars(publish_dir): json.dump(star_history, f, separators=(",", ":")) print(f"Accumulated: {len(star_history)} star snapshots (latest={star_history[-1]['stars'] if star_history else 'n/a'})") - return star_history + return star_history, fetch_star_windows() -def build_dashboard(publish_dir, ref_history, path_history, star_history): +def build_dashboard(publish_dir, ref_history, path_history, star_history, star_windows): data_dir = os.path.join(publish_dir, TRAFFIC_DIR) views = load_json(os.path.join(data_dir, "traffic_views.json")) clones = load_json(os.path.join(data_dir, "traffic_clones.json")) @@ -132,6 +170,7 @@ def build_dashboard(publish_dir, ref_history, path_history, star_history): "referrer_series": ref_history, "paths_series": path_history, "stars_series": star_history, + "stars_windows": star_windows, }, separators=(",", ":")) html = DASHBOARD_TEMPLATE.replace("__DATA_PLACEHOLDER__", embedded) @@ -207,7 +246,7 @@ DASHBOARD_TEMPLATE = r"""
Traffic dashboard — auto-updated daily from the traffic branch
Drag to zoom — click Reset to restore
Bars show stars gained per day · drag to zoom
Bars show stars gained per day · drag to zoom
Page Trends — daily 14-day view count for the top pages