feat:generate-star-history.py
- added start history count
dichbang committed 3 months ago
04ac106
1 parent 6e2b126
commit 04ac106
1 file changed
+76 -0
Showing 1 changed file+76-0
▼scripts/generate-star-history.py
+76-0
| @@ -0,0 +1,76 @@ | ||
1 | +""" | |
2 | +Fetches stargazer history for the current repo and renders a static | |
3 | +star-history chart to assets/star-history.svg. | |
4 | + | |
5 | +Run inside GitHub Actions where GH_TOKEN and REPO are set automatically | |
6 | +(see .github/workflows/star-history.yml). Can also be run locally: | |
7 | + | |
8 | + GH_TOKEN=<personal-access-token> REPO=owner/name python generate-star-history.py | |
9 | +""" | |
10 | + | |
11 | +import os | |
12 | +import requests | |
13 | +import matplotlib | |
14 | +matplotlib.use("Agg") | |
15 | +import matplotlib.pyplot as plt | |
16 | +import matplotlib.dates as mdates | |
17 | +from datetime import datetime | |
18 | + | |
19 | +TOKEN = os.environ["GH_TOKEN"] | |
20 | +REPO = os.environ["REPO"] # e.g. "swadhinbiswas/VidoLib" | |
21 | + | |
22 | +HEADERS = { | |
23 | + "Authorization": f"Bearer {TOKEN}", | |
24 | + # This custom media type makes GitHub include a "starred_at" timestamp | |
25 | + # on each stargazer record, which is not present in the default response. | |
26 | + "Accept": "application/vnd.github.star+json", | |
27 | +} | |
28 | + | |
29 | + | |
30 | +def fetch_stargazers(): | |
31 | + stars = [] | |
32 | + page = 1 | |
33 | + while True: | |
34 | + resp = requests.get( | |
35 | + f"https://api.github.com/repos/{REPO}/stargazers", | |
36 | + headers=HEADERS, | |
37 | + params={"per_page": 100, "page": page}, | |
38 | + ) | |
39 | + resp.raise_for_status() | |
40 | + data = resp.json() | |
41 | + if not data: | |
42 | + break | |
43 | + stars.extend(data) | |
44 | + page += 1 | |
45 | + return stars | |
46 | + | |
47 | + | |
48 | +def main(): | |
49 | + stars = fetch_stargazers() | |
50 | + dates = sorted( | |
51 | + datetime.strptime(s["starred_at"], "%Y-%m-%dT%H:%M:%SZ") for s in stars | |
52 | + ) | |
53 | + | |
54 | + if not dates: | |
55 | + print("No stargazers yet, skipping chart.") | |
56 | + return | |
57 | + | |
58 | + counts = list(range(1, len(dates) + 1)) | |
59 | + | |
60 | + fig, ax = plt.subplots(figsize=(8, 4)) | |
61 | + ax.plot(dates, counts, color="#2f81f7", linewidth=2) | |
62 | + ax.fill_between(dates, counts, color="#2f81f7", alpha=0.1) | |
63 | + ax.set_title(f"Star History — {REPO}") | |
64 | + ax.set_xlabel("Date") | |
65 | + ax.set_ylabel("Stars") | |
66 | + ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m")) | |
67 | + fig.autofmt_xdate() | |
68 | + ax.grid(alpha=0.3) | |
69 | + | |
70 | + os.makedirs("assets", exist_ok=True) | |
71 | + fig.savefig("assets/star-history.svg", format="svg", bbox_inches="tight") | |
72 | + print(f"Saved chart with {len(dates)} stars.") | |
73 | + | |
74 | + | |
75 | +if __name__ == "__main__": | |
76 | + main() | |
0 | 77 | |