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:
@@ -1,6 +1,8 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"plumber/internal/events"
|
||||
@@ -13,6 +15,14 @@ const (
|
||||
embedColor = 0xe96a26
|
||||
)
|
||||
|
||||
// Attachment is a local file Discord should upload with the message.
|
||||
type Attachment struct {
|
||||
Name string
|
||||
ContentType string
|
||||
Kind string
|
||||
Reader io.Reader
|
||||
}
|
||||
|
||||
// Message is a Discord-ready snapshot of a site post event.
|
||||
type Message struct {
|
||||
Title string
|
||||
@@ -21,36 +31,76 @@ type Message struct {
|
||||
City string
|
||||
Author string
|
||||
ImageURLs []string
|
||||
VideoURLs []string
|
||||
Files []Attachment
|
||||
ThreadName string
|
||||
}
|
||||
|
||||
func formatMessage(ev events.PostEvent) Message {
|
||||
title := strings.TrimSpace(ev.Title)
|
||||
return formatCreated(events.PostCreated{PostEvent: ev})
|
||||
}
|
||||
|
||||
func formatCreated(e events.PostCreated) Message {
|
||||
title := strings.TrimSpace(e.Title)
|
||||
if title == "" {
|
||||
title = "Reply"
|
||||
}
|
||||
author := strings.TrimSpace(ev.AuthorName)
|
||||
author := strings.TrimSpace(e.AuthorName)
|
||||
if author == "" {
|
||||
author = "Someone"
|
||||
}
|
||||
msg := Message{
|
||||
Title: truncateRunes(title, embedTitleLimit),
|
||||
URL: strings.TrimSpace(ev.Permalink),
|
||||
Description: truncateRunes(strings.TrimSpace(ev.Body), embedDescriptionLimit),
|
||||
City: strings.TrimSpace(ev.City),
|
||||
URL: strings.TrimSpace(e.Permalink),
|
||||
Description: truncateRunes(strings.TrimSpace(e.Body), embedDescriptionLimit),
|
||||
City: strings.TrimSpace(e.City),
|
||||
Author: author,
|
||||
ThreadName: threadName(author, ev.Title),
|
||||
ThreadName: threadName(author, e.Title),
|
||||
Files: filesFromMedia(e.Media),
|
||||
}
|
||||
for _, img := range ev.Images {
|
||||
for _, img := range e.Images {
|
||||
url := strings.TrimSpace(img.URL)
|
||||
if url == "" {
|
||||
continue
|
||||
}
|
||||
if img.Kind == "video" {
|
||||
msg.VideoURLs = append(msg.VideoURLs, url)
|
||||
continue
|
||||
}
|
||||
msg.ImageURLs = append(msg.ImageURLs, url)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func filesFromMedia(media []events.Media) []Attachment {
|
||||
if len(media) == 0 {
|
||||
return nil
|
||||
}
|
||||
files := make([]Attachment, 0, len(media))
|
||||
for _, m := range media {
|
||||
var r io.Reader
|
||||
switch {
|
||||
case len(m.Bytes) > 0:
|
||||
r = bytes.NewReader(m.Bytes)
|
||||
case m.Body != nil:
|
||||
r = m.Body
|
||||
default:
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSpace(m.Name)
|
||||
if name == "" {
|
||||
name = "upload"
|
||||
}
|
||||
files = append(files, Attachment{
|
||||
Name: name,
|
||||
ContentType: m.ContentType,
|
||||
Kind: m.Kind,
|
||||
Reader: r,
|
||||
})
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
func threadName(author, title string) string {
|
||||
author = strings.TrimSpace(author)
|
||||
if author == "" {
|
||||
@@ -96,6 +146,18 @@ func messageContent(msg Message) string {
|
||||
if u := publicURL(msg.URL); u != "" {
|
||||
parts = append(parts, u)
|
||||
}
|
||||
if len(msg.Files) == 0 {
|
||||
for _, mediaURL := range msg.ImageURLs {
|
||||
if u := publicURL(mediaURL); u != "" {
|
||||
parts = append(parts, u)
|
||||
}
|
||||
}
|
||||
for _, mediaURL := range msg.VideoURLs {
|
||||
if u := publicURL(mediaURL); u != "" {
|
||||
parts = append(parts, u)
|
||||
}
|
||||
}
|
||||
}
|
||||
return truncateRunes(strings.Join(parts, "\n"), 2000)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user