Show dupes in discord

This commit is contained in:
ekzyis 2023-04-25 00:42:11 +02:00
parent 75597bab8e
commit 6010e47dde
2 changed files with 103 additions and 11 deletions

View File

@ -3,10 +3,13 @@ package main
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt"
"log" "log"
"net/http" "net/http"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"github.com/dustin/go-humanize"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/namsral/flag" "github.com/namsral/flag"
) )
@ -22,12 +25,19 @@ type DiscordEmbedFooter struct {
IconUrl string `json:"icon_url"` IconUrl string `json:"icon_url"`
} }
type DiscordEmbedField struct {
Name string `json:"name"`
Value string `json:"value"`
Inline bool `json:"inline"`
}
type DiscordEmbed struct { type DiscordEmbed struct {
Title string `json:"title"` Title string `json:"title"`
Url string `json:"url"` Url string `json:"url"`
Color int `json:"color"` Color int `json:"color"`
Footer DiscordEmbedFooter `json:"footer"` Footer DiscordEmbedFooter `json:"footer"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
Fields []DiscordEmbedField `json:"fields"`
} }
type DiscordWebhookPayload struct { type DiscordWebhookPayload struct {
@ -78,7 +88,66 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
return return
} }
story := FetchStoryById(id) story := FetchStoryById(id)
PostStoryToStackerNews(&story) id, err = PostStoryToStackerNews(&story)
if err != nil {
var dupesErr *DupesError
if errors.As(err, &dupesErr) {
SendDupesErrorToDiscord(dupesErr)
} else {
log.Fatal("unexpected error returned")
}
}
}
func SendDupesErrorToDiscord(dupesErr *DupesError) {
title := fmt.Sprintf("%d dupe(s) found for %s:", len(dupesErr.Dupes), dupesErr.Url)
color := 0xffc107
var fields []DiscordEmbedField
for _, dupe := range dupesErr.Dupes {
fields = append(fields,
DiscordEmbedField{
Name: "Title",
Value: dupe.Title,
Inline: false,
},
DiscordEmbedField{
Name: "Id",
Value: StackerNewsItemLink(dupe.Id),
Inline: true,
},
DiscordEmbedField{
Name: "Url",
Value: dupe.Url,
Inline: true,
},
DiscordEmbedField{
Name: "User",
Value: dupe.User.Name,
Inline: true,
},
DiscordEmbedField{
Name: "Created",
Value: humanize.Time(dupe.CreatedAt),
Inline: true,
},
DiscordEmbedField{
Name: "Sats",
Value: fmt.Sprint(dupe.Sats),
Inline: true,
},
DiscordEmbedField{
Name: "Comments",
Value: fmt.Sprint(dupe.NComments),
Inline: true,
},
)
}
embed := DiscordEmbed{
Title: title,
Color: color,
Fields: fields,
}
SendEmbedToDiscord(embed)
} }
func SendEmbedToDiscord(embed DiscordEmbed) { func SendEmbedToDiscord(embed DiscordEmbed) {

33
sn.go
View File

@ -18,10 +18,17 @@ type GraphQLPayload struct {
Variables map[string]interface{} `json:"variables,omitempty"` Variables map[string]interface{} `json:"variables,omitempty"`
} }
type SnUser struct {
Name string `json:"name"`
}
type Dupe struct { type Dupe struct {
Id int `json:"id,string"` Id int `json:"id,string"`
Url string `json:"url"` Url string `json:"url"`
Title string `json:"title"` Title string `json:"title"`
User SnUser `json:"user"`
CreatedAt time.Time `json:"createdAt"`
Sats int `json:"sats"`
NComments int `json:"ncomments"`
} }
type DupesResponse struct { type DupesResponse struct {
@ -30,6 +37,15 @@ type DupesResponse struct {
} `json:"data"` } `json:"data"`
} }
type DupesError struct {
Url string
Dupes []Dupe
}
func (e *DupesError) Error() string {
return fmt.Sprintf("%s has %d dupes", e.Url, len(e.Dupes))
}
type User struct { type User struct {
Name string `json:"name"` Name string `json:"name"`
} }
@ -123,6 +139,12 @@ func FetchStackerNewsDupes(url string) *[]Dupe {
id id
url url
title title
user {
name
}
createdAt
sats
ncomments
} }
}`, }`,
Variables: map[string]interface{}{ Variables: map[string]interface{}{
@ -141,11 +163,11 @@ func FetchStackerNewsDupes(url string) *[]Dupe {
return &dupesResp.Data.Dupes return &dupesResp.Data.Dupes
} }
func PostStoryToStackerNews(story *Story) { func PostStoryToStackerNews(story *Story) (int, error) {
dupes := FetchStackerNewsDupes(story.Url) dupes := FetchStackerNewsDupes(story.Url)
if len(*dupes) > 0 { if len(*dupes) > 0 {
log.Printf("%s was already posted. Skipping.\n", story.Url) log.Printf("%s was already posted. Skipping.\n", story.Url)
return return -1, &DupesError{story.Url, *dupes}
} }
body := GraphQLPayload{ body := GraphQLPayload{
@ -183,6 +205,7 @@ func PostStoryToStackerNews(story *Story) {
story.Score, story.Descendants, story.Score, story.Descendants,
) )
CommentStackerNewsPost(comment, parentId) CommentStackerNewsPost(comment, parentId)
return parentId, nil
} }
func StackerNewsItemLink(id int) string { func StackerNewsItemLink(id int) string {