From 096922450a53a2273fa717f65c45316adf294946 Mon Sep 17 00:00:00 2001 From: Shubham Hibare Date: Sat, 19 Aug 2023 19:10:09 +0530 Subject: [PATCH] Refactor notifiers, use GoCommon --- go.mod | 4 +- go.sum | 4 +- internal/backup/backup.go | 27 +++--- internal/config/config.go | 5 ++ internal/notifiers/discord.go | 153 ++++++++++++++------------------- internal/notifiers/notifier.go | 58 ++++++------- 6 files changed, 115 insertions(+), 136 deletions(-) diff --git a/go.mod b/go.mod index d02a64c..f9b1bed 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/go-co-op/gocron v1.31.1 - github.com/hibare/GoCommon/v2 v2.1.1 + github.com/hibare/GoCommon/v2 v2.2.0 github.com/jedib0t/go-pretty/v6 v6.4.6 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 @@ -35,4 +35,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -// replace github.com/hibare/GoCommon => ../GoCommon +// replace github.com/hibare/GoCommon/v2 => ../GoCommon diff --git a/go.sum b/go.sum index 8ae5317..bc77baf 100644 --- a/go.sum +++ b/go.sum @@ -126,8 +126,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hibare/GoCommon/v2 v2.1.1 h1:LeMv8nQFTAeEwzqh6hQHobbgkfOzv5c8XWtyAgF8TCU= -github.com/hibare/GoCommon/v2 v2.1.1/go.mod h1:azkJtd0og4/HDZ47NydL/zEc3ALukwF0mPbmghNRrSQ= +github.com/hibare/GoCommon/v2 v2.2.0 h1:aQd/MvgONakXzNQlLTzFtCea7as1XtuBvv1eNk6y99U= +github.com/hibare/GoCommon/v2 v2.2.0/go.mod h1:azkJtd0og4/HDZ47NydL/zEc3ALukwF0mPbmghNRrSQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= diff --git a/internal/backup/backup.go b/internal/backup/backup.go index 5a04706..d81258f 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -1,7 +1,7 @@ package backup import ( - "fmt" + "errors" "os" "path/filepath" @@ -15,6 +15,11 @@ import ( "github.com/hibare/GoS3Backup/internal/notifiers" ) +var ( + ErrArchiving = errors.New("error archiving") + ErrNoProcessableFiles = errors.New("no processable files") +) + func Backup() { s3 := commonS3.S3{ Endpoint: config.Current.S3.Endpoint, @@ -40,28 +45,26 @@ func Backup() { zipPath, totalFiles, totalDirs, successFiles, err := commonFiles.ArchiveDir(dir) if err != nil { log.Warnf("Archiving failed %s", dir) - notifiers.BackupFailedNotification("", dir, totalDirs, totalFiles) + notifiers.NotifyBackupFailure(dir, totalDirs, totalFiles, err) continue } if successFiles <= 0 { - err := fmt.Errorf("Failed to archive") log.Warnf("Uploading failed %s: %s", dir, err) - notifiers.BackupFailedNotification(err.Error(), dir, totalDirs, totalFiles) + notifiers.NotifyBackupFailure(dir, totalDirs, totalFiles, ErrNoProcessableFiles) continue } log.Infof("Uploading files %d/%d", successFiles, totalFiles) key, err := s3.UploadFile(zipPath) - if err != nil { log.Warnf("Uploading failed %s: %s", dir, err) - notifiers.BackupFailedNotification(err.Error(), dir, totalDirs, totalFiles) + notifiers.NotifyBackupFailure(dir, totalDirs, totalFiles, err) continue } - log.Warnf("Uploaded files %d/%d at %s", successFiles, totalFiles, key) - notifiers.BackupSuccessfulNotification(dir, totalDirs, totalFiles, successFiles, key) + log.Infof("Uploaded files %d/%d at %s", successFiles, totalFiles, key) + notifiers.NotifyBackupSuccess(dir, totalDirs, totalFiles, successFiles, key) os.Remove(zipPath) } else { @@ -70,12 +73,12 @@ func Backup() { if successFiles <= 0 { log.Warnf("Uploading failed %s", dir) - notifiers.BackupFailedNotification("", dir, totalDirs, totalFiles) + notifiers.NotifyBackupFailure(dir, totalDirs, totalFiles, ErrNoProcessableFiles) continue } log.Warnf("Uploaded files %d/%d at %s", successFiles, totalFiles, s3.Prefix) - notifiers.BackupSuccessfulNotification(dir, totalDirs, totalFiles, successFiles, key) + notifiers.NotifyBackupSuccess(dir, totalDirs, totalFiles, successFiles, key) } } @@ -141,7 +144,7 @@ func PurgeOldBackups() { backups, err := ListBackups() if err != nil { - notifiers.BackupDeletionFailureNotification(err.Error(), constants.NotAvailable) + notifiers.NotifyBackupDeleteFailure(constants.NotAvailable, err) return } @@ -160,7 +163,7 @@ func PurgeOldBackups() { if err := s3.DeleteObjects(key, true); err != nil { log.Errorf("Error deleting backup %s: %v", key, err) - notifiers.BackupDeletionFailureNotification(err.Error(), key) + notifiers.NotifyBackupDeleteFailure(key, err) continue } } diff --git a/internal/config/config.go b/internal/config/config.go index 990be3f..d7dc31e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -70,6 +70,11 @@ func LoadConfig() { Current.Backup.Cron = constants.DefaultCron } + // If notifier webhook is empty, set status to disable + if Current.Notifiers.Discord.Webhook == "" { + Current.Notifiers.Discord.Enabled = false + } + Current.Backup.Hostname = commonUtils.GetHostname() } diff --git a/internal/notifiers/discord.go b/internal/notifiers/discord.go index c8d3353..4786de5 100644 --- a/internal/notifiers/discord.go +++ b/internal/notifiers/discord.go @@ -1,63 +1,36 @@ package notifiers import ( - "bytes" - "encoding/json" "fmt" - "net/http" "strconv" + "github.com/hibare/GoCommon/v2/pkg/notifiers/discord" "github.com/hibare/GoS3Backup/internal/config" + "github.com/hibare/GoS3Backup/internal/constants" "github.com/hibare/GoS3Backup/internal/version" log "github.com/sirupsen/logrus" ) -type DiscordWebhookMessage struct { - Embeds []DiscordEmbed `json:"embeds"` - Components []DiscordComponent `json:"components"` - Username string `json:"username"` - Content string `json:"content"` -} - -type DiscordEmbed struct { - Title string `json:"title"` - Description string `json:"description"` - Color int `json:"color"` - Footer DiscordEmbedFooter `json:"footer"` - Fields []DiscordEmbedField `json:"fields"` -} - -type DiscordEmbedField struct { - Name string `json:"name"` - Value string `json:"value"` - Inline bool `json:"inline,omitempty"` -} - -type DiscordEmbedFooter struct { - Text string `json:"text"` -} - -type DiscordComponent struct { - // Define struct for Discord components if needed +func runDiscordPrechecks() error { + if !config.Current.Notifiers.Discord.Enabled { + return ErrNotifierDisabled + } + return nil } -func (d *DiscordWebhookMessage) AddFooter() { - if version.V.NewVersionAvailable { - footer := DiscordEmbedFooter{ - Text: version.V.GetUpdateNotification(), - } - d.Embeds[0].Footer = footer +func discordNotifyBackupSuccess(directory string, totalDirs, totalFiles, successFiles int, key string) { + if err := runDiscordPrechecks(); err != nil { + log.Error(err) + return } -} -func DiscordBackupSuccessfulNotification(webhookUrl string, hostname, directory string, totalDirs, totalFiles, successFiles int, key string) error { - webhookMessage := DiscordWebhookMessage{ - Embeds: []DiscordEmbed{ + message := discord.Message{ + Embeds: []discord.Embed{ { Title: "Directory", Description: directory, Color: 1498748, - Fields: []DiscordEmbedField{ + Fields: []discord.EmbedField{ { Name: "Key", Value: key, @@ -76,24 +49,35 @@ func DiscordBackupSuccessfulNotification(webhookUrl string, hostname, directory }, }, }, - Components: []DiscordComponent{}, - Username: "Backup Job", - Content: fmt.Sprintf("**Backup Successful** - *%s*", hostname), + Components: []discord.Component{}, + Username: constants.ProgramIdentifier, + Content: fmt.Sprintf("**Backup Successful** - *%s*", config.Current.Backup.Hostname), } - webhookMessage.AddFooter() - return SendMessage(webhookUrl, webhookMessage) + if version.V.NewVersionAvailable { + if err := message.AddFooter(version.V.GetUpdateNotification()); err != nil { + log.Warn(err) + } + } + if err := message.Send(config.Current.Notifiers.Discord.Webhook); err != nil { + log.Error(err) + } } -func DiscordBackupFailedNotification(webhookUrl string, hostname, err, directory string, totalDirs, totalFiles int) error { - webhookMessage := DiscordWebhookMessage{ - Embeds: []DiscordEmbed{ +func discordNotifyBackupFailure(directory string, totalDirs, totalFiles int, err error) { + if err := runDiscordPrechecks(); err != nil { + log.Error(err) + return + } + + message := discord.Message{ + Embeds: []discord.Embed{ { Title: "Error", - Description: err, + Description: err.Error(), Color: 14554702, - Fields: []DiscordEmbedField{ + Fields: []discord.EmbedField{ { Name: "Directory", Value: directory, @@ -112,23 +96,35 @@ func DiscordBackupFailedNotification(webhookUrl string, hostname, err, directory }, }, }, - Components: []DiscordComponent{}, - Username: "Backup Job", - Content: fmt.Sprintf("**Backup Failed** - *%s*", hostname), + Components: []discord.Component{}, + Username: constants.ProgramIdentifier, + Content: fmt.Sprintf("**Backup Failed** - *%s*", config.Current.Backup.Hostname), + } + + if version.V.NewVersionAvailable { + if err := message.AddFooter(version.V.GetUpdateNotification()); err != nil { + log.Warn(err) + } } - webhookMessage.AddFooter() - return SendMessage(webhookUrl, webhookMessage) + if err := message.Send(config.Current.Notifiers.Discord.Webhook); err != nil { + log.Error(err) + } } -func DiscordBackupDeletionFailureNotification(webhookUrl string, hostname, err, key string) error { - webhookMessage := DiscordWebhookMessage{ - Embeds: []DiscordEmbed{ +func discordNotifyBackupDeleteFailure(key string, err error) { + if err := runDiscordPrechecks(); err != nil { + log.Error(err) + return + } + + message := discord.Message{ + Embeds: []discord.Embed{ { Title: "Error", - Description: err, + Description: err.Error(), Color: 14590998, - Fields: []DiscordEmbedField{ + Fields: []discord.EmbedField{ { Name: "Key", Value: key, @@ -137,35 +133,18 @@ func DiscordBackupDeletionFailureNotification(webhookUrl string, hostname, err, }, }, }, - Components: []DiscordComponent{}, - Username: "Backup Job", - Content: fmt.Sprintf("**Backup Deletion Failed** - *%s*", hostname), - } - webhookMessage.AddFooter() - - return SendMessage(webhookUrl, webhookMessage) -} - -func SendMessage(webhookUrl string, message DiscordWebhookMessage) error { - if config.Current.Notifiers.Discord.Webhook != "" && !config.Current.Notifiers.Discord.Enabled { - log.Warning("Discord notifier not enabled") - return nil - } - - payload, err := json.Marshal(message) - if err != nil { - return &json.SyntaxError{} + Components: []discord.Component{}, + Username: constants.ProgramIdentifier, + Content: fmt.Sprintf("**Backup Deletion Failed** - *%s*", config.Current.Backup.Hostname), } - resp, err := http.Post(webhookUrl, "application/json", bytes.NewBuffer(payload)) - if err != nil { - return err + if version.V.NewVersionAvailable { + if err := message.AddFooter(version.V.GetUpdateNotification()); err != nil { + log.Warn(err) + } } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return err + if err := message.Send(config.Current.Notifiers.Discord.Webhook); err != nil { + log.Error(err) } - - return nil } diff --git a/internal/notifiers/notifier.go b/internal/notifiers/notifier.go index 093ccc2..c22e370 100644 --- a/internal/notifiers/notifier.go +++ b/internal/notifiers/notifier.go @@ -1,59 +1,51 @@ package notifiers import ( + "errors" + "github.com/hibare/GoS3Backup/internal/config" log "github.com/sirupsen/logrus" ) -func BackupSuccessfulNotification(directory string, totalDirs, totalFiles, successFiles int, key string) { +var ( + ErrNotifiersDisabled = errors.New("notifiers are disabled") + ErrMissingNotifierWebhook = errors.New("missing notifier webhook") + ErrNotifierDisabled = errors.New("notifier is disabled") +) +func runPreChecks() error { if !config.Current.Notifiers.Enabled { - log.Warn("Notifiers are disabled") - return + return ErrNotifiersDisabled } - if config.Current.Notifiers.Discord.Webhook != "" && !config.Current.Notifiers.Discord.Enabled { - log.Warning("Discord notifier not enabled") + return nil +} + +func NotifyBackupSuccess(directory string, totalDirs, totalFiles, successFiles int, key string) { + if err := runPreChecks(); err != nil { + log.Error(err) return - } else if config.Current.Notifiers.Discord.Enabled { - if err := DiscordBackupSuccessfulNotification(config.Current.Notifiers.Discord.Webhook, config.Current.Backup.Hostname, directory, totalDirs, totalFiles, successFiles, key); err != nil { - log.Errorf("Error sending Discord notification: %v", err) - } } -} + discordNotifyBackupSuccess(directory, totalDirs, totalFiles, successFiles, key) -func BackupFailedNotification(err, directory string, totalDirs, totalFiles int) { +} - if !config.Current.Notifiers.Enabled { - log.Warn("Notifiers are disabled") +func NotifyBackupFailure(directory string, totalDirs, totalFiles int, err error) { + if err := runPreChecks(); err != nil { + log.Error(err) return } - if config.Current.Notifiers.Discord.Webhook != "" && !config.Current.Notifiers.Discord.Enabled { - log.Warning("Discord notifier not enabled") - return - } else if config.Current.Notifiers.Discord.Enabled { - if err := DiscordBackupFailedNotification(config.Current.Notifiers.Discord.Webhook, config.Current.Backup.Hostname, err, directory, totalDirs, totalFiles); err != nil { - log.Errorf("Error sending Discord notification: %v", err) - } - } + discordNotifyBackupFailure(directory, totalDirs, totalFiles, err) } -func BackupDeletionFailureNotification(err, key string) { - - if !config.Current.Notifiers.Enabled { - log.Warn("Notifiers are disabled") +func NotifyBackupDeleteFailure(key string, err error) { + if err := runPreChecks(); err != nil { + log.Error(err) return } - if config.Current.Notifiers.Discord.Webhook != "" && !config.Current.Notifiers.Discord.Enabled { - log.Warning("Discord notifier not enabled") - return - } else if config.Current.Notifiers.Discord.Enabled { - if err := DiscordBackupDeletionFailureNotification(config.Current.Notifiers.Discord.Webhook, config.Current.Backup.Hostname, err, key); err != nil { - log.Errorf("Error sending Discord notification: %v", err) - } - } + discordNotifyBackupDeleteFailure(key, err) }