From f853cb5050903f5ebeb116baf8bbf43731d21762 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 16 Apr 2023 23:26:31 +0200 Subject: [PATCH] Add function to comment HN story --- .env.template | 3 ++- hn.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ sn.go | 4 +-- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/.env.template b/.env.template index 959dded..8b8c8ec 100644 --- a/.env.template +++ b/.env.template @@ -1 +1,2 @@ -AUTH_COOKIE= \ No newline at end of file +SN_AUTH_COOKIE= +HN_AUTH_COOKIE= diff --git a/hn.go b/hn.go index f200536..c42fb7b 100644 --- a/hn.go +++ b/hn.go @@ -3,8 +3,16 @@ package main import ( "encoding/json" "fmt" + "io/ioutil" "log" "net/http" + "net/url" + "regexp" + "strconv" + "strings" + + "github.com/joho/godotenv" + "github.com/namsral/flag" ) type ItemID = int @@ -23,11 +31,21 @@ type Story struct { var ( HackerNewsUrl string HackerNewsFirebaseUrl string + HnAuthCookie string ) func init() { HackerNewsUrl = "https://news.ycombinator.com" HackerNewsFirebaseUrl = "https://hacker-news.firebaseio.com/v0" + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } + flag.StringVar(&HnAuthCookie, "HN_AUTH_COOKIE", "", "Cookie required for authorizing requests to news.ycombinator.com") + flag.Parse() + if HnAuthCookie == "" { + log.Fatal("HN_AUTH_COOKIE not set") + } } func FetchHackerNewsTopStories() []Story { @@ -79,6 +97,61 @@ func FetchStoryById(id ItemID) Story { return story } +func FetchHackerNewsItemHMAC(id ItemID) string { + hnUrl := fmt.Sprintf("%s/item?id=%d", HackerNewsUrl, id) + req, err := http.NewRequest("GET", hnUrl, nil) + if err != nil { + panic(err) + } + // Cookie header must be set to fetch the correct HMAC for posting comments + req.Header.Set("Cookie", HnAuthCookie) + client := http.DefaultClient + resp, err := client.Do(req) + if err != nil { + panic(err) + } + log.Printf("GET %s %d\n", hnUrl, resp.StatusCode) + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Failed to read response body:", err) + } + + // Find HMAC in body + re := regexp.MustCompile(`name="hmac" value="([a-z0-9]+)"`) + match := re.FindStringSubmatch(string(body)) + if len(match) == 0 { + log.Fatal("No HMAC found") + } + hmac := match[1] + + return hmac +} + +func CommentHackerNewsStory(text string, id ItemID) { + hmac := FetchHackerNewsItemHMAC(id) + + hnUrl := fmt.Sprintf("%s/comment", HackerNewsUrl) + data := url.Values{} + data.Set("parent", strconv.Itoa(id)) + data.Set("goto", fmt.Sprintf("item?id=%d", id)) + data.Set("text", text) + data.Set("hmac", hmac) + req, err := http.NewRequest("POST", hnUrl, strings.NewReader(data.Encode())) + if err != nil { + panic(err) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Cookie", HnAuthCookie) + client := http.DefaultClient + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + log.Printf("POST %s %d\n", hnUrl, resp.StatusCode) +} + func HackerNewsUserLink(user string) string { return fmt.Sprintf("%s/user?id=%s", HackerNewsUrl, user) } diff --git a/sn.go b/sn.go index 0f42094..730b836 100644 --- a/sn.go +++ b/sn.go @@ -51,10 +51,10 @@ func init() { if err != nil { log.Fatal("Error loading .env file") } - flag.StringVar(&SnAuthCookie, "AUTH_COOKIE", "", "Cookie required for authorizing requests to stacker.news/api/graphql") + flag.StringVar(&SnAuthCookie, "SN_AUTH_COOKIE", "", "Cookie required for authorizing requests to stacker.news/api/graphql") flag.Parse() if SnAuthCookie == "" { - log.Fatal("AUTH_COOKIE not set") + log.Fatal("SN_AUTH_COOKIE not set") } }