update scripts

This commit is contained in:
alexchao26
2021-12-01 20:34:10 -05:00
parent 2888e20870
commit b8c031d229
21 changed files with 405 additions and 305 deletions
+82
View File
@@ -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)
}
}
+29
View File
@@ -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!")
}
+84
View File
@@ -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
}
}