CI / test (pull_request) Successful in 6m29s
The picker accepts one MP4 or WebM, the thread lightbox zooms photos, and Discord gets the video as a file on a follow-up message so photo embeds still render.
134 lines
3.4 KiB
Go
134 lines
3.4 KiB
Go
package discord
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
// API is the Discord REST surface used by the outbound subscriber.
|
|
type API interface {
|
|
SendToChannel(ctx context.Context, channelID string, msg Message) (messageID string, err error)
|
|
StartThread(ctx context.Context, channelID, name string) (threadID string, err error)
|
|
SendToThread(ctx context.Context, threadID string, msg Message) (messageID string, err error)
|
|
Edit(ctx context.Context, channelID, messageID string, msg Message) error
|
|
Close() error
|
|
}
|
|
|
|
type sessionAPI struct {
|
|
session *discordgo.Session
|
|
}
|
|
|
|
func (s *sessionAPI) SendToChannel(_ context.Context, channelID string, msg Message) (string, error) {
|
|
sent, err := s.session.ChannelMessageSendComplex(channelID, toMessageSend(msg))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return sent.ID, nil
|
|
}
|
|
|
|
func (s *sessionAPI) StartThread(_ context.Context, channelID, name string) (string, error) {
|
|
thread, err := s.session.ThreadStartComplex(channelID, &discordgo.ThreadStart{
|
|
Name: name,
|
|
Type: discordgo.ChannelTypeGuildPublicThread,
|
|
AutoArchiveDuration: 10080,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return thread.ID, nil
|
|
}
|
|
|
|
func (s *sessionAPI) SendToThread(ctx context.Context, threadID string, msg Message) (string, error) {
|
|
return s.SendToChannel(ctx, threadID, msg)
|
|
}
|
|
|
|
func (s *sessionAPI) Edit(_ context.Context, channelID, messageID string, msg Message) error {
|
|
content := messageContent(msg)
|
|
embeds := toEmbeds(msg)
|
|
_, err := s.session.ChannelMessageEditComplex(&discordgo.MessageEdit{
|
|
ID: messageID,
|
|
Channel: channelID,
|
|
Content: &content,
|
|
Embeds: &embeds,
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (s *sessionAPI) Close() error {
|
|
if s == nil || s.session == nil {
|
|
return nil
|
|
}
|
|
return s.session.Close()
|
|
}
|
|
|
|
func toMessageSend(msg Message) *discordgo.MessageSend {
|
|
var files []*discordgo.File
|
|
for _, f := range msg.Files {
|
|
files = append(files, &discordgo.File{
|
|
Name: f.Name,
|
|
ContentType: f.ContentType,
|
|
Reader: f.Reader,
|
|
})
|
|
}
|
|
return &discordgo.MessageSend{
|
|
Content: messageContent(msg),
|
|
Embeds: toEmbeds(msg),
|
|
Files: files,
|
|
AllowedMentions: &discordgo.MessageAllowedMentions{},
|
|
}
|
|
}
|
|
|
|
func toEmbeds(msg Message) []*discordgo.MessageEmbed {
|
|
imageURLs := embedImageURLs(msg)
|
|
if msg.Title == "" && msg.Description == "" && msg.City == "" && msg.Author == "" && len(imageURLs) == 0 {
|
|
return nil
|
|
}
|
|
main := &discordgo.MessageEmbed{
|
|
Title: msg.Title,
|
|
URL: publicURL(msg.URL),
|
|
Description: msg.Description,
|
|
Color: embedColor,
|
|
}
|
|
if msg.City != "" {
|
|
main.Fields = append(main.Fields, &discordgo.MessageEmbedField{
|
|
Name: "City",
|
|
Value: msg.City,
|
|
Inline: true,
|
|
})
|
|
}
|
|
if msg.Author != "" {
|
|
main.Fields = append(main.Fields, &discordgo.MessageEmbedField{
|
|
Name: "Author",
|
|
Value: msg.Author,
|
|
Inline: true,
|
|
})
|
|
}
|
|
embeds := []*discordgo.MessageEmbed{main}
|
|
for i, url := range imageURLs {
|
|
if i == 0 {
|
|
main.Image = &discordgo.MessageEmbedImage{URL: url}
|
|
continue
|
|
}
|
|
embeds = append(embeds, &discordgo.MessageEmbed{
|
|
Color: embedColor,
|
|
Image: &discordgo.MessageEmbedImage{URL: url},
|
|
})
|
|
}
|
|
return embeds
|
|
}
|
|
|
|
func embedImageURLs(msg Message) []string {
|
|
var attached []string
|
|
for _, f := range msg.Files {
|
|
if strings.HasPrefix(f.ContentType, "image/") {
|
|
attached = append(attached, "attachment://"+f.Name)
|
|
}
|
|
}
|
|
if len(attached) > 0 {
|
|
return attached
|
|
}
|
|
return msg.ImageURLs
|
|
}
|