-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupdate_status.py
More file actions
552 lines (520 loc) · 26.2 KB
/
update_status.py
File metadata and controls
552 lines (520 loc) · 26.2 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
import requests
import os
import sys
import random
import time
import json
from datetime import datetime
from pathlib import Path
def set_github_status(token, message, emoji):
"""
Executes a GraphQL mutation to update the user's GitHub status.
Includes exponential backoff to handle rate limits and 20-second timeouts.
"""
query = """
mutation($input: ChangeUserStatusInput!) {
changeUserStatus(input: $input) {
status { message emoji }
}
}
"""
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
# Truncate to 100 chars to meet GitHub's API string length constraints
variables = {"input": {"message": str(message)[:100], "emoji": str(emoji)}}
for attempt in range(1, 4):
try:
response = requests.post(
"https://api.github.com/graphql",
json={"query": query, "variables": variables},
headers=headers,
timeout=20,
)
return response
except Exception as e:
# Escalates to main loop after 3 failed attempts
if attempt == 3:
raise e
time.sleep(5 * attempt)
def update_stats(base_path, pool_size, status_text=None, emoji=None, error=None):
"""
Maintains stats.json. Calculates error rates and manages a rolling
history of the last 15 updates. Tracks total status pool size.
"""
stats_file = base_path / "stats.json"
now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
# Load existing stats or initialize new schema if file is missing
stats = None
if stats_file.exists():
try:
with open(stats_file, "r", encoding="utf-8") as f:
stats = json.load(f)
except:
pass
if not stats:
stats = {
"total_attempts": 0,
"success_count": 0,
"failure_count": 0,
"error_rate_percent": "0.0%",
"last_run": "",
"status_pool_count": 0,
"last_error": "None",
"history": [],
}
stats["total_attempts"] += 1
stats["last_run"] = now
stats["status_pool_count"] = pool_size
if error:
stats["failure_count"] += 1
stats["last_error"] = str(error)[:200]
else:
stats["success_count"] += 1
stats["last_error"] = "None"
if status_text:
# Stores text and emoji shortcode for dashboard mapping
stats["history"].insert(
0, {"time": now, "status": status_text, "emoji": emoji}
)
# Limit history to 15 entries to prevent file bloat
stats["history"] = stats["history"][:15]
if stats["total_attempts"] > 0:
rate = (stats["failure_count"] / stats["total_attempts"]) * 100
stats["error_rate_percent"] = f"{round(rate, 2)}%"
with open(stats_file, "w", encoding="utf-8") as f:
json.dump(stats, f, indent=4)
def update_github_status():
"""
Main controller: selects the status, filters for variety, and validates token.
"""
token = os.getenv("GH_TOKEN")
base_path = Path(__file__).parent.absolute()
state_file = base_path / "last_status.txt"
# Status pool: Re-integrated requested items + variety expansion (Exactly 200)
status_pool = [
# --- REQUESTED ITEMS (35) ---
("↑ ↑ ↓ ↓ ← → ← → B A", ":video_game:"),
("Error 404: Status Not Found", ":ghost:"),
("Dial-up noises intensifying", ":telephone_receiver:"),
("Thinking in 01010110", ":computer:"),
("127.0.0.1", ":house:"),
("Sudo make me a sandwich", ":bread:"),
("Centering a div...", ":distraught:"),
("Keyboard go clack", ":keyboard:"),
("VRAM management is a full-time job", ":memory:"),
("Linux enthusiast", ":penguin:"),
("Vim is a way of life", ":memo:"),
("Exit Vim? How?", ":question:"),
("I have a bad feeling about this", ":milky_way:"),
("This is the way", ":crossed_swords:"),
("Wake up, Samurai", ":city_sunset:"),
("There is no spoon", ":foggy:"),
("Talk is cheap. Show me the code.", ":speech_balloon:"),
("Code is poetry", ":fountain_pen:"),
("Minimalist CSS is the goal", ":art:"),
("Small Web protocol exploration", ":satellite:"),
("Dark mode is the only mode", ":night_with_stars:"),
("JSON is my love language", ":heart:"),
("Vanilla JS or bust", ":icecream:"),
("Markdown is life", ":memo:"),
("It's not a bug, it's a feature", ":beetle:"),
("Git commit -m 'Fixed everything'", ":package:"),
("Compiling...", ":hourglass_flowing_sand:"),
("Rubber ducking through a logic error", ":duck:"),
("One does not simply walk into production", ":mountain:"),
("RTFM (Read The Friendly Manual)", ":book:"),
("Pythonic by design", ":snake:"),
("The cloud is just someone else's computer", ":cloud:"),
("Hello World!", ":earth_americas:"),
("Don't repeat yourself (DRY)", ":droplet:"),
("Refactoring for the soul", ":hammer_and_wrench:"),
# --- THE OFFICE US (50) ---
("I’m not superstitious, but I am a little stitious.", ":black_currant:"),
("Identity theft is not a joke, Jim!", ":eyeglasses:"),
("I declare bankruptcy!", ":money_with_wings:"),
("Threat Level Midnight", ":clapper:"),
("Assistant (to the) Regional Manager", ":briefcase:"),
("Bears, beets, Battlestar Galactica.", ":bear:"),
("How the turntables...", ":records:"),
("Dwight, you ignorant slut!", ":office:"),
("I'm an early bird and a night owl. I'm wise and I have worms.", ":owl:"),
("Sometimes I start a sentence and I don't even know where it's going.", ""),
("Parkour!", ":person_doing_cartwheel:"),
("Pretzel Day", ":pretzel:"),
("The Dundies", ":trophy:"),
("Did I stutter?", ""),
("I feel God in this Chili's tonight.", ":hot_pepper:"),
("The worst thing about prison was the Dementors.", ":ghost:"),
("Boy, have you lost your mind? Cause I’ll help you find it!", ""),
("Why are you the way that you are?", ""),
("Dunder Mifflin, this is Pam.", ":telephone_receiver:"),
("You miss 100% of the shots you don't take. - Michael Scott", ""),
("Jim Halpert is a smudge and arrogant.", ""),
("I'm fast. Somewhere between a snake and a mongoose.", ""),
("I don't want to work. I just want to bang on this mug all day.", ":coffee:"),
("I hate looking at your face. I wanna smash it.", ""),
("Rit-dit-dit-do-doo!", ""),
("That’s what she said.", ""),
("I wonder what people like about me. Probably my pigtails.", ""),
("If I can't scuba, then what's this all been about?", ":scuba:"),
("Creed Bratton has never stood out. He’s a survivor.", ""),
("Everything I have I owe to this job. This stupid, wonderful job.", ""),
("Save Bandit!", ":cat:"),
("I am running away from my responsibilities. And it feels good.", ":runner:"),
("Should have burned this place down when I had the chance.", ":fire:"),
("Safety but wait, a second, point of order. Shirley, occupant, which do we use?", ":ambulance:"),
("Business unless you’re Kevin.", ":cookie:"),
("I want people to be afraid of how much they love me.", ":heart:"),
("Dwight, get out of my nook!", ":book:"),
("I am Beyoncé, always.", ":crown:"),
("If I don't have some cake soon, I might die.", ":birthday:"),
("Every week, I'm supposed to take four hours and do a quality spot-check at the paper mill.", ":factory:"),
("I am a black belt in gift wrapping.", ":gift:"),
("Number one: Inverted file system.", ":file_folder:"),
("I ground up some aspirin and put it in his food.", ":pill:"),
("I have a lot of questions. Number one, how dare you?", ":question:"),
("The eyes are the groin of the head.", ":eyes:"),
("Mini-cupcakes? As in the mini version of regular cupcakes?", ":cupcake:"),
("I'm not a millionaire. I thought I would be by the time I was 30.", ":moneybag:"),
("Everything's a joke to you.", ":clown_face:"),
("Suddenly she’s not yo’ ho no mo’.", ":broken_heart:"),
("There’s a lot of beauty in ordinary things. Isn’t that kind of the point?", ":camera:"),
# --- CINEMA & CLASSICS (50) ---
("Do or do not. There is no try.", ":crossed_swords:"),
("I hate snakes, Jock! I hate 'em!", ":snake:"),
("This belongs in a museum!", ":classical_building:"),
("Roads? Where we're going, we don't need roads.", ":red_car:"),
("1.21 Gigawatts!", ":high_voltage:"),
("Life finds a way.", ":seedling:"),
("Clever girl...", ":sauropod:"),
("Hold on to your butts.", ":smoking:"),
("Great Scott!", ":zap:"), ("No ticket!", ":ticket:"),
("X never, ever marks the spot.", ":multiplication:"),
("Fortune and glory, kid.", ":coin:"),
("I find your lack of faith disturbing.", ":ringed_planet:"),
("Resistance is futile.", ":stop_sign:"),
("I'm sorry, Dave. I'm afraid I can't do that.", ":red_circle:"),
("42: The answer to everything", ":key:"),
("I'll be back.", ":robot:"),
("Houston, we have a problem.", ":rocket:"),
("May the Force be with you.", ":milky_way:"),
("You're gonna need a bigger boat.", ":ship:"),
("To infinity and beyond!", ":rocket:"),
("I am your father.", ""),
("Elementary, my dear Watson.", ":mag:"),
("Bond. James Bond.", ":suit:"),
("Winter is coming.", ":snowflake:"),
("You shall not pass!", ":man_mage:"),
("Inconceivable!", ""),
("Follow the white rabbit.", ":rabbit:"),
("I'm gonna make him an offer he can't refuse.", ""),
("Keep your friends close, but your enemies closer.", ""),
("The first rule of Fight Club is: You do not talk about Fight Club.", ""),
("Say 'hello' to my little friend!", ":boom:"),
("Just keep swimming.", ":fish:"),
("My precious.", ":ring:"),
("I am Iron Man.", ":mechanical_arm:"),
("E.T. phone home.", ":telephone_receiver:"),
("There's no place like home.", ":strawberry:"),
("Hasta la vista, baby.", ":sunglasses:"),
("I see dead people.", ":ghost:"),
("Here's Johnny!", ":axe:"),
("You talking to me?", ":raised_back_of_hand:"),
("I'm the king of the world!", ":anchor:"),
("Go ahead, make my day.", ":pistol:"),
("Why so serious?", ":clown_face:"),
("I'll have what she's having.", ":stew:"),
("Magic Mirror on the wall, who is the fairest one of all?", ":mirror:"),
("Frankly, my dear, I don't give a damn.", ":leaves:"),
("Carpe diem. Seize the day, boys.", ":mantelpiece_clock:"),
("Wax on, wax off.", ":manual_vibration_mode:"),
("Toto, I've a feeling we're not in Kansas anymore.", ":tornado:"),
# --- VIDEO GAMES (50) ---
("The cake is a lie.", ":birthday:"),
("Praise the Sun!", ":sun_with_face:"),
("It's dangerous to go alone! Take this.", ":crossed_swords:"),
("Protocol 3: Protect the Pilot", ":robot:"),
("Snake? Snake?! SNAKE!!!", ":snake:"),
("Would you kindly?", ":anchor:"),
("War. War never changes.", ":radioactive:"),
("Hey! Listen!", ":fairy:"),
("Stay awhile and listen.", ":scroll:"),
("Reticulating splines...", ""),
("FINISH HIM", ":skull:"),
("Fus Ro Dah!", ":wind_face:"),
("Wasted", ""),
("You Died", ""),
("All your base are belong to us", ":video_game:"),
("Our princess is in another castle.", ""),
("It's-a me, Mario!", ":mushroom:"),
("Had to be me. Someone else might have gotten it wrong.", ""),
("A man chooses, a slave obeys.", ""),
("Nothing is true, everything is permitted.", ""),
("Do you get to the Cloud District very often?", ""),
("Prepare for unforeseen consequences.", ""),
("Endure and survive.", ""),
("Rip and tear, until it is done.", ""),
("May your road lead you to warm sands.", ""),
("Wind's howling.", ":wolf:"),
("The right man in the wrong place can make all the difference.", ":briefcase:"),
("Whether we wanted it or not, we've stepped into a war with the Cabal.", ":ringed_planet:"),
("A hunter must hunt.", ":crescent_moon:"),
("Kept you waiting, huh?", ":eyeglasses:"),
("Boy!", ":axe:"),
("The numbers, Mason! What do they mean?", ":input_numbers:"),
("I used to be an adventurer like you, then I took an arrow in the knee.", ":bow_and_arrow:"),
("Get over here!", ":chains:"),
("Don't make a girl a promise if you know you can't keep it.", ":sparkles:"),
("Stand in the ashes of a trillion dead souls, and ask the ghosts if honor matters.", ":ghost:"),
("What is a man? A miserable little pile of secrets.", ":wine_glass:"),
("I am Andrew Ryan, and I'm here to ask you a question.", ":ocean:"),
("Seven six two millimeter. Full metal jacket.", ":bullet_train:"),
("Objective: Survive.", ":shield:"),
("Even in dark times, we cannot relinquish the things that make us human.", ":heart:"),
("It’s time to kick ass and chew bubblegum... and I’m all out of gum.", ":sunglasses:"),
("A skyscraper is a lot like a person. It’s got a skeleton, it’s got a skin.", ":building_construction:"),
("No gods or kings. Only man.", ":statue_of_liberty:"),
("History is written by the victors.", ":memo:"),
("I survive because the fire inside burned brighter than the fire around me.", ":fire:"),
("The healthy human mind doesn't wake up in the morning thinking this is its last day on Earth.", ":earth_americas:"),
("Good men mean well. We just don't always end up doing well.", ":man_climbing:"),
("You can't just shoot a hole into the surface of Mars.", ":test_tube:"),
("Everything is shiny and chrome.", ":motorcycle:"),
# --- BRUTALLY HONEST DEV REALITY (50) ---
("Writing code that I will hate in six months.", ""),
("It works. I don't know why. I'm not touching it.", ""),
("Fixing the fix that broke the fix.", ""),
("My code is a specialized form of art called 'Garbage'.", ""),
("Deleting 100 lines of code is more satisfying than writing them.", ":wastebasket:"),
("Segmentation fault (core dumped)", ""),
("git commit -m 'fixed bugs by creating new ones'", ""),
("A programmer is a machine that turns caffeine into code.", ":coffee:"),
("Documentation is a love letter to your future self.", ""),
("It's not a bug, it's a feature.", ":lady_beetle:"),
("Works on my machine.", ":shrug:"),
("Weeks of coding can save you hours of planning.", ""),
("Legacy code is code that works.", ""),
("Technical debt is high interest.", ":money_with_wings:"),
("If it's not in Git, it doesn't exist.", ""),
("90% of coding is staring at the screen.", ""),
("One man's constant is another man's variable.", ""),
("The best code is the code you can delete.", ""),
("Real programmers count from 0.", ""),
("Code never lies, comments sometimes do.", ""),
("Premature optimization is the root of all evil.", ""),
("First, solve the problem. Then, write the code.", ""),
("Code is like humor. If you have to explain it, it’s bad.", ""),
("I'm not procrastinating, I'm asynchronously processing.", ""),
("Java is to JavaScript what car is to carpet.", ""),
("A SQL query walks into a bar and asks... 'Can I join you?'", ""),
("Two hard things in CS: cache invalidation and naming things.", ""),
("Complexity is the enemy of reliability.", ""),
("Experience is the name everyone gives to their mistakes.", ""),
("To err is human, but to really foul things up you need a computer.", ""),
("Computers follow instructions, they don't read your mind.", ""),
("Testing leads to failure, and failure leads to understanding.", ""),
("Every bug was once a feature request.", ""),
("Refactoring: Because yesterday's me was an idiot.", ""),
("There is no such thing as a simple change.", ""),
("Junior devs solve problems with code. Senior devs solve problems by deleting it.", ""),
("Nothing is more permanent than a temporary hack.", ""),
("A 'quick fix' usually takes three hours and breaks two other things.", ""),
("If the code was hard to write, it should be hard to read.", ""),
("Your code is only as good as the edge cases you didn't think of.", ""),
("The code is finished when there's nothing left to take away.", ":scissors:"),
("StackOverflow: The only reason I still have a job.", ""),
("I spend 10% of my time writing code and 90% wondering why I wrote it.", ""),
("Comments should explain 'why', not 'what'.", ""),
("Software is a gas; it expands to fill its container.", ""),
("The project will be finished as soon as we stop adding features.", ""),
("Debugging is like being the detective in a movie where you are also the murderer.", ":detective:"),
("If it isn't broken, you haven't added enough features yet.", ""),
("Naming a variable is the hardest part of my workday.", ""),
("Code works, I sleep. Code breaks, I weep.", ":cry:"),
# --- LINUX & HARDWARE (50) ---
("I use Arch btw", ":penguin:"),
("RTFM", ""),
("Flatpak > Snap", ":package:"),
("Compiling the kernel...", ":coffee:"),
("Magic smoke containment specialist", ":dash:"),
("Distro hopping again...", ":cyclone:"),
("Kernel panic", ":exploding_head:"),
("chmod +x success.sh", ""),
("rm -rf /bin/worries", ""),
("grep -r 'meaning_of_life' /dev/null", ""),
("Everything is a file.", ""),
("Bash is a dish best served cold.", ""),
("Kill -9 everything.", ""),
("Pipe it to /dev/null.", ""),
("The BIOS is the boss.", ""),
("Systemd: Love it or leave it.", ""),
("Upgrading the firmware... wish me luck.", ""),
("Don't force it, get a bigger hammer.", ":hammer:"),
("Thermal paste is not a snack.", ""),
("The hardware works. The software is broken.", ""),
("It's a driver issue.", ""),
("Checking disk for errors...", ":mag:"),
("Fan speed: Maximum.", ""),
("Overclocked and thermal throttling", ":hot_face:"),
("I love the smell of ozone in the morning.", ""),
("Static electricity is my enemy.", ""),
("Re-seating the RAM usually works.", ""),
("Cable management is an art form.", ""),
("Waiting for the SSH connection...", ""),
("Is the server down or is it just me?", ""),
("Tailing the logs...", ":scroll:"),
("Sudo !!", ":zap:"),
("4GB of VRAM is enough for anyone... probably.", ":clapper:"),
("Minty fresh desktop environment", ":leafy_green:"),
("Dual-booting into chaos", ":wavy_dash:"),
("The cloud is just someone else's computer.", ":cloud:"),
("X11 is the past, Wayland is the future (eventually).", ":eye:"),
("ZFS is not a filesystem, it’s a religion.", ":anchor:"),
("It’s not slow, it’s just compiling.", ":gear:"),
("I’ve got 99 problems but a Windows update ain’t one.", ":window:"),
("Vim is easy to enter, impossible to leave.", ":door:"),
("A 256GB SSD is plenty if you don't hoard data.", ":minidisc:"),
("Ping 127.0.0.1. There's no place like home.", ":house:"),
("Building a PC is just LEGO for adults.", ":bricks:"),
("Man pages are my only friends.", ":book:"),
("The terminal is my natural habitat.", ":keyboard:"),
("Proprietary drivers are the devil.", ":smiling_imp:"),
("Swap space is for people who can't afford more RAM.", ":memory:"),
("If it doesn't work, try turning it off and back on again.", ":arrows_counterclockwise:"),
("Bleeding edge means bleeding out.", ":drop_of_blood:"),
# --- LOGIC, CS THEORY & GENERAL (50) ---
("P vs NP: Still undecided", ":thinking:"),
("Recursion: See status for details", ":repeat:"),
("Entropy increases", ":cyclone:"),
("Schrödinger's Status", ":cat:"),
("Occam's Razor: Simplest is usually right.", ":hocho:"),
("Standard Deviation", ":chart_with_upwards_trend:"),
("The universe is a simulation.", ":milky_way:"),
("O(n log n) is efficient enough.", ""),
("Correlation is not causation.", ":chart_with_upwards_trend:"),
("Non-deterministic behavior detected.", ":dice:"),
("Absolute Zero.", ":snowflake:"),
("Everything is an object", ":package:"),
("Garbage collection in progress", ":put_litter_in_its_place:"),
("Hello World", ""),
("System.gc();", ""),
("Turing complete", ":checkered_flag:"),
("Off-by-one errors are the worst", ":straight_ruler:"),
("Floating point precision is a myth", ":money_with_wings:"),
("Race condition in progress...", ":racing_car:"),
("Heisenberg's Uncertainty Principle", ":atom_symbol:"),
("Stack Overflow", ":layers:"),
("Deadlock detected", ":lock:"),
("Big O: O(1) is the dream", ":rocket:"),
("Null pointer exception", ":point_up:"),
("Binary search for meaning", ":mag:"),
("Asymptotic complexity", ":chart_with_downwards_trend:"),
("The Halting Problem is unsolvable", ":stop_sign:"),
("Finite State Machine", ":gear:"),
("Inheritance: I am my father's son", ":family:"),
("Encapsulation is key", ":closed_lock_with_key:"),
("Boolean logic: True or False?", ":switch:"),
("Abstractions all the way down", ":arrow_down:"),
("Deterministic chaos", ":twisted_rightwards_arrows:"),
("Syntactic sugar", ":candy:"),
("Functional programming for purity", ":alembic:"),
("State is the enemy of understanding.", ":brain:"),
("The Liskov Substitution Principle", ":ebony_star:"),
("Information is the resolution of uncertainty.", ":signal_strength:"),
("Immutable by design.", ":ice:"),
("Side effects: Use only as directed.", ":test_tube:"),
("Concurrency is not parallelism.", ":railway_track:"),
("Dependency injection for loose coupling.", ":syringe:"),
("First-class functions.", ":medal_military:"),
("The map is not the territory.", ":map:"),
("A monad is just a monoid in the category of endofunctors.", ":ring:"),
("Garbage in, garbage out.", ":wastebasket:"),
("Idempotency: Do it again, same result.", ":arrows_counterclockwise:"),
("Law of Demeter: Only talk to your friends.", ":speaking_head:"),
("Premature abstraction is a trap.", ":fishing_pole_and_fish:"),
("Everything that can happen, does happen.", ":cyclone:"),
# --- EMOJI ONLY (50) ---
(" ", ":computer:"),
(" ", ":brain:"),
(" ", ":tux:"),
(" ", ":zap:"),
(" ", ":floppy_disk:"),
(" ", ":t_rex:"),
(" ", ":joystick:"),
(" ", ":alien:"),
(" ", ":clapper:"),
(" ", ":microchip:"),
(" ", ":rocket:"),
(" ", ":saturn:"),
(" ", ":telescope:"),
(" ", ":gear:"),
(" ", ":hammer_and_wrench:"),
(" ", ":keyboard:"),
(" ", ":mouse_three_button:"),
(" ", ":desktop_computer:"),
(" ", ":battery:"),
(" ", ":link:"),
(" ", ":globe_with_meridians:"),
(" ", ":satellite:"),
(" ", ":pager:"),
(" ", ":radio:"),
(" ", ":level_slider:"),
(" ", ":control_knobs:"),
(" ", ":film_projector:"),
(" ", ":video_game:"),
(" ", ":crystal_ball:"),
(" ", ":dna:"),
(" ", ":atom_symbol:"),
(" ", ":alembic:"),
(" ", ":black_hole:"),
(" ", ":compass:"),
(" ", ":hourglass_flowing_sand:"),
(" ", ":mainframe:"),
(" ", ":electric_plug:"),
(" ", ":flying_saucer:"),
(" ", ":robot:"),
(" ", ":test_tube:"),
(" ", ":petri_dish:"),
(" ", ":microscope:"),
(" ", ":telescope:"),
(" ", ":milky_way:"),
(" ", ":fire:"),
(" ", ":ice:"),
(" ", ":radioactive:"),
(" ", ":biohazard:"),
(" ", ":magnet:"),
(" ", ":oil_drum:"),
]
try:
if not token:
raise ValueError("GH_TOKEN is missing. Set it in Repository Secrets.")
# Read last status to ensure we don't pick it again immediately
last_status = ""
if state_file.exists():
with open(state_file, "r", encoding="utf-8") as f:
last_status = f.read().strip()
available = [s for s in status_pool if s[0] != last_status]
if not available:
available = status_pool
status_text, emoji = random.choice(available)
response = set_github_status(token, status_text, emoji)
if response.status_code == 200:
res_data = response.json()
if "errors" in res_data:
raise Exception(f"GraphQL: {res_data['errors'][0]['message']}")
# Save selection to state file for future comparison
with open(state_file, "w", encoding="utf-8") as f:
f.write(status_text)
# Pass both text and emoji to the stats logger
update_stats(
base_path, len(status_pool), status_text=status_text, emoji=emoji
)
print(f"Set: {status_text}")
else:
raise Exception(f"HTTP {response.status_code}")
except Exception as e:
print(f"Error: {e}")
# Log failure while preserving the pool size metric
update_stats(base_path, len(status_pool), error=e)
sys.exit(1)
if __name__ == "__main__":
update_github_status()