Merge branch '2-post-curated-content' into 'develop'

Use discord to enable manual posting of HN links

Closes #2

See merge request ekzyis/hnbot!4
This commit is contained in:
ekzyis 2023-04-19 23:19:42 +00:00
commit 75597bab8e
6 changed files with 90 additions and 8 deletions

View File

@ -1,2 +1,3 @@
SN_AUTH_COOKIE=
DISCORD_WEBHOOK=
DISCORD_TOKEN=

View File

@ -6,12 +6,15 @@ import (
"log"
"net/http"
"github.com/bwmarrin/discordgo"
"github.com/joho/godotenv"
"github.com/namsral/flag"
)
var (
DiscordWebhook string
DiscordToken string
DiscordClient *discordgo.Session
)
type DiscordEmbedFooter struct {
@ -37,10 +40,45 @@ func init() {
log.Fatal("Error loading .env file")
}
flag.StringVar(&DiscordWebhook, "DISCORD_WEBHOOK", "", "Webhook to send logs to discord")
flag.StringVar(&DiscordToken, "DISCORD_TOKEN", "", "Discord bot token")
flag.Parse()
if DiscordWebhook == "" {
log.Fatal("DISCORD_WEBHOOK not set")
}
if DiscordToken == "" {
log.Fatal("DISCORD_TOKEN not set")
}
initBot()
}
func initBot() {
var err error
DiscordClient, err = discordgo.New(DiscordToken)
if err != nil {
log.Fatal("error creating discord session:", err)
}
DiscordClient.AddHandler(func(s *discordgo.Session, event *discordgo.Ready) {
log.Println("Logged in as", event.User.Username)
})
DiscordClient.AddHandler(onMessage)
DiscordClient.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsMessageContent
err = DiscordClient.Open()
if err != nil {
log.Fatal("error opening connection to discord: ", err, " -- Is your token correct?")
}
}
func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
// Ignore all messages created by the bot itself
if m.Author.ID == s.State.User.ID {
return
}
id, err := ParseHackerNewsLink(m.Content)
if err != nil {
return
}
story := FetchStoryById(id)
PostStoryToStackerNews(&story)
}
func SendEmbedToDiscord(embed DiscordEmbed) {

15
go.mod
View File

@ -3,11 +3,18 @@ module gitlab.com/ekzyis/hnbot
go 1.20
require (
github.com/dustin/go-humanize v1.0.1
github.com/joho/godotenv v1.5.1
github.com/namsral/flag v1.7.4-pre
github.com/stretchr/testify v1.8.2
)
require (
github.com/bwmarrin/discordgo v0.27.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/namsral/flag v1.7.4-pre // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.8.2 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

13
go.sum
View File

@ -1,8 +1,12 @@
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/namsral/flag v1.7.4-pre h1:b2ScHhoCUkbsq0d2C15Mv+VU8bl8hAXV8arnWiOHNZs=
@ -16,6 +20,15 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

18
hn.go
View File

@ -2,9 +2,12 @@ package main
import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"regexp"
"strconv"
)
type ItemID = int
@ -23,11 +26,13 @@ type Story struct {
var (
HackerNewsUrl string
HackerNewsFirebaseUrl string
HackerNewsLinkRegexp *regexp.Regexp
)
func init() {
HackerNewsUrl = "https://news.ycombinator.com"
HackerNewsFirebaseUrl = "https://hacker-news.firebaseio.com/v0"
HackerNewsLinkRegexp = regexp.MustCompile(`(?:https?:\/\/)?news\.ycombinator\.com\/item\?id=([0-9]+)`)
}
func FetchHackerNewsTopStories() []Story {
@ -79,6 +84,19 @@ func FetchStoryById(id ItemID) Story {
return story
}
func ParseHackerNewsLink(link string) (ItemID, error) {
match := HackerNewsLinkRegexp.FindStringSubmatch(link)
if len(match) == 0 {
return -1, errors.New("input is not a hacker news link")
}
id, err := strconv.Atoi(match[1])
if err != nil {
// this should never happen
panic(err)
}
return id, nil
}
func HackerNewsUserLink(user string) string {
return fmt.Sprintf("%s/user?id=%s", HackerNewsUrl, user)
}

13
main.go
View File

@ -1,9 +1,14 @@
package main
import "time"
func main() {
stories := FetchHackerNewsTopStories()
filtered := CurateContentForStackerNews(&stories)
for _, story := range *filtered {
PostStoryToStackerNews(&story)
for {
stories := FetchHackerNewsTopStories()
filtered := CurateContentForStackerNews(&stories)
for _, story := range *filtered {
PostStoryToStackerNews(&story)
}
time.Sleep(time.Hour)
}
}