Skip to content

Commit

Permalink
feat: better error handling, bump go-archive dep, retries
Browse files Browse the repository at this point in the history
  • Loading branch information
tyzbit committed Feb 6, 2023
1 parent 992e4af commit aa9c0fe
Show file tree
Hide file tree
Showing 17 changed files with 1,100 additions and 44 deletions.
22 changes: 16 additions & 6 deletions bot/message_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,19 @@ func (bot *ArchiverBot) handleArchiveRequest(s *discordgo.Session, r *discordgo.
return fmt.Errorf("unable to look up message by id: %v", r.MessageID)
}
xurlsStrict := xurls.Strict
urls := xurlsStrict.FindAllString(message.Content, -1)
if len(urls) == 0 {
messageUrls := xurlsStrict.FindAllString(message.Content, -1)
if len(messageUrls) == 0 {
return fmt.Errorf("found 0 URLs in message")
}

log.Debug("URLs parsed from message: ", strings.Join(urls, ", "))
log.Debug("URLs parsed from message: ", strings.Join(messageUrls, ", "))

// This UUID will be used to tie together the ArchiveEventEvent,
// the archiveRequestUrls and the archiveResponseUrls.
archiveEventUUID := uuid.New().String()

var archives []ArchiveEvent
for _, url := range urls {
for _, url := range messageUrls {
domainName, err := getDomainName(url)
if err != nil {
log.Error("unable to get domain name for url: ", url)
Expand Down Expand Up @@ -174,7 +174,7 @@ func (bot *ArchiverBot) handleArchiveRequest(s *discordgo.Session, r *discordgo.
if archive.ResponseURL == "" {
log.Debug("need to call archive.org api for ", archive.RequestURL)

urls = []string{}
urls := []string{}
if rearchive {
url, err := goarchive.ArchiveURL(archive.RequestURL)
if err != nil || url == "" {
Expand All @@ -184,7 +184,7 @@ func (bot *ArchiverBot) handleArchiveRequest(s *discordgo.Session, r *discordgo.
urls = append(urls, url)
} else {
var errs []error
urls, errs = goarchive.GetLatestURLs([]string{archive.RequestURL}, ServerConfig.AutoArchive)
urls, errs = goarchive.GetLatestURLs([]string{archive.RequestURL}, ServerConfig.RetryAttempts, ServerConfig.AutoArchive)
for _, err := range errs {
if err != nil {
log.Errorf("error archiving url: %v", err)
Expand Down Expand Up @@ -212,6 +212,16 @@ func (bot *ArchiverBot) handleArchiveRequest(s *discordgo.Session, r *discordgo.
}
}

if len(archivedLinks) < len(messageUrls) {
log.Errorf("did not receive the same number of archived links as submitted URLs")
if len(archivedLinks) == 0 {
log.Errorf("did not receive any Archive.org links")
archivedLinks = []string{"I was unable to get any Wayback Machine URLs. " +
"Most of the time, this is " +
"due to rate-limiting by Archive.org. " +
"Please try again by adding the 'repeat' emoji to the message."}
}
}
plural := ""
if len(archivedLinks) > 1 {
plural = "s"
Expand Down
75 changes: 59 additions & 16 deletions bot/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bot

import (
"fmt"
"strconv"
"strings"
"time"

Expand All @@ -24,8 +25,14 @@ type ServerConfig struct {
ReplyToOriginalMessage bool `pretty:"Reply to original message (embed must be off) (replyto)"`
UseEmbed bool `pretty:"Use embed to reply (embed)"`
AutoArchive bool `pretty:"Automatically try archiving a page if it is not found (archive)"`
RetryAttempts uint `pretty:"Number of attempts the bot should make to archive a URL. Max 10"`
}

const (
MinAllowedRetryAttempts = 1
MaxAllowedRetryAttempts = 10
)

var (
defaultServerConfig ServerConfig = ServerConfig{
DiscordId: "0",
Expand All @@ -34,6 +41,7 @@ var (
ReplyToOriginalMessage: false,
UseEmbed: true,
AutoArchive: true,
RetryAttempts: 4,
}

archiverRepoUrl string = "https://github.com/tyzbit/go-discord-archiver"
Expand Down Expand Up @@ -90,6 +98,7 @@ func (bot *ArchiverBot) getServerConfig(guildId string) ServerConfig {
// setServerConfig sets a single config setting for the calling server. Syntax:
// (commandPrefix) config [setting] [value]
func (bot *ArchiverBot) setServerConfig(s *discordgo.Session, m *discordgo.Message) error {
var scError error
// Look up the guild from the message
guild, err := s.Guild(m.GuildID)
if err != nil {
Expand All @@ -107,9 +116,9 @@ func (bot *ArchiverBot) setServerConfig(s *discordgo.Session, m *discordgo.Messa

command := strings.Split(m.Content, " ")
var setting, value string
if len(command) == 4 {
setting = command[2]
value = command[3]
if len(command) == 5 {
setting = command[3]
value = command[4]
} else {
setting = "get"
}
Expand All @@ -120,6 +129,16 @@ func (bot *ArchiverBot) setServerConfig(s *discordgo.Session, m *discordgo.Messa
}

tx := &gorm.DB{}
var valueIsStringBoolean = false
var valueIsNumber = false
var description string
var errDetails string
if (value == "on" || value == "off") {
valueIsStringBoolean = true
}
if _, err := strconv.Atoi(value); err == nil {
valueIsNumber = true
}
switch setting {
// "get" is the only command that does not alter the database.
case "get":
Expand All @@ -129,30 +148,54 @@ func (bot *ArchiverBot) setServerConfig(s *discordgo.Session, m *discordgo.Messa
})
return nil
case "switch":
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("archive_enabled", value == "on")
if valueIsStringBoolean {
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("archive_enabled", value == "on")
}
case "replyto":
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("reply_to_original_message", value == "on")
if valueIsStringBoolean {
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("reply_to_original_message", value == "on")
}
case "embed":
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("use_embed", value == "on")
if valueIsStringBoolean {
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("use_embed", value == "on")
}
case "archive":
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("auto_archive", value == "on")
if valueIsStringBoolean {
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("auto_archive", value == "on")
}
case "attempts":
if valueIsNumber {
uintValue, err := strconv.ParseUint(value, 10, 0)
if err != nil {
errDetails = "not a number."
}
if (uintValue >= MinAllowedRetryAttempts && uintValue <= MaxAllowedRetryAttempts) {
tx = bot.DB.Model(&ServerConfig{}).Where(&ServerConfig{DiscordId: guild.ID}).Update("retry_attempts", uintValue)
} else {
errDetails = "not between " +
fmt.Sprint(MinAllowedRetryAttempts) + " and " + fmt.Sprint(MaxAllowedRetryAttempts) + "."
}
}
default:
bot.sendMessage(s, sc.UseEmbed, sc.ReplyToOriginalMessage, m, errorEmbed)
return nil
}

// We only expect one server to be updated at a time. Otherwise, return an error.
if tx.RowsAffected != 1 {
return fmt.Errorf("did not expect %v rows to be affected updating "+
"server config for server: %v(%v)", fmt.Sprintf("%v", tx.RowsAffected), guild.Name, guild.ID)
errorEmbed.Title = "Unable to set " + setting + " to " + value + ", " + errDetails
bot.sendMessage(s, sc.UseEmbed, sc.ReplyToOriginalMessage, m, errorEmbed)
scError = fmt.Errorf("did not expect %v rows to be affected updating "+
"server config for server: %v(%v)", fmt.Sprintf("%v", tx.RowsAffected), guild.Name, guild.ID)
} else {
description = setting + " set to " + value
scError = nil
bot.sendMessage(s, sc.UseEmbed, sc.ReplyToOriginalMessage, m, &discordgo.MessageEmbed{
Title: "Setting Updated",
Description: description,
})
}

bot.sendMessage(s, sc.UseEmbed, sc.ReplyToOriginalMessage, m, &discordgo.MessageEmbed{
Title: "Setting Updated",
Description: setting + " set to " + value,
})

return nil
return scError
}

// updateServersWatched updates the servers watched value
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ require (
github.com/google/uuid v1.3.0
github.com/mvdan/xurls v1.1.0
github.com/sirupsen/logrus v1.8.1
github.com/tyzbit/go-archive v0.0.0-20220422014241-aa077f0a8174
gorm.io/driver/mysql v1.3.3
gorm.io/driver/sqlite v1.3.1
gorm.io/gorm v1.23.4
)

require (
github.com/BurntSushi/toml v0.4.1 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/go-playground/locales v0.13.0 // indirect
Expand All @@ -35,6 +35,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/tyzbit/go-archive v0.0.0-20230206195843-20514a4efc44 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/bwmarrin/discordgo v0.25.0 h1:NXhdfHRNxtwso6FPdzW2i3uBvvU7UIQTghmV2T4nqAs=
github.com/bwmarrin/discordgo v0.25.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -67,6 +69,14 @@ github.com/tyzbit/go-archive v0.0.0-20220422011230-e4ccafb403ab h1:98S4kV6VGEV9F
github.com/tyzbit/go-archive v0.0.0-20220422011230-e4ccafb403ab/go.mod h1:+lKbHcRfCD67HK5VtyeMKQAsdZlbP5eq08sTlWzPQq4=
github.com/tyzbit/go-archive v0.0.0-20220422014241-aa077f0a8174 h1:0L+g6CllW/VPERnQcWc4FtTeGBiNkIIdK3HBupbn2aI=
github.com/tyzbit/go-archive v0.0.0-20220422014241-aa077f0a8174/go.mod h1:+lKbHcRfCD67HK5VtyeMKQAsdZlbP5eq08sTlWzPQq4=
github.com/tyzbit/go-archive v0.0.0-20230206185234-e0ab8e1dc3de h1:v/UKYFZspLSbhTDoTqkUQAetYWsAemQyxh0R+2b6hzA=
github.com/tyzbit/go-archive v0.0.0-20230206185234-e0ab8e1dc3de/go.mod h1:D8vNUS0ZU4ILov2Igxw1h+Kj7aeyapjUU1ruPLEx9gw=
github.com/tyzbit/go-archive v0.0.0-20230206192309-94b220444e20 h1:bsOewcV4u7FFxaunSAqW9uwU2iaqOR+5DsisO0NRqzM=
github.com/tyzbit/go-archive v0.0.0-20230206192309-94b220444e20/go.mod h1:D8vNUS0ZU4ILov2Igxw1h+Kj7aeyapjUU1ruPLEx9gw=
github.com/tyzbit/go-archive v0.0.0-20230206193458-f613421690a2 h1:adhdKsU62u6V50w5Wqw7RYR9DUhUpPS4rxuqdQfgN0g=
github.com/tyzbit/go-archive v0.0.0-20230206193458-f613421690a2/go.mod h1:D8vNUS0ZU4ILov2Igxw1h+Kj7aeyapjUU1ruPLEx9gw=
github.com/tyzbit/go-archive v0.0.0-20230206195843-20514a4efc44 h1:eFnPPxL7hFNDJ+EKmW6OTk8MEr5C04+2gKqsP1C10F8=
github.com/tyzbit/go-archive v0.0.0-20230206195843-20514a4efc44/go.mod h1:D8vNUS0ZU4ILov2Igxw1h+Kj7aeyapjUU1ruPLEx9gw=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
Expand Down
21 changes: 21 additions & 0 deletions vendor/github.com/avast/retry-go/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions vendor/github.com/avast/retry-go/.godocdown.tmpl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions vendor/github.com/avast/retry-go/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions vendor/github.com/avast/retry-go/Gopkg.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions vendor/github.com/avast/retry-go/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit aa9c0fe

Please sign in to comment.