mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-03 02:38:28 +02:00
update scripts
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
// Package aoc gets inputs and prompts from adventofcode.com
|
||||
package aoc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ParseFlags() (day, year int, cookie string) {
|
||||
today := time.Now()
|
||||
flag.IntVar(&day, "day", today.Day(), "day number to fetch, 1-25")
|
||||
flag.IntVar(&year, "year", today.Year(), "AOC year")
|
||||
// defaults to env variable
|
||||
flag.StringVar(&cookie, "cookie", os.Getenv("AOC_SESSION_COOKIE"), "AOC session cookie")
|
||||
flag.Parse()
|
||||
|
||||
if day > 25 || day < 1 {
|
||||
log.Fatalf("day out of range: %d", day)
|
||||
}
|
||||
|
||||
if year < 2015 {
|
||||
log.Fatalf("year is before 2015: %d", year)
|
||||
}
|
||||
|
||||
if cookie == "" {
|
||||
log.Fatalf("no session cookie set on flag or env var (AOC_SESSION_COOKIE)")
|
||||
}
|
||||
|
||||
return day, year, cookie
|
||||
}
|
||||
|
||||
func GetWithAOCCookie(url string, cookie string) []byte {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("making request: %s", err)
|
||||
}
|
||||
|
||||
sessionCookie := http.Cookie{
|
||||
Name: "session",
|
||||
Value: cookie,
|
||||
}
|
||||
req.AddCookie(&sessionCookie)
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf("making request: %s", err)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("reading response body: %s", err)
|
||||
}
|
||||
fmt.Println("response length is", len(body))
|
||||
|
||||
// specific error message from AOC site
|
||||
if strings.HasPrefix(string(body), "Please don't repeatedly") {
|
||||
log.Fatalf("Repeated request github.com/alexchao26/advent-of-code-go error")
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func WriteToFile(filename string, contents []byte) {
|
||||
err := os.MkdirAll(filepath.Dir(filename), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("making directory: %s", err)
|
||||
}
|
||||
err = os.WriteFile(filename, contents, os.FileMode(0644))
|
||||
if err != nil {
|
||||
log.Fatalf("writing file: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package aoc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
func GetInput(day, year int, cookie string) {
|
||||
fmt.Printf("fetching for day %d, year %d\n", day, year)
|
||||
|
||||
// make the request
|
||||
url := fmt.Sprintf("https://adventofcode.com/%d/day/%d/input", year, day)
|
||||
body := GetWithAOCCookie(url, cookie)
|
||||
|
||||
if strings.HasPrefix(string(body), "Puzzle inputs differ by user") {
|
||||
panic("'Puzzle inputs differ by user' response")
|
||||
}
|
||||
|
||||
// write to file
|
||||
filename := filepath.Join(util.Dirname(), "../..", fmt.Sprintf("%d/day%02d/input.txt", year, day))
|
||||
WriteToFile(filename, body)
|
||||
|
||||
fmt.Println("Wrote to file: ", filename)
|
||||
|
||||
fmt.Println("Done!")
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package aoc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
func GetPrompt(day, year int, cookie string) {
|
||||
fmt.Printf("fetching for day %d, year %d\n", day, year)
|
||||
|
||||
// make the request
|
||||
url := fmt.Sprintf("https://adventofcode.com/%d/day/%d", year, day)
|
||||
body := GetWithAOCCookie(url, cookie)
|
||||
|
||||
// parse the dang html
|
||||
prompt := parseHTML(body)
|
||||
|
||||
// write to file
|
||||
filename := filepath.Join(util.Dirname(), "../../", fmt.Sprintf("%d/day%02d/prompt.md", year, day))
|
||||
WriteToFile(filename, []byte(prompt))
|
||||
|
||||
fmt.Println("Wrote prompt to file: ", filename)
|
||||
|
||||
fmt.Println("Done!")
|
||||
}
|
||||
|
||||
// uses dfsHTML function once to get the class=day-desc html nodes, then parse
|
||||
// the text inside of them
|
||||
func parseHTML(htmlIn []byte) (promptOnly string) {
|
||||
strBuilder := strings.Builder{}
|
||||
node, _ := html.Parse(bytes.NewReader(htmlIn))
|
||||
|
||||
dayDescNodes := dfsHTML(node, cbFindDayDescClass)
|
||||
dayDescNodesMap := map[*html.Node]bool{}
|
||||
|
||||
for _, ddNode := range dayDescNodes {
|
||||
dayDescNodesMap[ddNode.(*html.Node)] = true
|
||||
dfsHTML(ddNode.(*html.Node), cbParseHTMLText(&strBuilder, dayDescNodesMap))
|
||||
}
|
||||
|
||||
return strBuilder.String()
|
||||
}
|
||||
|
||||
// function takes in a node and a callback that is run on each node
|
||||
// callback returns a slice of interfaces which are returned by dfs
|
||||
func dfsHTML(node *html.Node, cb func(*html.Node) []interface{}) []interface{} {
|
||||
var sli []interface{}
|
||||
for child := node.FirstChild; child != nil; child = child.NextSibling {
|
||||
if cb(child) != nil {
|
||||
sli = append(sli, child)
|
||||
}
|
||||
sli = append(sli, dfsHTML(child, cb)...)
|
||||
}
|
||||
return sli
|
||||
}
|
||||
|
||||
func cbFindDayDescClass(node *html.Node) []interface{} {
|
||||
for _, attr := range node.Attr {
|
||||
if attr.Key == "class" && attr.Val == "day-desc" {
|
||||
// fmt.Println("day-desc node found!")
|
||||
return []interface{}{node}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cbParseHTMLText(builder *strings.Builder, dayDescNodesMap map[*html.Node]bool) func(*html.Node) []interface{} {
|
||||
return func(node *html.Node) []interface{} {
|
||||
if node.Type == html.TextNode {
|
||||
builder.WriteString(node.Data)
|
||||
}
|
||||
if node.Parent != nil && dayDescNodesMap[node.Parent] {
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user