diff --git a/scripts/usage_stats.py b/scripts/usage_stats.py index 4b5d048..7e22f93 100644 --- a/scripts/usage_stats.py +++ b/scripts/usage_stats.py @@ -69,31 +69,35 @@ def _is_bot(ua: str, path: str) -> bool: # ── Feature mapping (from Referer header) ───────────────────────────────────── # Evaluated in order: first match wins. None label = exclude. -_FEATURE_MAP: list[tuple[str, str | None, str | None]] = [ - ("planner.bincio.org", None, "planner"), - ("wiki.bincio.org", None, "wiki"), - ("activity.bincio.org", "/admin/", None), # exclude admin polling - ("activity.bincio.org", "/activity/", "activity"), - ("activity.bincio.org", "/segments/", "segments"), - ("activity.bincio.org", "/stats/", "stats"), - ("activity.bincio.org", "/explore/", "explore"), - ("activity.bincio.org", "/ideas/", "ideas"), - ("activity.bincio.org", "/u/", "profile"), - ("activity.bincio.org", None, "feed"), - ("bincio.org", None, "hub"), +# Tuple: (host, path_startswith_or_None, path_contains_or_None, label_or_None) +_FEATURE_MAP: list[tuple[str, str | None, str | None, str | None]] = [ + ("planner.bincio.org", None, None, "planner"), + ("wiki.bincio.org", None, None, "wiki"), + ("activity.bincio.org", "/admin/", None, None), # exclude + ("activity.bincio.org", "/activity/", None, "activity"), + ("activity.bincio.org", "/segments/", None, "segments"), + ("activity.bincio.org", "/stats/", None, "stats"), + ("activity.bincio.org", "/community/", None, "community"), + ("activity.bincio.org", "/ideas/", None, "ideas"), + # explore lives at /u/{handle}/athlete/explore/ — check before generic /u/ + ("activity.bincio.org", "/u/", "athlete/explore", "explore"), + ("activity.bincio.org", "/u/", None, "profile"), + ("activity.bincio.org", None, None, "feed"), + ("bincio.org", None, None, "hub"), ] FEATURE_COLORS = { - "feed": "#60a5fa", - "activity": "#4ade80", - "segments": "#facc15", - "planner": "#f97316", - "wiki": "#a855f7", - "ideas": "#f43f5e", - "explore": "#34d399", - "profile": "#94a3b8", - "hub": "#64748b", - "stats": "#e879a0", + "feed": "#60a5fa", + "activity": "#4ade80", + "segments": "#facc15", + "planner": "#f97316", + "wiki": "#a855f7", + "ideas": "#f43f5e", + "explore": "#34d399", + "community": "#22d3ee", + "profile": "#94a3b8", + "hub": "#64748b", + "stats": "#e879a0", } def _feature(referer: str) -> str | None: @@ -105,9 +109,10 @@ def _feature(referer: str) -> str | None: path = p.path except Exception: return None - for h, prefix, label in _FEATURE_MAP: + for h, prefix, contains, label in _FEATURE_MAP: if host == h: - if prefix is None or path.startswith(prefix): + if (prefix is None or path.startswith(prefix)) and \ + (contains is None or contains in path): return label return None