mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-11-09 00:30:02 +00:00
302 lines
9.9 KiB
Go
302 lines
9.9 KiB
Go
package messagehook
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/pkg/errors"
|
|
"gopkg.in/irc.v4"
|
|
|
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
)
|
|
|
|
type (
|
|
discordActor struct {
|
|
plugins.ActorKit
|
|
}
|
|
|
|
discordPayload struct {
|
|
Content string `json:"content"`
|
|
Username string `json:"username,omitempty"`
|
|
AvatarURL string `json:"avatar_url,omitempty"`
|
|
Embeds []discordPayloadEmbed `json:"embeds,omitempty"`
|
|
}
|
|
|
|
discordPayloadEmbed struct {
|
|
Title string `json:"title,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
URL string `json:"url,omitempty"`
|
|
Color int64 `json:"color,omitempty"`
|
|
Image *discordPayloadEmbedImage `json:"image,omitempty"`
|
|
Thumbnail *discordPayloadEmbedImage `json:"thumbnail,omitempty"`
|
|
Author *discordPayloadEmbedAuthor `json:"author,omitempty"`
|
|
Fields []discordPayloadEmbedField `json:"fields,omitempty"`
|
|
}
|
|
|
|
discordPayloadEmbedAuthor struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url,omitempty"`
|
|
IconURL string `json:"icon_url,omitempty"`
|
|
}
|
|
|
|
discordPayloadEmbedField struct {
|
|
Name string `json:"name"`
|
|
Value string `json:"value"`
|
|
Inline bool `json:"inline"`
|
|
}
|
|
|
|
discordPayloadEmbedImage struct {
|
|
URL string `json:"url"`
|
|
}
|
|
)
|
|
|
|
func (d discordActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
|
var payload discordPayload
|
|
|
|
if payload.Content, err = formatMessage(attrs.MustString("content", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return false, errors.Wrap(err, "parsing content")
|
|
}
|
|
|
|
if payload.Username, err = formatMessage(attrs.MustString("username", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return false, errors.Wrap(err, "parsing username")
|
|
}
|
|
|
|
if payload.AvatarURL, err = formatMessage(attrs.MustString("avatar_url", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return false, errors.Wrap(err, "parsing avatar_url")
|
|
}
|
|
|
|
if err = d.addEmbed(&payload, m, r, eventData, attrs); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return sendPayload(attrs.MustString("hook_url", ptrStringEmpty), payload, http.StatusNoContent)
|
|
}
|
|
|
|
func (discordActor) IsAsync() bool { return false }
|
|
|
|
func (discordActor) Name() string { return "discordhook" }
|
|
|
|
func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
|
if err = d.ValidateRequireNonEmpty(attrs, "hook_url"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = d.ValidateRequireValidTemplate(tplValidator, attrs, "content"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = d.ValidateRequireValidTemplateIfSet(tplValidator, attrs, "avatar_url", "username"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !attrs.MustBool("add_embed", ptrBoolFalse) {
|
|
// We're not validating the rest if embeds are disabled but in
|
|
// this case the content is mandatory
|
|
return d.ValidateRequireNonEmpty(attrs, "content")
|
|
}
|
|
|
|
return d.ValidateRequireValidTemplateIfSet(
|
|
tplValidator, attrs,
|
|
"embed_title",
|
|
"embed_description",
|
|
"embed_url",
|
|
"embed_image",
|
|
"embed_thumbnail",
|
|
"embed_author_name",
|
|
"embed_author_url",
|
|
"embed_author_icon_url",
|
|
"embed_fields",
|
|
)
|
|
}
|
|
|
|
//nolint:gocyclo // It's complex but just a bunch of converters
|
|
func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (err error) {
|
|
if !attrs.MustBool("add_embed", ptrBoolFalse) {
|
|
// No embed? No problem!
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
embed discordPayloadEmbed
|
|
sv string
|
|
)
|
|
|
|
if embed.Title, err = formatMessage(attrs.MustString("embed_title", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_title")
|
|
}
|
|
|
|
if embed.Description, err = formatMessage(attrs.MustString("embed_description", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_description")
|
|
}
|
|
|
|
if embed.URL, err = formatMessage(attrs.MustString("embed_url", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_url")
|
|
}
|
|
|
|
if sv, err = formatMessage(attrs.MustString("embed_image", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_image")
|
|
} else if sv != "" {
|
|
embed.Image = &discordPayloadEmbedImage{URL: sv}
|
|
}
|
|
|
|
if sv, err = formatMessage(attrs.MustString("embed_thumbnail", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_thumbnail")
|
|
} else if sv != "" {
|
|
embed.Thumbnail = &discordPayloadEmbedImage{URL: sv}
|
|
}
|
|
|
|
if sv, err = formatMessage(attrs.MustString("embed_author_name", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_author_name")
|
|
} else if sv != "" {
|
|
embed.Author = &discordPayloadEmbedAuthor{Name: sv}
|
|
|
|
if embed.Author.URL, err = formatMessage(attrs.MustString("embed_author_url", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_author_url")
|
|
}
|
|
|
|
if embed.Author.IconURL, err = formatMessage(attrs.MustString("embed_author_icon_url", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_author_icon_url")
|
|
}
|
|
}
|
|
|
|
if sv, err = formatMessage(attrs.MustString("embed_fields", ptrStringEmpty), m, r, eventData); err != nil {
|
|
return errors.Wrap(err, "parsing embed_fields")
|
|
} else if sv != "" {
|
|
var flds []discordPayloadEmbedField
|
|
if err = json.Unmarshal([]byte(sv), &flds); err != nil {
|
|
return errors.Wrap(err, "unmarshalling embed_fields")
|
|
}
|
|
|
|
embed.Fields = flds
|
|
}
|
|
|
|
payload.Embeds = append(payload.Embeds, embed)
|
|
return nil
|
|
}
|
|
|
|
//nolint:funlen // This is just a bunch of field descriptions
|
|
func (discordActor) register(args plugins.RegistrationArguments) {
|
|
args.RegisterActor("discordhook", func() plugins.Actor { return &discordActor{} })
|
|
|
|
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
|
Description: "Sends a message to a Discord Web-hook",
|
|
Name: "Discord Message-Webhook",
|
|
Type: "discordhook",
|
|
|
|
Fields: []plugins.ActionDocumentationField{
|
|
{
|
|
Description: "URL to send the POST request to",
|
|
Key: "hook_url",
|
|
Name: "Hook URL",
|
|
Optional: false,
|
|
SupportTemplate: false,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Overwrites the username set in the webhook configuration",
|
|
Key: "username",
|
|
Name: "Username",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Overwrites the avatar set in the webhook configuration",
|
|
Key: "avatar_url",
|
|
Name: "Avatar URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Message content to send to the web-hook (this must be set if embed is disabled)",
|
|
Key: "content",
|
|
Name: "Message",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Default: "false",
|
|
Description: "Whether to include the embed in the post",
|
|
Key: "add_embed",
|
|
Name: "Add Embed",
|
|
Optional: true,
|
|
SupportTemplate: false,
|
|
Type: plugins.ActionDocumentationFieldTypeBool,
|
|
},
|
|
{
|
|
Description: "Title of the embed",
|
|
Key: "embed_title",
|
|
Name: "Embed Title",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Description of the embed",
|
|
Key: "embed_description",
|
|
Name: "Embed Description",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "URL the title should link to",
|
|
Key: "embed_url",
|
|
Name: "Embed URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "URL of the big image displayed in the embed",
|
|
Key: "embed_image",
|
|
Name: "Embed Image URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "URL of the small image displayed in the embed",
|
|
Key: "embed_thumbnail",
|
|
Name: "Embed Thumbnail URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Name of the post author (if empty all other author-fields are ignored)",
|
|
Key: "embed_author_name",
|
|
Name: "Embed Author Name",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "URL the author name should link to",
|
|
Key: "embed_author_url",
|
|
Name: "Embed Author URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "URL of the author avatar",
|
|
Key: "embed_author_icon_url",
|
|
Name: "Embed Author Avatar URL",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
{
|
|
Description: "Fields to display in the embed (must yield valid JSON: `[{\"name\": \"\", \"value\": \"\", \"inline\": false}]`)",
|
|
Key: "embed_fields",
|
|
Name: "Embed Fields",
|
|
Optional: true,
|
|
SupportTemplate: true,
|
|
Type: plugins.ActionDocumentationFieldTypeString,
|
|
},
|
|
},
|
|
})
|
|
}
|