Некоторые проверки не удались
CI / test (push) Successful in 2m5s
Docker / Build and publish worker image (push) Failing after 31s
156 строки
3.7 KiB
Go
156 строки
3.7 KiB
Go
package sender
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"rocketgit.ru/rsmon/worker/app/models"
|
|
"rocketgit.ru/rsmon/worker/internal/wire"
|
|
)
|
|
|
|
// messageKindUp is the canonical string the notifier uses for "monitor
|
|
// just came back up" events. Lives here as a package-level constant so
|
|
// the goconst linter stops flagging the literal "up" appearing three
|
|
// times across the sender package.
|
|
const messageKindUp = "up"
|
|
|
|
// MattermostPayload provides functionality.
|
|
type MattermostPayload struct {
|
|
Channel *string `json:"channel,omitempty"`
|
|
Username *string `json:"username,omitempty"`
|
|
IconURL *string `json:"icon_url,omitempty"`
|
|
Text *string `json:"text,omitempty"`
|
|
}
|
|
|
|
// RunMattermost provides functionality.
|
|
func RunMattermost(message *models.Message) (*string, error) {
|
|
_, _, markdownBody, _ := GetContent(message, time.Now())
|
|
|
|
s := "@channel "
|
|
if message.Kind == messageKindUp {
|
|
s += ":white_check_mark: "
|
|
} else {
|
|
s += ":warning: "
|
|
}
|
|
s = s + "\n\n" + markdownBody.String()
|
|
|
|
color := "green"
|
|
if message.Kind == "down" {
|
|
color = "red"
|
|
}
|
|
|
|
un := "RSMon"
|
|
icon := "https://rsmon.ru/" + color + "_logo.svg"
|
|
payload := MattermostPayload{
|
|
Text: &s,
|
|
Username: &un,
|
|
IconURL: &icon,
|
|
}
|
|
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
log.Println("send mattermost:", message.Contact.Value)
|
|
// log.Println(string(body))
|
|
|
|
resp, err := httpClient.Post(
|
|
message.Contact.Value,
|
|
"application/json",
|
|
bytes.NewBuffer(body),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer resp.Body.Close() //nolint:errcheck
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
str := string(body)
|
|
return &str, nil
|
|
}
|
|
|
|
// SendMattermostWithCredential delivers a Mattermost notification using the
|
|
// supplied wire credential block (which carries the default username +
|
|
// icon URL). The webhook URL is per-task; the credential block only sets
|
|
// the cosmetic defaults. This mirrors what the legacy RunMattermost did with
|
|
// secrets + a hardcoded RSMon username / icon.
|
|
func SendMattermostWithCredential(
|
|
contactValue, messageKind, subject, markdownBody string,
|
|
cred *wire.MattermostCredential,
|
|
) (*string, error) {
|
|
return SendMattermostWithCredentialContext(context.Background(), contactValue, messageKind, subject, markdownBody, cred)
|
|
}
|
|
|
|
func SendMattermostWithCredentialContext(
|
|
ctx context.Context, contactValue, messageKind, subject, markdownBody string,
|
|
cred *wire.MattermostCredential,
|
|
) (*string, error) {
|
|
if contactValue == "" {
|
|
return nil, errors.New("mattermost contact value is empty")
|
|
}
|
|
|
|
s := "@channel "
|
|
if messageKind == messageKindUp {
|
|
s += ":white_check_mark: "
|
|
} else {
|
|
s += ":warning: "
|
|
}
|
|
s = s + "\n\n" + subject + "\n\n" + markdownBody
|
|
|
|
color := "green"
|
|
if messageKind == "down" {
|
|
color = "red"
|
|
}
|
|
|
|
username := "RSMon"
|
|
iconURL := "https://rsmon.ru/" + color + "_logo.svg"
|
|
if cred != nil {
|
|
if cred.DefaultUsername != "" {
|
|
username = cred.DefaultUsername
|
|
}
|
|
if cred.DefaultIconURL != "" {
|
|
iconURL = cred.DefaultIconURL
|
|
}
|
|
}
|
|
|
|
payload := MattermostPayload{
|
|
Text: &s,
|
|
Username: &username,
|
|
IconURL: &iconURL,
|
|
}
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client := &http.Client{Timeout: 60 * time.Second}
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, contactValue, bytes.NewBuffer(body))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close() //nolint:errcheck
|
|
|
|
respBody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
str := string(respBody)
|
|
return &str, nil
|
|
}
|