aboutsummaryrefslogtreecommitdiff
path: root/backend/internal/alerts/alerts.go
blob: 44d4a50e38079461aa86ce53d160f36e9d1f56ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package alerts

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"yaum/internal/model"
)

type SMTPConfig struct {
	Host     string
	Port     int
	Username string
	Password string
	From     string
}

func SendDiscord(webhookURL string, svc model.Service, hb model.Heartbeat, wasUp bool) {
	color := 15548997
	title := "🔴 Site Fora do Ar"
	if hb.IsUp {
		color = 5763719
		title = "🟢 Site Recuperado"
	}

	desc := "o servico caiu"
	fields := []map[string]any{
		{"name": "URL", "value": svc.URL, "inline": true},
		{"name": "Codigo", "value": fmt.Sprintf("`%d`", hb.StatusCode), "inline": true},
		{"name": "Tempo", "value": fmt.Sprintf("%dms", hb.ResponseTimeMs), "inline": true},
	}
	if hb.ErrorMessage != "" {
		fields = append(fields, map[string]any{"name": "Erro", "value": hb.ErrorMessage, "inline": false})
	}
	if hb.IsUp {
		desc = "o servico voltou"
	}

	payload := map[string]any{
		"embeds": []map[string]any{
			{
				"title":       title + " | " + svc.Name,
				"description": desc,
				"color":       color,
				"fields":      fields,
				"footer":      map[string]any{"text": "YAUM — Yet Another Uptime Monitor"},
				"timestamp":   hb.TestedAt.Format(time.RFC3339),
			},
		},
		"username": "YAUM",
	}

	data, _ := json.Marshal(payload)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Post(webhookURL, "application/json", bytes.NewReader(data))
	if err != nil {
		log.Printf("[alerta:discord] erro ao enviar: %v", err)
		return
	}
	resp.Body.Close()
	if resp.StatusCode >= 400 {
		log.Printf("[alerta:discord] webhook retornou %d", resp.StatusCode)
		return
	}
	log.Printf("[alerta:discord] webhook enviado para '%s'", svc.Name)
}

func SendEmail(svc model.Service, hb model.Heartbeat, wasUp bool, cfg *SMTPConfig) {
	if cfg == nil || cfg.From == "" || cfg.Host == "" {
		log.Println("[alerta:email] smtp nao configurado — pulando")
		return
	}

	statusEmoji := "🟢"
	statusTxt := "UP"
	subject := "[YAUM] Site Recuperado: " + svc.Name
	if !hb.IsUp {
		statusEmoji = "🔴"
		statusTxt = "DOWN"
		subject = "[YAUM] Site Fora do Ar: " + svc.Name
	}

	body := fmt.Sprintf(`YAUM — Yet Another Uptime Monitor

%s Status: %s

Servico: %s
URL: %s
Status HTTP: %d
Tempo de Resposta: %dms
Mensagem: %s
Testado em: %s
`,
		statusEmoji, statusTxt,
		svc.Name, svc.URL, hb.StatusCode, hb.ResponseTimeMs, hb.ErrorMessage,
		hb.TestedAt.Format("2006-01-02 15:04:05 MST"),
	)

	if err := sendMail(hostPort(cfg.Host, cfg.Port), cfg.Username, cfg.Password, cfg.From, []string{svc.AlertEmail}, subject, body); err != nil {
		log.Printf("[alerta:email] erro: %v", err)
		return
	}
	log.Printf("[alerta:email] email enviado para %s", svc.AlertEmail)
}

func hostPort(host string, port int) string {
	return fmt.Sprintf("%s:%d", host, port)
}