GoDoxy/internal/notif/webhook.go

132 lines
3 KiB
Go

package notif
import (
_ "embed"
"encoding/json"
"io"
"net/http"
"strings"
"github.com/yusing/go-proxy/internal/gperr"
)
type Webhook struct {
ProviderBase
Template string `json:"template"`
Payload string `json:"payload"`
Method string `json:"method"`
MIMEType string `json:"mime_type"`
ColorMode string `json:"color_mode"`
}
//go:embed templates/discord.json
var discordPayload string
var webhookTemplates = map[string]string{
"discord": discordPayload,
}
func (webhook *Webhook) Validate() gperr.Error {
if err := webhook.ProviderBase.Validate(); err != nil && !err.Is(ErrMissingToken) {
return err
}
switch webhook.MIMEType {
case "":
webhook.MIMEType = "application/json"
case "application/json", "application/x-www-form-urlencoded", "text/plain":
default:
return gperr.New("invalid mime_type, expect empty, 'application/json', 'application/x-www-form-urlencoded' or 'text/plain'")
}
switch webhook.Template {
case "":
if webhook.MIMEType == "application/json" && !json.Valid([]byte(webhook.Payload)) {
return gperr.New("invalid payload, expect valid JSON")
}
if webhook.Payload == "" {
return gperr.New("invalid payload, expect non-empty")
}
case "discord":
webhook.ColorMode = "dec"
webhook.Method = http.MethodPost
webhook.MIMEType = "application/json"
if webhook.Payload == "" {
webhook.Payload = discordPayload
}
default:
return gperr.New("invalid template, expect empty or 'discord'")
}
switch webhook.Method {
case "":
webhook.Method = http.MethodPost
case http.MethodGet, http.MethodPost, http.MethodPut:
default:
return gperr.New("invalid method, expect empty, 'GET', 'POST' or 'PUT'")
}
switch webhook.ColorMode {
case "":
webhook.ColorMode = "hex"
case "hex", "dec":
default:
return gperr.New("invalid color_mode, expect empty, 'hex' or 'dec'")
}
return nil
}
// GetMethod implements Provider.
func (webhook *Webhook) GetMethod() string {
return webhook.Method
}
// GetMIMEType implements Provider.
func (webhook *Webhook) GetMIMEType() string {
return webhook.MIMEType
}
// fmtError implements Provider.
func (webhook *Webhook) fmtError(respBody io.Reader) error {
body, err := io.ReadAll(respBody)
if err != nil || len(body) == 0 {
return ErrUnknownError
}
return rawError(body)
}
func (webhook *Webhook) MarshalMessage(logMsg *LogMessage) ([]byte, error) {
title, err := json.Marshal(logMsg.Title)
if err != nil {
return nil, err
}
fields, err := logMsg.Body.Format(LogFormatRawJSON)
if err != nil {
return nil, err
}
var color string
if webhook.ColorMode == "hex" {
color = logMsg.Color.HexString()
} else {
color = logMsg.Color.DecString()
}
message, err := logMsg.Body.Format(LogFormatMarkdown)
if err != nil {
return nil, err
}
plTempl := strings.NewReplacer(
"$title", string(title),
"$message", string(message),
"$fields", string(fields),
"$color", color,
)
var pl string
if webhook.Template != "" {
pl = webhookTemplates[webhook.Template]
} else {
pl = webhook.Payload
}
pl = plTempl.Replace(pl)
return []byte(pl), nil
}