1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-09-07 12:46:23 -07:00

Update templates with embed stuff, add example URL matchers

This commit is contained in:
Eggbertx 2025-03-15 23:52:13 -07:00
parent 2facfe68fc
commit 4929366f82
8 changed files with 101 additions and 13 deletions

View file

@ -95,10 +95,26 @@
"EnableCyclicThreads": true,
"CyclicThreadNumPosts": 500,
"EnableEmbeds": true,
"EnableNoFlag": true,
"EmbedWidth": 200,
"EmbedHeight": 164,
"EmbedHeight": 200,
"EmbedMatchers": {
"youtube": {
"URLRegex": "^https?://(?:(?:(?:www\\.)?youtube\\.com/watch\\?v=)|(?:youtu\\.be/))([^&]+)",
"EmbedTemplate": "<iframe class=\"embed\" width={{.ThumbWidth}} height={{.ThumbHeight}} src=\"https://www.youtube-nocookie.com/embed/{{.VideoID}}\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>",
"ThumbnailURLTemplate": "https://img.youtube.com/vi/{{.VideoID}}/0.jpg"
},
"vimeo": {
"URLRegex": "^https?://(?:\\w+\\.)?vimeo\\.com/(\\d{2,10})",
"EmbedTemplate": "<iframe src=\"https://player.vimeo.com/video/{{.VideoID}}\" class=\"embed\" width={{.ThumbWidth}} height={{.ThumbHeight}} allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>",
"ThumbnailURLTemplate": "https://vumbnail.com/{{.VideoID}}.jpg"
},
"rawvideo": {
"URLRegex": "^https?://\\S+\\.\\S+/\\S+/(\\S+\\.(?:mp4|webm))$",
"EmbedTemplate": "<video class=\"embed\" src=\"{{.VideoID}}\"></video>",
"VideoIDSubmatchIndex": 0
}
},
"ImagesOpenNewTab": true,
"NewTabOnOutlinks": true,
"DisableBBcode": false,

View file

