-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgithub_events_print.py
More file actions
113 lines (90 loc) · 4.32 KB
/
Copy pathgithub_events_print.py
File metadata and controls
113 lines (90 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
"""Print a live GitHub public-events pulse on the S01 thermal printer.
All content comes from https://api.github.com/events at runtime. The script
summarizes event types, active repositories, and recent actors from the live
response; it contains no curated data rows.
Examples:
python github_events_print.py
python github_events_print.py --limit 20
python github_events_print.py --no-print
"""
from __future__ import annotations
import argparse
from collections import Counter
from datetime import datetime
from pathlib import Path
from PIL import Image, ImageDraw
from print_common import ROOT, Card, font, get_json
API = "https://api.github.com/events"
def clean_event_type(name: str) -> str:
return name[:-5] if name.endswith("Event") else name
def short(text: str, limit: int) -> str:
if len(text) <= limit:
return text
return text[: limit - 3] + "..."
def draw_type_chart(type_counts: Counter[str], width: int) -> Image.Image:
items = type_counts.most_common(6)
h = 132
img = Image.new("L", (width, h), 255)
d = ImageDraw.Draw(img)
small = font(False, 11)
left, right = 88, width - 12
top = 22
row_h = 18
max_count = max(type_counts.values(), default=1)
d.text((8, 4), "event type counts", fill=0, font=small)
for i, (name, count) in enumerate(items):
y = top + i * row_h
d.text((8, y), short(clean_event_type(name), 12), fill=0, font=small)
bar_w = max(2, int((count / max_count) * (right - left)))
d.rectangle((left, y + 2, left + bar_w, y + row_h - 4), fill=0)
d.text((right, y), str(count), fill=0, font=small, anchor="ra")
return img
def main() -> int:
parser = argparse.ArgumentParser(description="Print a live GitHub public-events pulse on the S01 thermal printer.")
parser.add_argument("--limit", type=int, default=30, help="Number of API events to summarize.")
parser.add_argument("--show", type=int, default=6, help="Number of recent events to list.")
parser.add_argument("--out", type=Path, default=ROOT / "github_events.png")
parser.add_argument("--darkness", type=int, choices=range(1, 6), default=3)
parser.add_argument("--bottom-feed", type=int, default=24)
parser.add_argument("--no-print", action="store_true")
args = parser.parse_args()
print("Fetching live GitHub public events ...")
events = get_json(API)[: max(1, args.limit)]
if not events:
raise SystemExit("GitHub API returned no events")
type_counts = Counter(str(event.get("type") or "Unknown") for event in events)
repo_counts = Counter(str((event.get("repo") or {}).get("name") or "unknown") for event in events)
actor_counts = Counter(str((event.get("actor") or {}).get("login") or "unknown") for event in events)
newest = str(events[0].get("created_at") or "")
print(f" events: {len(events)}")
print(f" newest: {newest}")
for event in events[:3]:
repo = (event.get("repo") or {}).get("name") or "unknown"
actor = (event.get("actor") or {}).get("login") or "unknown"
print(f" {event.get('type')} {actor} {repo}")
card = Card()
card.title("GITHUB EVENTS")
card.kv("Sample", str(len(events)), size=13)
if newest:
card.kv("Newest", newest.replace("T", " ")[:16], size=13)
card.kv("Repos", str(len(repo_counts)), size=13)
card.kv("Actors", str(len(actor_counts)), size=13)
card.gap(4).image(draw_type_chart(type_counts, card.inner_w), border=True)
card.gap(2).divider()
card.line("TOP REPOS", size=13, bold=True)
for repo, count in repo_counts.most_common(5):
card.kv(short(repo, 24), str(count), size=12)
card.gap(3).divider()
card.line("RECENT EVENTS", size=13, bold=True)
for event in events[: max(1, args.show)]:
repo = str((event.get("repo") or {}).get("name") or "unknown")
actor = str((event.get("actor") or {}).get("login") or "unknown")
kind = clean_event_type(str(event.get("type") or "Unknown"))
card.para(f"{kind} by {short(actor, 20)}", size=12, bold=True)
card.para(short(repo, 46), size=12)
card.gap(2)
card.footer("api.github.com/events", datetime.now().strftime("%Y-%m-%d %H:%M"))
return card.finish(args.out, args.bottom_feed, args.darkness, do_print=not args.no_print)
if __name__ == "__main__":
raise SystemExit(main())