2021-03-31 01:38:34 +02:00
package telegram
import (
2021-12-03 03:05:17 +01:00
"bytes"
2021-03-31 01:38:34 +02:00
"fmt"
2021-12-03 07:44:17 +01:00
"io"
2021-03-31 01:38:34 +02:00
"net/http"
2021-10-08 03:28:04 +02:00
"github.com/TwiN/gatus/v3/alerting/alert"
2021-12-03 03:05:17 +01:00
"github.com/TwiN/gatus/v3/client"
2021-10-08 03:28:04 +02:00
"github.com/TwiN/gatus/v3/core"
2021-03-31 01:38:34 +02:00
)
// AlertProvider is the configuration necessary for sending an alert using Telegram
type AlertProvider struct {
Token string ` yaml:"token" `
ID string ` yaml:"id" `
2021-05-16 03:31:32 +02:00
2021-10-23 22:47:12 +02:00
// DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type
2021-05-19 04:29:15 +02:00
DefaultAlert * alert . Alert ` yaml:"default-alert" `
2021-03-31 01:38:34 +02:00
}
// IsValid returns whether the provider's configuration is valid
func ( provider * AlertProvider ) IsValid ( ) bool {
return len ( provider . Token ) > 0 && len ( provider . ID ) > 0
}
2021-12-03 03:05:17 +01:00
// Send an alert using the provider
func ( provider * AlertProvider ) Send ( endpoint * core . Endpoint , alert * alert . Alert , result * core . Result , resolved bool ) error {
buffer := bytes . NewBuffer ( [ ] byte ( provider . buildRequestBody ( endpoint , alert , result , resolved ) ) )
request , err := http . NewRequest ( http . MethodPost , fmt . Sprintf ( "https://api.telegram.org/bot%s/sendMessage" , provider . Token ) , buffer )
if err != nil {
return err
}
request . Header . Set ( "Content-Type" , "application/json" )
response , err := client . GetHTTPClient ( nil ) . Do ( request )
if err != nil {
return err
}
if response . StatusCode > 399 {
2021-12-03 07:44:17 +01:00
body , _ := io . ReadAll ( response . Body )
2021-12-03 03:05:17 +01:00
return fmt . Errorf ( "call to provider alert returned status code %d: %s" , response . StatusCode , string ( body ) )
}
return err
}
// buildRequestBody builds the request body for the provider
func ( provider * AlertProvider ) buildRequestBody ( endpoint * core . Endpoint , alert * alert . Alert , result * core . Result , resolved bool ) string {
2021-03-31 01:38:34 +02:00
var message , results string
if resolved {
2021-12-12 22:33:16 +01:00
message = fmt . Sprintf ( "An alert for *%s* has been resolved:\\n—\\n _healthcheck passing successfully %d time(s) in a row_\\n— " , endpoint . DisplayName ( ) , alert . FailureThreshold )
2021-03-31 01:38:34 +02:00
} else {
2021-12-12 22:33:16 +01:00
message = fmt . Sprintf ( "An alert for *%s* has been triggered:\\n—\\n _healthcheck failed %d time(s) in a row_\\n— " , endpoint . DisplayName ( ) , alert . FailureThreshold )
2021-03-31 01:38:34 +02:00
}
for _ , conditionResult := range result . ConditionResults {
var prefix string
if conditionResult . Success {
prefix = "✅"
} else {
prefix = "❌"
}
results += fmt . Sprintf ( "%s - `%s`\\n" , prefix , conditionResult . Condition )
}
var text string
2021-05-16 03:31:32 +02:00
if len ( alert . GetDescription ( ) ) > 0 {
text = fmt . Sprintf ( "⛑ *Gatus* \\n%s \\n*Description* \\n_%s_ \\n\\n*Condition results*\\n%s" , message , alert . GetDescription ( ) , results )
2021-03-31 01:38:34 +02:00
} else {
text = fmt . Sprintf ( "⛑ *Gatus* \\n%s \\n*Condition results*\\n%s" , message , results )
}
2021-12-03 03:05:17 +01:00
return fmt . Sprintf ( ` { "chat_id": "%s", "text": "%s", "parse_mode": "MARKDOWN"} ` , provider . ID , text )
2021-03-31 01:38:34 +02:00
}
2021-05-16 03:31:32 +02:00
// GetDefaultAlert returns the provider's default alert configuration
2021-05-19 04:29:15 +02:00
func ( provider AlertProvider ) GetDefaultAlert ( ) * alert . Alert {
2021-05-16 03:31:32 +02:00
return provider . DefaultAlert
}