@ -6,6 +6,7 @@ import (
"net"
"path"
"strconv"
"strings"
"time"
"github.com/gochan-org/gochan/pkg/config"
@ -76,8 +77,12 @@ func (p *Post) WebPath() string {
return p.ThreadPath() + "#" + strconv.Itoa(p.ID)
}
func (p *Post) HasEmbed() bool {
return strings.HasPrefix(p.Filename, "embed:")
}
func (p *Post) ThumbnailPath() string {
if p.Filename == "" {
if p.Filename == "" || p.HasEmbed() {
return ""
}
thumbnail, _ := uploads.GetThumbnailFilenames(p.Filename)
@ -85,7 +90,7 @@ func (p *Post) ThumbnailPath() string {
}
func (p *Post) UploadPath() string {
if p.Filename == "" {
if p.Filename == "" || p.HasEmbed() {
return ""
}
return config.WebPath(p.BoardDir, "src", p.Filename)

View file

@ -664,6 +664,19 @@ func (pc *PostConfig) GetEmbedVideoID(url string) (string, string, error) {
return "", "", ErrNoMatchingEmbedHandler
}
// GetEmbedTemplates returns the embed and (if it has one) thumbnail URL templates for the given embed ID
func (pc *PostConfig) GetEmbedTemplates(embedID string) (*template.Template, *template.Template, error) {
embedTmpl, ok := pc.embedMatchersEmbedTemplate[embedID]
if !ok {
return nil, nil, ErrNoMatchingEmbedHandler
}
thumbTmpl, ok := pc.embedMatchersThumbnailURLTemplate[embedID]
if !ok {
thumbTmpl = nil
}
return embedTmpl, thumbTmpl, nil
}
func (pc *PostConfig) validateEmbedMatchers() error {
if pc.EmbedMatchers == nil {
return nil

View file

@ -1,6 +1,7 @@
package gctemplates
import (
"bytes"
"errors"
"fmt"
"html"
@ -23,6 +24,13 @@ var (
ErrInvalidMap = errors.New("invalid template map call")
)
type EmbedVideo struct {
VideoID string
Handler string
ThumbWidth int
ThumbHeight int
}
var funcMap = template.FuncMap{
// Arithmetic functions
"add": func(a, b int) int {
@ -165,6 +173,38 @@ var funcMap = template.FuncMap{
}
return dir
},
"embedVideo": func(filename string, videoID string, board string) template.HTML {
filenameParts := strings.SplitN(filename, ":", 2)
if len(filenameParts) != 2 {
return "invalid embed ID"
}
boardCfg := config.GetBoardConfig(board)
embedTmpl, thumbTmpl, err := boardCfg.GetEmbedTemplates(filenameParts[1])
if err != nil {
return template.HTML(err.Error())
}
templateData := EmbedVideo{
VideoID: videoID,
Handler: filenameParts[1],
ThumbWidth: boardCfg.EmbedWidth,
ThumbHeight: boardCfg.EmbedHeight,
}
var buf bytes.Buffer
if thumbTmpl != nil {
if err := thumbTmpl.Execute(&buf, templateData); err != nil {
return template.HTML(err.Error())
}
return template.HTML(`<img src="` + buf.String() + `" alt="Video thumbnail" class="embed thumb">`)
}
if err = embedTmpl.Execute(&buf, templateData); err != nil {
return template.HTML(err.Error())
}
return template.HTML(buf.String())
},
// Template convenience functions
"makeLoop": func(n int, offset int) []int {
loopArr := make([]int, n)

View file

@ -14,13 +14,6 @@ var (
ErrUnrecognizedEmbed = errors.New("unrecognized embed URL")
)
type EmbedVideo struct {
VideoID string
Handler string
ThumbWidth int
ThumbHeight int
}
// AttachEmbedFromRequest checks if the post contains an embedded media URL from the form (if applicable) and if it is valid.
// It returns true if the post contains an embedded media URL, an error if the URL is invalid or some other error occurred.
// It attaches the embed as a pseudo-upload in the database if the URL is valid.

View file

@ -459,6 +459,18 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
server.ServeError(writer, err.Error(), wantsJSON, nil)
return
}
embed, err := AttachEmbedFromRequest(request, boardConfig, warnEv, errEv)
if err != nil {
server.ServeError(writer, err.Error(), wantsJSON, nil)
return
}
if embed != nil {
// CheckAndAttachEmbed verifies that the post does not already have an embed or an upload, so upload
// is guaranteed to be nil here
upload = embed
}
var filePath, thumbPath, catalogThumbPath string
documentRoot := config.GetSystemCriticalConfig().DocumentRoot
if upload != nil {
@ -478,7 +490,7 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
errEv.Err(err).Caller().
Str("sql", "postInsertion").
Msg("Unable to insert post")
if upload != nil {
if upload != nil && !upload.IsEmbed() {
os.Remove(filePath)
os.Remove(thumbPath)
os.Remove(catalogThumbPath)

View file

@ -39,7 +39,13 @@
<div class="file-deleted-box" style="text-align:center;">File removed</div>
{{- else if ne $.post.Filename "" -}}
{{- template "uploadinfo" . -}}
<a class="upload-container" href="{{.post.UploadPath}}"><img src="{{getThumbnailWebPath .post.ID}}" alt="{{.post.UploadPath}}" width="{{.post.ThumbnailWidth}}" height="{{.post.ThumbnailHeight}}" class="upload thumb" /></a>
<a class="upload-container" href="{{.post.UploadPath}}">
{{- if $.post.HasEmbed -}}
{{embedVideo .post.Filename .post.OriginalFilename $.board.Dir}}
{{- else -}}
<img src="{{getThumbnailWebPath .post.ID}}" alt="{{.post.UploadPath}}" width="{{.post.ThumbnailWidth}}" height="{{.post.ThumbnailHeight}}" class="upload thumb" />
{{- end -}}
</a>
{{- end -}}
{{- if $.post.IsTopPost}}{{template "nameline" .}}{{end -}}
<div class="post-text">{{.post.Message}}</div>

View file

@ -14,6 +14,9 @@
{{- if $.boardConfig.EnableSpoileredImages -}}
<label for="spoiler"><input type="checkbox" id="spoiler" name="spoiler"/>Spoiler</label>
{{- end}}</td></tr>
{{- if $.boardConfig.HasEmbedMatchers -}}
<tr><th class="postblock">Embed</th><td><input type="text" name="embed" size="25" /></td></tr>
{{- end -}}
{{- if or (customFlagsEnabled $.board.Dir) $.boardConfig.EnableGeoIP -}}
<tr>
<th class="postblock">Flag</th>