87 lines
1.8 KiB
Go
87 lines
1.8 KiB
Go
package notifications
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/kjannette/trahn-backend/internal/httputil"
|
|
)
|
|
|
|
type Sender struct {
|
|
webhookURL string
|
|
botName string
|
|
httpClient *http.Client
|
|
retry httputil.RetryConfig
|
|
}
|
|
|
|
func NewSender(webhookURL, botName string) *Sender {
|
|
if botName == "" {
|
|
botName = "TrahnGridTrader"
|
|
}
|
|
return &Sender{
|
|
webhookURL: webhookURL,
|
|
botName: botName,
|
|
httpClient: &http.Client{Timeout: 10 * time.Second},
|
|
retry: httputil.RetryConfig{
|
|
MaxAttempts: 3,
|
|
BaseDelay: 1 * time.Second,
|
|
MaxDelay: 5 * time.Second,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *Sender) Send(msg string) {
|
|
formatted := fmt.Sprintf("[%s] %s", s.botName, msg)
|
|
fmt.Printf("[%s] %s\n", time.Now().UTC().Format(time.RFC3339), formatted)
|
|
|
|
if s.webhookURL == "" {
|
|
return
|
|
}
|
|
|
|
payload := s.formatPayload(formatted)
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
fmt.Printf("[CHAT ERROR] marshal: %v\n", err)
|
|
return
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
resp, err := httputil.Do(ctx, s.httpClient, s.retry, func() (*http.Request, error) {
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, s.webhookURL, bytes.NewReader(body))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
return req, nil
|
|
})
|
|
if err != nil {
|
|
fmt.Printf("[CHAT ERROR] Failed to send notification after retries: %v\n", err)
|
|
return
|
|
}
|
|
resp.Body.Close()
|
|
}
|
|
|
|
func (s *Sender) formatPayload(msg string) map[string]string {
|
|
if strings.Contains(s.webhookURL, "discord") {
|
|
return map[string]string{
|
|
"content": msg,
|
|
"username": s.botName,
|
|
}
|
|
}
|
|
return map[string]string{
|
|
"text": fmt.Sprintf("`%s`", msg),
|
|
"username": s.botName,
|
|
}
|
|
}
|
|
|
|
func (s *Sender) Enabled() bool {
|
|
return s.webhookURL != ""
|
|
}
|