Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Added msgerrors package and refactored code for safer error handling #22

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions msgerrors/msgerror.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package msgerrors

import (
"errors"
"strings"
)

// MsgError wraps a slice of errors and provides convenient
// syntax for processing individual errors without breaking
// the service
type MsgError struct {
err []string
}

// New instantiates a MsgError with a nil Err field
func New() *MsgError {
return &MsgError{err: make([]string, 0, 0)}
}

// Append safely adds a new error to our list
func (m *MsgError) Append(err error) {
if err != nil {
m.err = append(m.err, err.Error())
}
}

// Error provides the string output of our error
// This allows MsgError to implement the core "error"
// interface
func (m *MsgError) Error() string {
if len(m.err) == 0 {
return ""
}
return strings.Join(m.err, "\n")
}

// Errors provides conventient syntax for returning
// an error containing all information about the
// accumulated errors in code. It will return
// nil if no errors have been collated
func (m *MsgError) Errors() error {
if len(m.err) == 0 {
return nil
}
return errors.New(m.Error())
}
36 changes: 36 additions & 0 deletions msgerrors/msgerror_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package msgerrors

import (
"errors"
"strings"
"testing"
)

func TestMsgError(t *testing.T) {
msgErr := New()

if msgErr.Error() != "" {
t.Errorf("Expected empty string. Recieved %s", msgErr.Error())
}
if msgErr.Errors() != nil {
t.Errorf("Expected nil. Recieved %s", msgErr.Errors())
}

err1 := errors.New("Error 1")
err2 := errors.New("Error 2")
msgErr.Append(err1)
msgErr.Append(err2)

if len(msgErr.err) != 2 {
t.Errorf("Expected length 2. Recieved %d", len(msgErr.err))
}

concatenatedErr := strings.Join([]string{"Error 1", "Error 2"}, "\n")
if msgErr.Error() != concatenatedErr {
t.Errorf("Expected %s. \n Recieved %s", concatenatedErr, msgErr.Error())
}

if msgErr.Errors() == nil {
t.Errorf("Expected %s. \n Recieved %s", errors.New(concatenatedErr), msgErr.Errors())
}
}
8 changes: 5 additions & 3 deletions service/discord/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package discord

import (
"github.com/bwmarrin/discordgo"
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -90,13 +91,14 @@ func (d *Discord) AddReceivers(channelIDs ...string) {
// Send takes a message subject and a message body and sends them to all previously set chats.
func (d Discord) Send(subject, message string) error {
fullMessage := subject + "\n" + message // Treating subject as message title

msgErr := msgerrors.New()
for _, channelID := range d.channelIDs {
_, err := d.client.ChannelMessageSend(channelID, fullMessage)
if err != nil {
return errors.Wrapf(err, "failed to send message to Discord channel '%s'", channelID)
err = errors.Wrapf(err, "failed to send message to Discord channel '%s'", channelID)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}
4 changes: 2 additions & 2 deletions service/mail/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func (m Mail) Send(subject, message string) error {

err := msg.Send(m.smtpHostAddr, m.smtpAuth)
if err != nil {
err = errors.Wrap(err, "failed to send mail")
return errors.Wrap(err, "failed to send mail")
}

return err
return nil
}
9 changes: 5 additions & 4 deletions service/msteams/ms_teams.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package msteams

import (
goteamsnotify "github.com/atc0005/go-teams-notify/v2"
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -47,13 +48,13 @@ func (m MSTeams) Send(subject, message string) error {
msgCard := goteamsnotify.NewMessageCard()
msgCard.Title = subject
msgCard.Text = message

msgErr := msgerrors.New()
for _, webHook := range m.webHooks {
err := m.client.Send(webHook, msgCard)
if err != nil {
return errors.Wrapf(err, "failed to send message to Microsoft Teams via webhook '%s'", webHook)
err := errors.Wrapf(err, "failed to send message to Microsoft Teams via webhook '%s'", webHook)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}
12 changes: 8 additions & 4 deletions service/pushbullet/pushbullet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pushbullet

import (
"github.com/cschomburg/go-pushbullet"
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -36,17 +37,20 @@ func (pb *Pushbullet) AddReceivers(deviceNicknames ...string) {
// (android, chrome, firefox, windows)
// see https://www.pushbullet.com/apps
func (pb Pushbullet) Send(subject, message string) error {
msgErr := msgerrors.New()
for _, deviceNickname := range pb.deviceNicknames {
dev, err := pb.client.Device(deviceNickname)
if err != nil {
return errors.Wrapf(err, "failed to find Pushbullet device with nickname '%s'", deviceNickname)
err = errors.Wrapf(err, "failed to find Pushbullet device with nickname '%s'", deviceNickname)
msgErr.Append(err)
continue
}

err = dev.PushNote(subject, message)
if err != nil {
return errors.Wrapf(err, "failed to send message to Pushbullet device with nickname '%s'", deviceNickname)
err = errors.Wrapf(err, "failed to send message to Pushbullet device with nickname '%s'", deviceNickname)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}
9 changes: 5 additions & 4 deletions service/pushbullet/sms.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pushbullet

import (
"github.com/cschomburg/go-pushbullet"
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -49,13 +50,13 @@ func (sms SMS) Send(subject, message string) error {
if err != nil {
return errors.Wrapf(err, "failed to find valid pushbullet user")
}

msgErr := msgerrors.New()
for _, phoneNumber := range sms.phoneNumbers {
err = sms.client.PushSMS(user.Iden, sms.deviceIdentifier, phoneNumber, fullMessage)
if err != nil {
return errors.Wrapf(err, "failed to send SMS message to %s via Pushbullet", phoneNumber)
err = errors.Wrapf(err, "failed to send SMS message to %s via Pushbullet", phoneNumber)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}
9 changes: 5 additions & 4 deletions service/slack/slack.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package slack

import (
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
"github.com/slack-go/slack"
)
Expand Down Expand Up @@ -36,16 +37,16 @@ func (s *Slack) AddReceivers(channelIDs ...string) {
// see https://api.slack.com/
func (s Slack) Send(subject, message string) error {
fullMessage := subject + "\n" + message // Treating subject as message title

msgErr := msgerrors.New()
for _, channelID := range s.channelIDs {
id, timestamp, err := s.client.PostMessage(
channelID,
slack.MsgOptionText(fullMessage, false),
)
if err != nil {
return errors.Wrapf(err, "failed to send message to Slack channel '%s' at time '%s'", id, timestamp)
err = errors.Wrapf(err, "failed to send message to Slack channel '%s' at time '%s'", id, timestamp)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}
9 changes: 5 additions & 4 deletions service/telegram/telegram.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strconv"

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"github.com/nikoksr/notify/msgerrors"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -50,14 +51,14 @@ func (t Telegram) Send(subject, message string) error {

msg := tgbotapi.NewMessage(0, fullMessage)
msg.ParseMode = defaultParseMode

msgErr := msgerrors.New()
for _, chatID := range t.chatIDs {
msg.ChatID = chatID
_, err := t.client.Send(msg)
if err != nil {
return errors.Wrapf(err, "failed to send message to Telegram chat '%d'", chatID)
err = errors.Wrapf(err, "failed to send message to Telegram chat '%d'", chatID)
msgErr.Append(err)
}
}

return nil
return msgErr.Errors()
}