Skip to content
This repository was archived by the owner on Dec 28, 2024. It is now read-only.

Commit 607e2ae

Browse files
committed
Add option to auto-fetch puzzle input
1 parent 79380fe commit 607e2ae

File tree

7 files changed

+96
-6
lines changed

7 files changed

+96
-6
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
input/*
22
!input/.gitkeep
33

4+
!input/cache/
5+
input/cache/*
6+
!input/cache/.gitkeep
7+
48
build/*
59
!build/.gitkeep
610

711
.idea
12+
client-env.sh

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ run the solution.
1717
If you don't want to use the client, curl is also an option:
1818
`curl -X POST --data-binary @INPUT_FILE http://localhost/DAY/PART`
1919

20+
### Auto-fetch puzzle input
21+
If you copy the file `./client-env.sh.example` to `./client-env.sh` and fill in your
22+
session token, the client (when running `./client.sh`) can auto-fetch your puzzle
23+
input. You can then run the client as only `./client.sh -day DAY -part PART`.
24+
2025
### Running in Kubernetes
2126
* Install `minikube` and run `./k8s/start-minikube.sh` to create the `aoc2024` cluster.
2227
* Then run `./k8s/build.sh all` to build all the docker images, making them available

client-env.sh.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
# Copy this file as `client-env.sh`, removing the `.example` suffix.
3+
#
4+
# To get the session token, inspect the requests sent to AoC and copy the Cookie-field of the request.
5+
# Instructions here: https://github.com/wimglenn/advent-of-code-wim/issues/1
6+
# Then remove the 'session=' from the beginning of the cookie.
7+
export AOC2024_INPUT_CACHE_PATH='./input/cache'
8+
export AOC2024_SESSION_TOKEN='insert-token-here'

client.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
# a binary file
44
profile_name='aoc2024'
55
url='localhost'
6+
env_file='./client-env.sh'
7+
8+
if [ -f "$env_file" ]; then
9+
source "$env_file"
10+
fi
611

712
if [ -n "$(command -v minikube)" ] && minikube profile list | grep -q "$profile_name"; then
813
echo "Minikube is installed and profile '$profile_name' exists, using minikube ip ($(minikube ip))."

client/run.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,21 @@ func runCmd(args []string) {
2424

2525
validateDayAndPart(*day, *part)
2626

27+
sessionToken := os.Getenv("AOC2024_SESSION_TOKEN")
28+
2729
var input string
2830
switch {
2931
case *file != "":
3032
input = readFile(*file)
33+
case sessionToken != "":
34+
data, err := fetchInput(*day, sessionToken)
35+
if err != nil {
36+
fmt.Printf("Failed to fetch input using session token '%s': %v", sessionToken, err)
37+
os.Exit(1)
38+
}
39+
input = data
3140
default:
32-
fmt.Printf("No input method selected, can't get puzzle input.\n")
41+
fmt.Println("No input method selected and session token not set, can't get puzzle input.")
3342
os.Exit(1)
3443
}
3544

client/utils.go

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,79 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7+
"net/http"
78
"os"
9+
"strings"
810
)
911

1012
func readFile(path string) string {
11-
data, err := os.ReadFile(path)
13+
data, err := readFileSafely(path)
1214
if err != nil {
13-
fmt.Printf("Failed to read file '%s' with error: %v\n", path, err)
15+
fmt.Print(err.Error())
1416
os.Exit(1)
1517
}
18+
return data
19+
}
20+
21+
func readFileSafely(path string) (string, error) {
22+
data, err := os.ReadFile(path)
23+
if err != nil {
24+
return "", fmt.Errorf("failed to read file '%s' with error: %v", path, err)
25+
}
1626

1727
buff := bytes.NewBuffer(data)
18-
input, err := io.ReadAll(buff)
28+
content, err := io.ReadAll(buff)
1929
if err != nil {
20-
fmt.Printf("Failed to parse data from file '%s' with error: %v\n", path, err)
30+
return "", fmt.Errorf("failed to parse data from file '%s' with error: %v", path, err)
31+
}
32+
33+
return string(content), nil
34+
}
35+
36+
func saveFileSafely(path string, content string) error {
37+
err := os.WriteFile(path, []byte(content), 0744)
38+
return err
39+
}
40+
41+
func fetchInput(
42+
day int,
43+
sessionToken string,
44+
) (string, error) {
45+
cachePath := os.Getenv("AOC2024_INPUT_CACHE_PATH")
46+
var cacheFile string
47+
cacheEnabled := false
48+
if cachePath != "" {
49+
cacheEnabled = true
50+
cacheFile = fmt.Sprintf("%s/day%d-%s", cachePath, day, sessionToken)
51+
52+
content, err := readFileSafely(cacheFile)
53+
if err == nil {
54+
return content, nil
55+
}
56+
}
57+
58+
url := fmt.Sprintf("https://adventofcode.com/2024/day/%d/input", day)
59+
req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
60+
if err != nil {
61+
return "", err
62+
}
63+
req.Header.Set("Cookie", fmt.Sprintf("session=%s", sessionToken))
64+
65+
client := &http.Client{}
66+
resp, err := client.Do(req)
67+
if err != nil {
68+
return "", err
69+
}
70+
defer resp.Body.Close()
71+
body, err := io.ReadAll(resp.Body)
72+
if err != nil {
73+
return "", err
74+
}
75+
strBody, _ := strings.CutSuffix(string(body), "\n")
76+
77+
if cacheEnabled {
78+
_ = saveFileSafely(cacheFile, strBody)
2179
}
2280

23-
return string(input)
81+
return strBody, nil
2482
}

input/cache/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)