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"
|
||||
# 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 (
|
||||
HandlerFlux HandlerType = iota + 1
|
||||
HandlerDiscordEmbed
|
||||
)
|
||||
|
||||
func (h HandlerType) String() string {
|
||||
switch h {
|
||||
case HandlerFlux:
|
||||
return "flux"
|
||||
case HandlerDiscordEmbed:
|
||||
return "discord_embed"
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
@ -148,6 +151,8 @@ func readHandlerType(d *scfg.Directive) (HandlerType, error) {
|
|||
switch ty {
|
||||
case "flux":
|
||||
return HandlerFlux, nil
|
||||
case "discord_embed":
|
||||
return HandlerDiscordEmbed, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid handler type %q", ty)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@ data:
|
|||
type "flux"
|
||||
topic "flux"
|
||||
}
|
||||
|
||||
handler "/forgejo" {
|
||||
type "discord_embed"
|
||||
topic "forgejo"
|
||||
}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
|
2
main.go
2
main.go
|
@ -74,6 +74,8 @@ func main() {
|
|||
switch handler.Type {
|
||||
case config.HandlerFlux:
|
||||
h = bridge.NewFluxHandler()
|
||||
case config.HandlerDiscordEmbed:
|
||||
h = bridge.NewDiscordEmbedHandler()
|
||||
}
|
||||
|
||||
slog.Debug("Registering bridge", "route", route, "handler", handler.Type)
|
||||
|
|
Loading…
Reference in a new issue