55package notification
66
77import (
8+ "bufio"
89 "bytes"
910 "encoding/json"
1011 "fmt"
1112 "io"
1213 "net/http"
14+ "slices"
1315 "strings"
1416 "time"
1517
@@ -66,8 +68,18 @@ func NewDiscordSender(log logger.Logger, config *config.AppConfig) domain.Sender
6668 }
6769}
6870
71+ func (s * discordSender ) Name () string {
72+ return "discord"
73+ }
74+
6975func (s * discordSender ) Send (statusCode int , payload domain.NotificationPayload ) error {
7076 if ! s .isEnabled () {
77+ s .log .Debug ().Msg ("no webhook defined, skipping notification" )
78+ return nil
79+ }
80+
81+ if ! s .shouldSend (statusCode ) {
82+ s .log .Debug ().Msg ("no notification wanted for this status, skipping notification" )
7183 return nil
7284 }
7385
@@ -78,34 +90,34 @@ func (s *discordSender) Send(statusCode int, payload domain.NotificationPayload)
7890
7991 jsonData , err := json .Marshal (m )
8092 if err != nil {
81- return errors .Wrap (err , "discord client could not marshal data : %+v " , m )
93+ return errors .Wrap (err , "could not marshal json request for status : %v payload: %v " , statusCode , payload )
8294 }
8395
8496 req , err := http .NewRequest (http .MethodPost , s .cfg .Config .Notifications .Discord , bytes .NewBuffer (jsonData ))
8597 if err != nil {
86- return errors .Wrap (err , "discord client could not create request" )
98+ return errors .Wrap (err , "could not create request for status: %v payload: %v" , statusCode , payload )
8799 }
88100
89101 req .Header .Set ("Content-Type" , "application/json" )
90- //req.Header.Set("User-Agent", "seasonpackarr")
102+ // req.Header.Set("User-Agent", "seasonpackarr")
91103
92104 res , err := s .httpClient .Do (req )
93105 if err != nil {
94- return errors .Wrap (err , "discord client could not make request : %+v " , req )
106+ return errors .Wrap (err , "client request error for status : %v payload: %v " , statusCode , payload )
95107 }
96108
97109 defer res .Body .Close ()
98110
99- body , err := io .ReadAll (res .Body )
100- if err != nil {
101- return errors .Wrap (err , "discord client could not read data" )
102- }
103-
104- s .log .Trace ().Msgf ("discord status: %v response: %v" , res .StatusCode , string (body ))
111+ s .log .Trace ().Msgf ("discord response status: %d" , res .StatusCode )
105112
106113 // discord responds with 204, Notifiarr with 204 so lets take all 200 as ok
107- if res .StatusCode >= 300 {
108- return errors .New ("bad discord client status: %v body: %v" , res .StatusCode , string (body ))
114+ if res .StatusCode != http .StatusOK && res .StatusCode != http .StatusNoContent {
115+ body , err := io .ReadAll (bufio .NewReader (res .Body ))
116+ if err != nil {
117+ return errors .Wrap (err , "could not read body for status: %v payload: %v" , statusCode , payload )
118+ }
119+
120+ return errors .New ("unexpected status: %v body: %v" , res .StatusCode , string (body ))
109121 }
110122
111123 s .log .Debug ().Msg ("notification successfully sent to discord" )
@@ -114,20 +126,34 @@ func (s *discordSender) Send(statusCode int, payload domain.NotificationPayload)
114126}
115127
116128func (s * discordSender ) isEnabled () bool {
117- if s .cfg .Config .Notifications .Discord == "" {
118- s .log .Warn ().Msg ("no webhook defined, skipping notification" )
129+ return len (s .cfg .Config .Notifications .Discord ) != 0
130+ }
131+
132+ func (s * discordSender ) shouldSend (statusCode int ) bool {
133+ if len (s .cfg .Config .Notifications .NotificationLevel ) == 0 {
119134 return false
120135 }
121136
122- return true
137+ statusCodes := make (map [int ]struct {})
138+
139+ for _ , level := range s .cfg .Config .Notifications .NotificationLevel {
140+ if codes , ok := domain .StatusMap [level ]; ok {
141+ for _ , code := range codes {
142+ statusCodes [code ] = struct {}{}
143+ }
144+ }
145+ }
146+
147+ _ , shouldSend := statusCodes [statusCode ]
148+ return shouldSend
123149}
124150
125151func (s * discordSender ) buildEmbed (statusCode int , payload domain.NotificationPayload ) DiscordEmbeds {
126152 color := LIGHT_BLUE
127153
128- if ( statusCode >= 200 ) && ( statusCode < 250 ) { // not matching
154+ if slices . Contains ( domain . StatusMap [ domain . NotificationLevelInfo ], statusCode ) { // not matching
129155 color = GRAY
130- } else if ( statusCode >= 400 ) && ( statusCode < 500 ) { // error processing
156+ } else if slices . Contains ( domain . StatusMap [ domain . NotificationLevelError ], statusCode ) { // error processing
131157 color = RED
132158 } else { // success
133159 color = GREEN
@@ -164,7 +190,7 @@ func (s *discordSender) buildEmbed(statusCode int, payload domain.NotificationPa
164190
165191 if payload .Error != nil {
166192 // actual error?
167- if statusCode >= 400 {
193+ if slices . Contains ( domain . StatusMap [ domain . NotificationLevelError ], statusCode ) {
168194 f := DiscordEmbedsFields {
169195 Name : "Error" ,
170196 Value : fmt .Sprintf ("```%s```" , payload .Error .Error ()),
0 commit comments