-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoday.py
executable file
·123 lines (93 loc) · 3.56 KB
/
today.py
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
#!/bin/env python3
import requests
import datetime
import time
import argparse
import sys
import os
import pathlib
import re
def load_dotenv():
dotenv_p = pathlib.Path(".env")
if not dotenv_p.is_file():
print("NOTE: .env not found")
return
with open(dotenv_p, "r") as fp:
for m in re.finditer(r"^([a-zA-Z][a-zA-Z_0-9]*)=(.*)$", fp.read(), flags=re.MULTILINE):
os.environ[m[1]] = m[2]
class AocError(Exception): ...
def main() -> int:
load_dotenv()
parser = argparse.ArgumentParser(__file__)
parser.add_argument("--dry", action="store_true", help="only displays what endpoints will be called and files affected")
parser.add_argument("-d", "--day", type=int, help="override the day")
parser.add_argument("-y", "--year", type=int, help="overrid the year")
args = parser.parse_args()
is_dry = args.dry
# check that requests are limited to once every 15-minutes
cache_folder = pathlib.Path(os.getenv("HOME")) / ".cache"
timestamp = cache_folder / "aoc_today_ts"
if timestamp.exists():
try:
with open(timestamp, "r") as fp:
ts = float(fp.read())
except ValueError:
raise AocError("timestamp file was incorrectly formatted")
if time.time() - ts < 15 * 60:
raise AocError("requests are limited to once every 15 minutes")
else:
cache_folder.mkdir(parents=True, exist_ok=True)
is_manual = args.year is not None or args.day is not None
# Get the correct time
utcoffset = -datetime.timedelta(hours=5)
timezone = datetime.timezone(utcoffset)
today = datetime.datetime.now(tz=timezone)
year = today.year if args.year is None else args.year
month = today.month if not is_manual else 12
day = today.day if args.day is None else args.day
resolved_day = datetime.datetime(year=year, month=month, day=day, tzinfo=timezone)
if today < resolved_day:
raise AocError("can't fetch days in the future")
if month != 12:
raise AocError("It is not december yet...")
base = pathlib.Path("input")
if year != today.year:
base = base / str(year)
path = base / f"day{day}.txt"
if path.exists():
raise AocError(f"this day has already been fetched, manually delete the file ({path}) to allow the script to fetch this day")
if is_dry:
print("new file:", str(path))
else:
base.mkdir(parents=True, exist_ok=True)
if not "AOC_SESSION" in os.environ:
raise AocError("missing session cookie (export AOC_SESSION=<session cookie> or place in .env")
session = os.getenv("AOC_SESSION")
headers = {
"User-Agent": "github.com/RagePly/aoc24 the.hugo.lom@gmail.com",
"Cookie": f"session={session}"
}
endpoint = f"https://adventofcode.com/{year}/day/{day}/input"
if is_dry:
print("endpoint:", endpoint)
print("header:")
for n,v in headers.items():
print(" ", n + ":", v)
else:
res = requests.get(endpoint, headers=headers)
# write the timestamp independant of result
with open(timestamp, "w") as fp:
fp.write(str(time.time()))
if not res.ok:
raise AocError("failed to fetch puzzle input")
content = res.text
with open(path, "w") as fp:
bs = fp.write(content)
print(f"wrote {bs} to {path}")
return 0
if __name__ == "__main__":
try:
sys.exit(main())
except AocError as e:
sys.stderr.write(str(e) + "\n")
sys.exit(1)