55# curl -H "Cookie: session=$(cat ~/.adventofcode.session)" https://adventofcode.com/2024 -o 2024.html
66
77
8+ import os
89import re
910import sys
11+ import time
1012from pathlib import Path
1113
1214import requests
1315
14- if len (sys .argv ) != 2 :
15- print (f"Usage: { sys .argv [0 ]} <file>" )
16+
17+ def get_cookie ():
18+ for line in Path ("~/.adventofcode.session" ).expanduser ().read_text ().splitlines ():
19+ line = line .strip ()
20+ if len (line ) == 128 and line .startswith ("53" ):
21+ return line
22+ print ("session cookie not found" )
1623 exit (1 )
1724
18- f = sys .argv [1 ]
19- if Path (f ).is_file ():
20- calendar = Path (f ).read_text ()
21- elif f .isdigit ():
22- s = Path ("~/.adventofcode.session" ).expanduser ()
23- if s .is_file ():
24- session = s .read_text ().strip ()
25+
26+ def get_calendar (f ):
27+ f = str (f )
28+ if Path (f ).is_file ():
29+ calendar = Path (f ).read_text ()
30+
31+ elif Path (f ).with_suffix (".html" ).is_file ():
32+ calendar = Path (f ).with_suffix (".html" ).read_text ()
33+
34+ elif f .isdigit ():
35+ session = get_cookie ()
2536 content = requests .get (
2637 f"https://adventofcode.com/{ f } " ,
2738 headers = {
3445
3546 calendar = content .decode ()
3647
48+ else :
49+ print (f"Calendar not found: { f } " )
50+ exit ()
51+
52+ return calendar
53+
3754
3855def rgb (s : str ) -> str :
3956 if "color:" not in s :
@@ -44,13 +61,7 @@ def rgb(s: str) -> str:
4461 print ("color problem:" , s )
4562 exit (2 )
4663 if len (rgb ) == 3 :
47- if rgb == "ccc" :
48- rgb = "cccccc"
49- elif rgb == "333" :
50- rgb = "333333"
51- else :
52- print (f"Unknown color: { rgb } " )
53- exit ()
64+ rgb = rgb [0 ] + rgb [0 ] + rgb [1 ] + rgb [1 ] + rgb [2 ] + rgb [2 ]
5465 elif len (rgb ) == 6 :
5566 pass
5667 else :
@@ -64,43 +75,183 @@ def rgb(s: str) -> str:
6475 return f"\033 [38;2;{ r } ;{ g } ;{ b } m"
6576
6677
67- colors = {}
68- colors [None ] = rgb ("#606060;" ) # "\033[0m"
78+ def remove_between (line , sa , sb ):
79+ while True :
80+ a = line .find (sa )
81+ if a == - 1 :
82+ break
83+ b = line .find (sb , a )
84+ if a == - 1 :
85+ break
86+
87+ line = line [:a ] + line [b + len (sb ) :]
88+ return line
89+
90+
91+ def sunbeam_2019 (line ):
92+ sa = '<span class="sunbeam"'
93+ sb = ">"
94+ color = rgb ("color: #ffff66;" )
95+ while True :
96+ a = line .find (sa )
97+ if a == - 1 :
98+ break
99+ b = line .find (sb , a )
100+ if a == - 1 :
101+ break
102+
103+ line = line [:a ] + color + line [b + len (sb ) :]
104+ color = ""
105+
106+ line = remove_between (line , '<span style="animation-delay:' , ">" )
107+ line = line .replace ("*</span></span>" , "" )
108+ return line
109+
110+
111+ def text_shadow_2019 (line ):
112+ sa = '<span style="text-shadow:'
113+ sb = ">"
114+ while True :
115+ a = line .find (sa )
116+ if a == - 1 :
117+ break
118+ b = line .find (sb , a )
119+ if a == - 1 :
120+ break
121+
122+ color = ""
123+ text_shadow = line [a : b + len (sb )]
124+ for s in text_shadow .split ():
125+ if s .startswith ("#" ):
126+ color = rgb ("color: " + s .split ("," )[0 ] + ";" )
127+ break
128+
129+ line = line [:a ] + color + line [b + len (sb ) :]
130+ return line
131+
69132
133+ def ascii_calendar (calendar ):
134+ colors = {}
135+ colors [None ] = rgb ("color: #606060;" ) # "\033[0m"
70136
71- for line in calendar .splitlines ():
137+ for line in calendar .splitlines ():
138+ if line .startswith (".calendar .calendar-color-" ):
139+ line = line .split (maxsplit = 2 )
140+ color = line [1 ][1 :]
141+ code = rgb (line [2 ])
72142
73- if line . startswith ( ".calendar .calendar- color-" ):
143+ colors [ color ] = code
74144
75- line = line .split (maxsplit = 2 )
76- color = line [1 ][1 :]
77- code = rgb (line [2 ])
145+ year = int (re .search (r"<title>Advent of Code (\d+)</title>" , calendar ).group (1 ))
78146
79- colors [color ] = code
147+ if year == 2015 :
148+ colors [None ] = rgb ("color: #009900;" )
149+ colors ["calendar-ornament0" ] = rgb ("color: #0066ff;" )
150+ colors ["calendar-ornament1" ] = rgb ("color: #ff9900;" )
151+ colors ["calendar-ornament2" ] = rgb ("color: #ff0000;" )
152+ colors ["calendar-ornament3" ] = rgb ("color: #ffff66;" )
153+ colors ["calendar-lightbeam" ] = rgb ("color: #ffff66;" )
154+ colors ["calendar-trunk" ] = rgb ("color: #cccccc;" )
80155
156+ if year == 2016 :
157+ colors ["calendar-streets" ] = rgb ("color:#666666;" )
158+ colors ["calendar-window-blue" ] = rgb ("color:#0066ff;" )
159+ colors ["calendar-window-yellow" ] = rgb ("color:#ffff66;" )
160+ colors ["calendar-window-green" ] = rgb ("color:#009900;" )
161+ colors ["calendar-window-red" ] = rgb ("color:#ff0000;" )
162+ colors ["calendar-window-dark" ] = rgb ("color:#333333;" )
163+ colors ["calendar-window-brown" ] = rgb ("color:#553322;" )
164+ colors ["calendar-antenna-star" ] = rgb ("color: #ffff66;" )
165+ colors ["calendar-antenna-signal0" ] = rgb ("color: #ffff66;" )
166+ colors ["calendar-antenna-signal1" ] = rgb ("color: #ffff66;" )
167+ colors ["calendar-antenna-signal2" ] = rgb ("color: #ffff66;" )
168+ colors ["calendar-antenna-signal3" ] = rgb ("color: #ffff66;" )
169+ colors ["calendar-antenna-signal4" ] = rgb ("color: #ffff66;" )
170+ colors ["calendar-antenna-signal5" ] = rgb ("color: #ffff66;" )
81171
82- calendar = re .search (r'<pre class="calendar.*?">(.+?)</pre>' , calendar , re .DOTALL ).group (1 )
83- for line in calendar .splitlines ():
172+ if year == 2017 :
173+ colors ["calendar-ornament0" ] = rgb ("color:#ff9900;" )
174+ colors ["calendar-ornament5" ] = rgb ("color:#990099;" )
175+ colors ["calendar-verycomplete" ] = rgb ("color:#ffff66;" )
176+ colors ["calendar-ornament2" ] = rgb ("color:#aaaaaa;" )
177+ colors ["calendar-ornament3" ] = rgb ("color:#ff0000;" )
178+ colors ["calendar-ornament1" ] = rgb ("color:#0066ff;" )
179+ colors ["calendar-ornament4" ] = rgb ("color:#009900;" )
180+
181+ if year == 2019 :
182+ colors ["calendar-s" ] = rgb ("color: #333;" )
183+
184+ calendar = re .search (r'<pre class="calendar.*?">(.+?)</pre>' , calendar , re .DOTALL ).group (1 )
185+ for line in calendar .splitlines ():
186+ # if "calendar-verycomplete" not in line and "calendar-mark-verycomplete" not in line:
187+ # print(line)
188+ # continue
189+
190+ line = remove_between (line , "<a " , ">" )
191+ line = remove_between (line , '<span class="calendar-day">' , "</a>" )
192+
193+ if year == 2017 :
194+ if 'span class="calendar-print-text' in line :
195+ continue
196+ line = line .replace ("</i>" , "" )
197+ line = line .replace ("<i>" , "" )
198+ line = remove_between (line , '<span style="animation-delay:' , ">" )
199+
200+ if year == 2019 :
201+ line = remove_between (line , '<span style="position:relative;' , ">" )
202+ # line = remove_between(line, '<span style="text-shadow', ">")
203+ line = text_shadow_2019 (line )
204+ line = sunbeam_2019 (line )
205+
206+ if year == 2024 :
207+ line = line .replace ("</i>" , "" )
208+ line = line .replace ("<i>" , "" )
209+ line = line .replace ('<span id="calendar-monorail-8">' , "" )
210+ line = line .replace ('<span id="calendar-monorail-9">' , "" )
211+ line = line .replace ('<span class="calendar-9-path">.</span>' , "" )
212+
213+ line = re .sub (r'<span class="(.+?)">' , lambda x : colors .get (x .group (1 ), "" ), line )
214+
215+ # line = re.sub(r"(<span.+?>)(.+?)(</span>)", lambda m: f"{rgb(m[1])}{m[2]}\033[0m", line)
216+ line = re .sub (r"(<span.+?>)(.+?)(</span>)" , lambda m : "" , line )
217+
218+ line = line .replace ("</span>" , colors [None ])
219+
220+ line = line .replace (">" , ">" )
221+ line = line .replace ("<" , "<" )
222+ line = line .replace (""" , "'" )
223+ line = line .replace ("&" , "&" )
84224
85- if "calendar-verycomplete" not in line :
86225 print (line )
87- continue
88226
89- a = line .index (">" ) + 1
90- b = line .find ('<span class="calendar-day">' )
91- line = line [a :b ]
227+ print ("\033 [0m" )
228+
92229
93- line = re .sub (r'<span class="(.+?)">' , lambda x : colors .get (x .group (1 ), "" ), line )
230+ def main ():
231+ if len (sys .argv ) >= 2 and sys .argv [1 ] == "rec" :
232+ if len (sys .argv ) == 2 :
233+ os .system (f"asciinema rec --overwrite calendars.cast --command '{ __file__ } rec years'" )
234+ os .system ("agg calendars.cast calendars.gif --rows 37 --cols 56 --font-size 6" )
235+ else :
94236
95- # line = re.sub(r"(<span.+?>)(.+?)(</span>)", lambda m: f"{rgb(m[1])}{m[2]}\033[0m", line)
96- line = re .sub (r"(<span.+?>)(.+?)(</span>)" , lambda m : "" , line )
237+ for year in range (2015 , 2026 ):
238+ print (f"\033 [?25l\033 [H\033 [2J\033 [1;32m{ year } \033 [0m" )
239+ ascii_calendar (get_calendar (year ))
240+ time .sleep (2 )
97241
98- line = line . replace ( "</span>" , colors [ None ] )
99- line = line . replace ( "</i>" , colors [ None ])
100- line = line . replace ( "<i>" , " \033 [2m" )
242+ print ( " \033 [25h" )
243+
244+ exit ( )
101245
102- line = line . replace ( ">" , ">" )
103- line = line . replace ( "<" , "< " )
104- line = line . replace ( """ , "'" )
246+ if len ( sys . argv ) != 2 :
247+ print ( f"Usage: { sys . argv [ 0 ] } [<file> | <year> | rec] " )
248+ exit ( 1 )
105249
106- print (line + "\033 [0m" )
250+ ascii_calendar (get_calendar (sys .argv [1 ]))
251+
252+
253+ if __name__ == "__main__" :
254+ try :
255+ main ()
256+ except KeyboardInterrupt :
257+ pass
0 commit comments