feat: add discord_embed handler
This commit is contained in:
parent
64e91cb2d4
commit
c832ea4645
5 changed files with 95 additions and 0 deletions
74
bridge/discord.go
Normal file
74
bridge/discord.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscordMessage struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
Embeds []struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Footer struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
} `json:"footer"`
|
||||||
|
Author struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"author"`
|
||||||
|
} `json:"embeds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscordEmbedHandler struct{}
|
||||||
|
|
||||||
|
func NewDiscordEmbedHandler() DiscordEmbedHandler {
|
||||||
|
return DiscordEmbedHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DiscordEmbedHandler) ProduceNotifications(r *http.Request) ([]Notification, error) {
|
||||||
|
l := slog.With(slog.String("handler", "discord_embed"))
|
||||||
|
|
||||||
|
dec := json.NewDecoder(r.Body)
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
var not DiscordMessage
|
||||||
|
if err := dec.Decode(¬); err != nil {
|
||||||
|
l.Error("invalid message format", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications := make([]Notification, len(not.Embeds))
|
||||||
|
for i, embed := range not.Embeds {
|
||||||
|
not := notifications[i]
|
||||||
|
not.Title = embed.Title
|
||||||
|
not.IsMarkdown = true
|
||||||
|
if embed.URL != "" {
|
||||||
|
not.Actions = []NotificationAction{NewViewAction("Open in Browser", embed.URL)}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body strings.Builder
|
||||||
|
body.WriteString(embed.Description)
|
||||||
|
|
||||||
|
if embed.Author.Name != "" {
|
||||||
|
body.WriteString("\n\n**Author**\n")
|
||||||
|
body.WriteString(embed.Author.Name)
|
||||||
|
if embed.Author.URL != "" {
|
||||||
|
body.WriteString(" (" + embed.Author.URL + ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if embed.Footer.Text != "" {
|
||||||
|
body.WriteString("\n\n" + embed.Footer.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
not.Body = body.String()
|
||||||
|
|
||||||
|
notifications[i] = not
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifications, nil
|
||||||
|
}
|
|
@ -23,3 +23,12 @@ handler "/flux" {
|
||||||
# type "alertmanager"
|
# type "alertmanager"
|
||||||
# topic "/infra"
|
# topic "/infra"
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
# Handle discord type messages. This is meant for
|
||||||
|
# webhook that doesn't support generic one's.
|
||||||
|
# Instead, we convert discord messages to ntfy message.
|
||||||
|
# See: https://discord.com/developers/docs/resources/channel#message-object
|
||||||
|
handler "/discord-like" {
|
||||||
|
type "discord_embed" # handle message with `embeds` content
|
||||||
|
topic "discord-like"
|
||||||
|
}
|
||||||
|
|
|
@ -11,12 +11,15 @@ type HandlerType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HandlerFlux HandlerType = iota + 1
|
HandlerFlux HandlerType = iota + 1
|
||||||
|
HandlerDiscordEmbed
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h HandlerType) String() string {
|
func (h HandlerType) String() string {
|
||||||
switch h {
|
switch h {
|
||||||
case HandlerFlux:
|
case HandlerFlux:
|
||||||
return "flux"
|
return "flux"
|
||||||
|
case HandlerDiscordEmbed:
|
||||||
|
return "discord_embed"
|
||||||
}
|
}
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
@ -148,6 +151,8 @@ func readHandlerType(d *scfg.Directive) (HandlerType, error) {
|
||||||
switch ty {
|
switch ty {
|
||||||
case "flux":
|
case "flux":
|
||||||
return HandlerFlux, nil
|
return HandlerFlux, nil
|
||||||
|
case "discord_embed":
|
||||||
|
return HandlerDiscordEmbed, nil
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("invalid handler type %q", ty)
|
return 0, fmt.Errorf("invalid handler type %q", ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ data:
|
||||||
type "flux"
|
type "flux"
|
||||||
topic "flux"
|
topic "flux"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handler "/forgejo" {
|
||||||
|
type "discord_embed"
|
||||||
|
topic "forgejo"
|
||||||
|
}
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
|
|
2
main.go
2
main.go
|
@ -74,6 +74,8 @@ func main() {
|
||||||
switch handler.Type {
|
switch handler.Type {
|
||||||
case config.HandlerFlux:
|
case config.HandlerFlux:
|
||||||
h = bridge.NewFluxHandler()
|
h = bridge.NewFluxHandler()
|
||||||
|
case config.HandlerDiscordEmbed:
|
||||||
|
h = bridge.NewDiscordEmbedHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("Registering bridge", "route", route, "handler", handler.Type)
|
slog.Debug("Registering bridge", "route", route, "handler", handler.Type)
|
||||||
|
|
Loading…
Reference in a new issue