#!/usr/bin/env python3 """Record the repository's daily star count and render its README chart.""" from __future__ import annotations import json import math from datetime import datetime, timezone from pathlib import Path from urllib.request import Request, urlopen ROOT = Path(__file__).resolve().parents[1] DATA_PATH = ROOT / "data" / "star-history.json" SVG_PATH = ROOT / "assets" / "star-history.svg" REPOSITORY = "cporter202/coreclaw-api-directory" def fetch_star_count() -> int: request = Request( f"https://api.github.com/repos/{REPOSITORY}", headers={ "Accept": "application/vnd.github+json", "User-Agent": "coreclaw-api-directory-star-history", "X-GitHub-Api-Version": "2022-11-28", }, ) with urlopen(request, timeout=20) as response: return int(json.load(response)["stargazers_count"]) def update_history(stars: int) -> dict: history = json.loads(DATA_PATH.read_text(encoding="utf-8")) today = datetime.now(timezone.utc).date().isoformat() points = history.setdefault("points", []) if points and points[-1]["date"] == today: points[-1]["stars"] = stars else: points.append({"date": today, "stars": stars}) points.sort(key=lambda point: point["date"]) DATA_PATH.write_text(json.dumps(history, indent=2) + "\n", encoding="utf-8") return history def render_svg(history: dict) -> str: points = history["points"] width, height = 1200, 430 left, right, top, bottom = 92, 1135, 132, 340 current = int(points[-1]["stars"]) max_value = max(int(point["stars"]) for point in points) max_y = max(4, int(math.ceil(max_value / 4.0) * 4)) def x_at(index: int) -> float: if len(points) == 1: return (left + right) / 2 return left + (right - left) * index / (len(points) - 1) def y_at(value: int) -> float: return bottom - (bottom - top) * value / max_y coordinates = [ (x_at(index), y_at(int(point["stars"]))) for index, point in enumerate(points) ] polyline = " ".join(f"{x:.1f},{y:.1f}" for x, y in coordinates) area = ( f"M {coordinates[0][0]:.1f} {bottom} " + " ".join(f"L {x:.1f} {y:.1f}" for x, y in coordinates) + f" L {coordinates[-1][0]:.1f} {bottom} Z" ) grid = [] for step in range(5): y = top + (bottom - top) * step / 4 label = round(max_y * (4 - step) / 4) grid.append( f'' f'{label}' ) dots = "".join( f'' for x, y in coordinates[-30:] ) end_label = points[-1]["date"] if len(points) > 1 else "Tracking started" return f''' CoreClaw API Directory star history Daily GitHub star count, currently {current} stars. STAR GROWTH CoreClaw API Directory ★ {current} CURRENT STARS {''.join(grid)} {dots} {points[0]['date']} {end_label} Daily snapshots recorded by this repository ''' def main() -> None: history = update_history(fetch_star_count()) SVG_PATH.write_text(render_svg(history), encoding="utf-8") print( f"Recorded {history['points'][-1]['stars']} stars for " f"{history['points'][-1]['date']}" ) if __name__ == "__main__": main()