1- #!/bin/python
1+ #!/usr/ bin/python
22
33import os
44import pathlib
55
66import click
7- import ecd
7+ import requests
88from lib import running
99
10+ from Crypto .Cipher import AES
11+ from Crypto .Util .Padding import unpad
12+
1013
1114class Runner (running .Runner ):
1215
1316 def solutions_path (self ) -> pathlib .Path :
1417 """Return the solution file."""
1518 return pathlib .Path (f"{ self .year } /solutions.txt" )
1619
20+ def write_solutions (self , year : int , day : int ) -> str :
21+ """Write the solutions to file."""
22+ cookie = (pathlib .Path (os .getenv ("XDG_DATA_HOME" )) / "cookies/ec" ).read_text ().strip ()
23+ session = requests .Session ()
24+ session .cookies .set ("everybody-codes" , cookie )
25+
26+ year = year .removeprefix ("event" ).removeprefix ("story" ).removeprefix ("0" )
27+ data = session .get (f"https://api.everybody.codes/event/{ year } /quest/{ day } " ).json ()
28+ want = [f"answer{ i } " for i in range (1 , 4 )]
29+ if not set (want ).issubset (set (data )):
30+ return None
31+ solutions = [line for line in self .solutions_path ().read_text ().splitlines () if not line .split (maxsplit = 1 )[0 ].startswith (f"{ day :02} " )]
32+ answers = []
33+ for part in range (1 , 4 ):
34+ answers .append (f"{ day :02} .{ part } { data [f"answer{ part } " ]} " )
35+ self .solutions_path ().write_text ("\n " .join (solutions + answers ) + "\n " )
36+ return answers
37+
1738 def input_path (self , part : int ) -> pathlib .Path :
1839 """Return the input file."""
1940 p = pathlib .Path (f"{ self .year } /inputs/{ self .day :02} .{ part } .txt" )
@@ -28,11 +49,22 @@ def module_name(self) -> str:
2849
2950 def download_input (self , year : int , day : int , part : int ) -> str | None :
3051 """Download the input."""
31- event = int (year .replace ("event" , "" ))
32- data = ecd .get_inputs (quest = day , event = event )
33- if str (part ) not in data :
34- return None
35- return data [str (part )]
52+ # Hard coded per account, see https://api.everybody.codes/user/me
53+ seed = 49
54+ year = year .removeprefix ("event" ).removeprefix ("story" ).removeprefix ("0" )
55+
56+ cookie = (pathlib .Path (os .getenv ("XDG_DATA_HOME" )) / "cookies/ec" ).read_text ().strip ()
57+
58+ session = requests .Session ()
59+ session .cookies .set ("everybody-codes" , cookie )
60+
61+ data = session .get (f"https://everybody.codes/assets/{ year } /{ day } /input/{ seed } .json" ).json ()
62+ metadata = session .get (f"https://api.everybody.codes/event/{ year } /quest/{ day } " ).json ()
63+
64+ aes_key = metadata [f"key{ part } " ].encode ()
65+ cipher = AES .new (aes_key , AES .MODE_CBC , iv = aes_key [:AES .block_size ])
66+ plaintext = cipher .decrypt (bytes .fromhex (data [str (part )]))
67+ return unpad (plaintext , AES .block_size ).decode ()
3668
3769
3870@click .command ()
0 commit comments