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.
This commit is contained in:
+77
-24
@@ -16,7 +16,7 @@ import (
|
||||
"plumber/internal/store"
|
||||
)
|
||||
|
||||
const discordTimeout = 15 * time.Second
|
||||
const discordTimeout = 60 * time.Second
|
||||
|
||||
// Bot posts site events to a Discord channel and owns post-to-message links.
|
||||
type Bot struct {
|
||||
@@ -91,13 +91,27 @@ func (b *Bot) Handle(_ context.Context, ev any) {
|
||||
defer cancel()
|
||||
switch e := ev.(type) {
|
||||
case events.PostCreated:
|
||||
b.onCreated(ctx, e.PostEvent)
|
||||
defer b.publishPosted(e)
|
||||
b.onCreated(ctx, e)
|
||||
case events.PostUpdated:
|
||||
b.onUpdated(ctx, e.PostEvent)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bot) onCreated(ctx context.Context, ev events.PostEvent) {
|
||||
func (b *Bot) publishPosted(e events.PostCreated) {
|
||||
if e.Release == nil {
|
||||
return
|
||||
}
|
||||
done := events.PostedToDiscord{PostID: e.PostID, Release: e.Release}
|
||||
if b.bus == nil {
|
||||
e.Release()
|
||||
return
|
||||
}
|
||||
b.bus.Publish(context.Background(), done)
|
||||
}
|
||||
|
||||
func (b *Bot) onCreated(ctx context.Context, e events.PostCreated) {
|
||||
ev := e.PostEvent
|
||||
_, err := b.links.GetByPostID(ctx, ev.PostID)
|
||||
if err == nil {
|
||||
return
|
||||
@@ -107,17 +121,17 @@ func (b *Bot) onCreated(ctx context.Context, ev events.PostEvent) {
|
||||
return
|
||||
}
|
||||
if isRoot(ev) {
|
||||
b.createRoot(ctx, ev)
|
||||
b.createRoot(ctx, e)
|
||||
return
|
||||
}
|
||||
b.createReply(ctx, ev)
|
||||
b.createReply(ctx, e)
|
||||
}
|
||||
|
||||
func (b *Bot) onUpdated(ctx context.Context, ev events.PostEvent) {
|
||||
link, err := b.links.GetByPostID(ctx, ev.PostID)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
b.onCreated(ctx, ev)
|
||||
b.onCreated(ctx, events.PostCreated{PostEvent: ev})
|
||||
return
|
||||
}
|
||||
log.Printf("discord: load link %s: %v", ev.PostID, err)
|
||||
@@ -135,56 +149,95 @@ func (b *Bot) onUpdated(ctx context.Context, ev events.PostEvent) {
|
||||
log.Printf("discord: edited %s", ev.PostID)
|
||||
}
|
||||
|
||||
func (b *Bot) createRoot(ctx context.Context, ev events.PostEvent) {
|
||||
msg := formatMessage(ev)
|
||||
func (b *Bot) createRoot(ctx context.Context, e events.PostCreated) {
|
||||
msg := formatCreated(e)
|
||||
threadID, err := b.api.StartThread(ctx, b.channelID, msg.ThreadName)
|
||||
if err != nil {
|
||||
log.Printf("discord: start thread %s: %v", ev.PostID, err)
|
||||
log.Printf("discord: start thread %s: %v", e.PostID, err)
|
||||
return
|
||||
}
|
||||
messageID, err := b.api.SendToThread(ctx, threadID, msg)
|
||||
messageID, err := b.sendCreated(ctx, threadID, msg)
|
||||
if err != nil {
|
||||
log.Printf("discord: send root %s: %v", ev.PostID, err)
|
||||
log.Printf("discord: send root %s: %v", e.PostID, err)
|
||||
return
|
||||
}
|
||||
if err := b.links.Upsert(ctx, store.DiscordLink{
|
||||
PostID: ev.PostID,
|
||||
PostID: e.PostID,
|
||||
MessageID: messageID,
|
||||
ThreadID: threadID,
|
||||
}); err != nil {
|
||||
log.Printf("discord: save root link %s: %v", ev.PostID, err)
|
||||
log.Printf("discord: save root link %s: %v", e.PostID, err)
|
||||
return
|
||||
}
|
||||
log.Printf("discord: posted root %s", ev.PostID)
|
||||
log.Printf("discord: posted root %s", e.PostID)
|
||||
}
|
||||
|
||||
func (b *Bot) createReply(ctx context.Context, ev events.PostEvent) {
|
||||
root, err := b.links.GetByPostID(ctx, ev.RootID)
|
||||
func (b *Bot) createReply(ctx context.Context, e events.PostCreated) {
|
||||
root, err := b.links.GetByPostID(ctx, e.RootID)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
log.Printf("discord: skip reply %s: no root thread", ev.PostID)
|
||||
log.Printf("discord: skip reply %s: no root thread", e.PostID)
|
||||
return
|
||||
}
|
||||
log.Printf("discord: load root link %s: %v", ev.RootID, err)
|
||||
log.Printf("discord: load root link %s: %v", e.RootID, err)
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(root.ThreadID) == "" {
|
||||
log.Printf("discord: skip reply %s: no root thread", ev.PostID)
|
||||
log.Printf("discord: skip reply %s: no root thread", e.PostID)
|
||||
return
|
||||
}
|
||||
messageID, err := b.api.SendToThread(ctx, root.ThreadID, formatMessage(ev))
|
||||
messageID, err := b.sendCreated(ctx, root.ThreadID, formatCreated(e))
|
||||
if err != nil {
|
||||
log.Printf("discord: send reply %s: %v", ev.PostID, err)
|
||||
log.Printf("discord: send reply %s: %v", e.PostID, err)
|
||||
return
|
||||
}
|
||||
if err := b.links.Upsert(ctx, store.DiscordLink{
|
||||
PostID: ev.PostID,
|
||||
PostID: e.PostID,
|
||||
MessageID: messageID,
|
||||
}); err != nil {
|
||||
log.Printf("discord: save reply link %s: %v", ev.PostID, err)
|
||||
log.Printf("discord: save reply link %s: %v", e.PostID, err)
|
||||
return
|
||||
}
|
||||
log.Printf("discord: posted reply %s", ev.PostID)
|
||||
log.Printf("discord: posted reply %s", e.PostID)
|
||||
}
|
||||
|
||||
func (b *Bot) sendCreated(ctx context.Context, threadID string, msg Message) (string, error) {
|
||||
_, videos := splitAttachments(msg.Files)
|
||||
msg.Files = nil
|
||||
if len(videos) > 0 {
|
||||
msg.VideoURLs = nil
|
||||
}
|
||||
messageID, err := b.send(ctx, threadID, msg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, video := range videos {
|
||||
if _, err := b.send(ctx, threadID, Message{Files: []Attachment{video}}); err != nil {
|
||||
log.Printf("discord: send video %s: %v", threadID, err)
|
||||
}
|
||||
}
|
||||
return messageID, nil
|
||||
}
|
||||
|
||||
func splitAttachments(files []Attachment) (images, videos []Attachment) {
|
||||
for _, f := range files {
|
||||
if strings.HasPrefix(f.ContentType, "video/") || f.Kind == "video" {
|
||||
videos = append(videos, f)
|
||||
continue
|
||||
}
|
||||
images = append(images, f)
|
||||
}
|
||||
return images, videos
|
||||
}
|
||||
|
||||
func (b *Bot) send(ctx context.Context, threadID string, msg Message) (string, error) {
|
||||
messageID, err := b.api.SendToThread(ctx, threadID, msg)
|
||||
if err != nil && len(msg.Files) > 0 {
|
||||
log.Printf("discord: send with files %s: %v; retrying without files", threadID, err)
|
||||
msg.Files = nil
|
||||
return b.api.SendToThread(ctx, threadID, msg)
|
||||
}
|
||||
return messageID, err
|
||||
}
|
||||
|
||||
func (b *Bot) editChannel(ctx context.Context, ev events.PostEvent, link *store.DiscordLink) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user