1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-29 08:56:23 -07:00

Start moving template functions to their respective packages

This commit is contained in:
Eggbertx 2024-03-13 13:41:15 -07:00
parent f16fa39770
commit 4b5ea350eb
10 changed files with 192 additions and 143 deletions

View file

@ -92,7 +92,7 @@ func (p Post) TitleText() string {
return title
}
func (p Post) ThreadPath() string {
func (p *Post) ThreadPath() string {
threadID := p.ParentID
if threadID == 0 {
threadID = p.ID
@ -100,11 +100,11 @@ func (p Post) ThreadPath() string {
return config.WebPath(p.BoardDir, "res", strconv.Itoa(threadID)+".html")
}
func (p Post) WebPath() string {
func (p *Post) WebPath() string {
return p.ThreadPath() + "#" + strconv.Itoa(p.ID)
}
func (p Post) ThumbnailPath() string {
func (p *Post) ThumbnailPath() string {
if p.Filename == "" {
return ""
}

117
pkg/gcsql/templatefuncs.go Normal file
View file

@ -0,0 +1,117 @@
package gcsql
import (
"strconv"
"text/template"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gctemplates"
"github.com/gochan-org/gochan/pkg/gcutil"
)
func init() {
gctemplates.AddTemplateFuncs(template.FuncMap{
"bannedForever": func(ban *IPBan) bool {
return ban.IsActive && ban.Permanent && !ban.CanAppeal
},
"isBanned": func(ban *IPBan, board string) bool {
return ban.IsActive && ban.BoardID != nil
},
"banMask": func(ban IPBan) string {
if ban.ID < 1 {
if ban.RangeStart == ban.RangeEnd {
return ban.RangeStart
}
return ""
}
ipn, err := gcutil.GetIPRangeSubnet(ban.RangeStart, ban.RangeEnd)
if err != nil {
return "?"
}
return ipn.String()
},
"getBoardDirFromID": func(id int) string {
dir, _ := GetBoardDir(id)
return dir
},
"intPtrToBoardDir": func(id *int, ifNil string, ifErr string) string {
if id == nil {
return ifNil
}
dir, err := GetBoardDir(*id)
if err != nil {
return ifErr
}
return dir
},
"getStaffNameFromID": func(id int) string {
username, err := GetStaffUsernameFromID(id)
if err != nil {
return "?"
}
return username
},
"getAppealBanIP": func(appealID int) string {
ban, err := GetIPBanByID(appealID)
if err != nil || ban == nil {
return "?"
}
if ban.RangeStart == ban.RangeEnd {
return ban.RangeStart
}
ipn, err := gcutil.GetIPRangeSubnet(ban.RangeStart, ban.RangeEnd)
if err != nil {
return "?"
}
return ipn.String()
},
"getTopPostID": func(post *Post) int {
id, _ := post.TopPostID()
return id
},
"numReplies": func(boardid, opID int) int {
num, err := GetThreadReplyCountFromOP(opID)
if err != nil {
return 0
}
return num
},
"getBoardDir": func(id int) string {
dir, err := GetBoardDir(id)
if err != nil {
return ""
}
return dir
},
"boardPagePath": func(board *Board, page int) string {
return config.WebPath(board.Dir, strconv.Itoa(page)+".html")
},
"getBoardDefaultStyle": func(dir string) string {
boardCfg := config.GetBoardConfig(dir)
if !boardCfg.IsGlobal() {
// /<board>/board.json exists, overriding the default them and theme set in SQL
return boardCfg.DefaultStyle
}
var defaultStyle string
err := QueryRowSQL(`SELECT default_style FROM DBPREFIXboards WHERE dir = ?`,
[]any{dir}, []any{&defaultStyle})
if err != nil || defaultStyle == "" {
gcutil.LogError(err).Caller().
Str("board", dir).
Msg("Unable to get default style attribute of board")
return boardCfg.DefaultStyle
}
return defaultStyle
},
"sectionBoards": func(sectionID int) []Board {
var boards []Board
for _, board := range AllBoards {
if board.SectionID == sectionID && !board.IsHidden(false) {
boards = append(boards, board)
}
}
return boards
},
})
}

View file

@ -1,6 +1,7 @@
package gcsql
import (
"database/sql"
"errors"
)
@ -86,3 +87,21 @@ func (p *Post) AttachFile(upload *Upload) error {
}
return tx.Commit()
}
// GetUploadFilenameAndBoard returns the filename (or an empty string) and
// the board of the given post ID
func GetUploadFilenameAndBoard(postID int) (string, string, error) {
const query = `SELECT filename, dir FROM DBPREFIXfiles
JOIN DBPREFIXposts ON post_id = DBPREFIXposts.id
JOIN DBPREFIXthreads ON thread_id = DBPREFIXthreads.id
JOIN DBPREFIXboards ON DBPREFIXboards.id = board_id
WHERE DBPREFIXposts.id = ?`
var filename, dir string
err := QueryRowSQL(query, []any{postID}, []any{&filename, &dir})
if errors.Is(err, sql.ErrNoRows) {
return "", "", nil
} else if err != nil {
return "", "", err
}
return filename, dir, nil
}

View file

@ -5,15 +5,12 @@ import (
"fmt"
"html"
"html/template"
"path"
"strconv"
"strings"
"time"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/gochan-org/gochan/pkg/posting/uploads"
)
var (
@ -147,112 +144,9 @@ var funcMap = template.FuncMap{
},
// Imageboard functions
"bannedForever": func(ban *gcsql.IPBan) bool {
return ban.IsActive && ban.Permanent && !ban.CanAppeal
},
"isBanned": func(ban *gcsql.IPBan, board string) bool {
return ban.IsActive && ban.BoardID != nil
},
"banMask": func(ban gcsql.IPBan) string {
if ban.ID < 1 {
if ban.RangeStart == ban.RangeEnd {
return ban.RangeStart
}
return ""
}
ipn, err := gcutil.GetIPRangeSubnet(ban.RangeStart, ban.RangeEnd)
if err != nil {
return "?"
}
return ipn.String()
},
"customFlagsEnabled": func(board string) bool {
return config.GetBoardConfig(board).CustomFlags != nil
},
"getBoardDirFromID": func(id int) string {
dir, _ := gcsql.GetBoardDir(id)
return dir
},
"intPtrToBoardDir": func(id *int, ifNil string, ifErr string) string {
if id == nil {
return ifNil
}
dir, err := gcsql.GetBoardDir(*id)
if err != nil {
return ifErr
}
return dir
},
"getStaffNameFromID": func(id int) string {
username, err := gcsql.GetStaffUsernameFromID(id)
if err != nil {
return "?"
}
return username
},
"getAppealBanIP": func(appealID int) string {
ban, err := gcsql.GetIPBanByID(appealID)
if err != nil || ban == nil {
return "?"
}
if ban.RangeStart == ban.RangeEnd {
return ban.RangeStart
}
ipn, err := gcutil.GetIPRangeSubnet(ban.RangeStart, ban.RangeEnd)
if err != nil {
return "?"
}
return ipn.String()
},
"getCatalogThumbnail": func(img string) string {
_, catalogThumb := uploads.GetThumbnailFilenames(img)
return catalogThumb
},
"getTopPostID": func(post *gcsql.Post) int {
id, _ := post.TopPostID()
return id
},
"getThreadThumbnail": func(img string) string {
thumb, _ := uploads.GetThumbnailFilenames(img)
return thumb
},
"getUploadType": func(name string) string {
return uploads.GetThumbnailExtension(path.Ext(name))
},
"numReplies": func(boardid, opID int) int {
num, err := gcsql.GetThreadReplyCountFromOP(opID)
if err != nil {
return 0
}
return num
},
"getBoardDir": func(id int) string {
dir, err := gcsql.GetBoardDir(id)
if err != nil {
return ""
}
return dir
},
"getBoardDefaultStyle": func(dir string) string {
boardCfg := config.GetBoardConfig(dir)
if !boardCfg.IsGlobal() {
// /<board>/board.json exists, overriding the default them and theme set in SQL
return boardCfg.DefaultStyle
}
var defaultStyle string
err := gcsql.QueryRowSQL(`SELECT default_style FROM DBPREFIXboards WHERE dir = ?`,
[]any{dir}, []any{&defaultStyle})
if err != nil || defaultStyle == "" {
gcutil.LogError(err).Caller().
Str("board", dir).
Msg("Unable to get default style attribute of board")
return boardCfg.DefaultStyle
}
return defaultStyle
},
"boardPagePath": func(board *gcsql.Board, page int) string {
return config.WebPath(board.Dir, strconv.Itoa(page)+".html")
},
"webPath": config.WebPath,
"webPathDir": func(part ...string) string {
dir := config.WebPath(part...)
@ -261,15 +155,6 @@ var funcMap = template.FuncMap{
}
return dir
},
"sectionBoards": func(sectionID int) []gcsql.Board {
var boards []gcsql.Board
for _, board := range gcsql.AllBoards {
if board.SectionID == sectionID && !board.IsHidden(false) {
boards = append(boards, board)
}
}
return boards
},
// Template convenience functions
"makeLoop": func(n int, offset int) []int {
loopArr := make([]int, n)
@ -285,3 +170,11 @@ var funcMap = template.FuncMap{
return config.GetVersion().String()
},
}
// AddTemplateFuncs adds the functions in the given FuncMap (map[string]any, with "any" expected to be a function)
// to the map of functions available to templates
func AddTemplateFuncs(funcs template.FuncMap) {
for key, tFunc := range funcs {
funcMap[key] = tFunc
}
}

View file

@ -8,7 +8,6 @@ import (
"sort"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcsql"
)
const (
@ -228,12 +227,7 @@ func ParseTemplate(name, tmplStr string) (*template.Template, error) {
// InitTemplates loads the given templates by name. If no parameters are given,
// all templates are (re)loaded
func InitTemplates(which ...string) error {
err := gcsql.ResetBoardSectionArrays()
if err != nil {
return err
}
func InitTemplates(which ...string) (err error) {
if which == nil {
// no templates specified
for t := range templateMap {

View file

@ -61,16 +61,7 @@ func checkImageFingerprintBan(img image.Image, _ string) (*gcsql.FileBan, error)
}
func GetPostImageFingerprint(postID int) (string, error) {
const query = `SELECT filename, dir
FROM DBPREFIXfiles
JOIN DBPREFIXposts ON post_id = DBPREFIXposts.id
JOIN DBPREFIXthreads ON thread_id = DBPREFIXthreads.id
JOIN DBPREFIXboards ON DBPREFIXboards.id = board_id
WHERE DBPREFIXposts.id = ?
LIMIT 1`
var filename, board string
err := gcsql.QueryRowSQL(query,
[]any{postID}, []any{&filename, &board})
filename, board, err := gcsql.GetUploadFilenameAndBoard(postID)
if err != nil {
return "", err
}
@ -82,7 +73,6 @@ func GetPostImageFingerprint(postID int) (string, error) {
return "", ErrVideoThumbFingerprint
}
filename, _ = GetThumbnailFilenames(filename)
subDir = "thumb"
}
filePath := path.Join(config.GetSystemCriticalConfig().DocumentRoot,
board, subDir, filename)

View file

@ -0,0 +1,36 @@
package uploads
import (
"path"
"text/template"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gctemplates"
"github.com/gochan-org/gochan/pkg/gcutil"
)
func init() {
gctemplates.AddTemplateFuncs(template.FuncMap{
"getCatalogThumbnail": func(img string) string {
_, catalogThumb := GetThumbnailFilenames(img)
return catalogThumb
},
"getThreadThumbnail": func(img string) string {
thumb, _ := GetThumbnailFilenames(img)
return thumb
},
"getUploadType": func(name string) string {
return GetThumbnailExtension(path.Ext(name))
},
"getThumbnailWebPath": func(postID int) string {
filename, board, err := gcsql.GetUploadFilenameAndBoard(postID)
if err != nil {
gcutil.LogError(err).Caller().Int("postID", postID).Send()
return ""
}
filename, _ = GetThumbnailFilenames(filename)
return config.WebPath(board, "thumb", filename)
},
})
}

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{with .board -}}
{{with $.op -}}
<title>{{$.op.TitleText}}</title>
<title>{{.TitleText}}</title>
{{- else}}
<title>/{{$.board.Dir}}/ - {{$.board.Title}}</title>
{{end}}

View file

@ -15,13 +15,13 @@
{{- if ne .post.Email ""}}</a>{{end}}</span>
{{- if ne .post.Tripcode ""}}<span class="tripcode">!{{.post.Tripcode}}</span>{{end -}}
{{- if ne .post.Country.Flag ""}}{{template "post_flag" .post.Country}}{{end}} {{formatTimestamp .post.Timestamp -}}
</label> <a href="{{.post.WebPath}}">No.</a> <a href="javascript:quote({{.post.ID}})" class="backlink-click">{{.post.ID}}</a>
</label> <a href="{{.WebPath}}">No.</a> <a href="javascript:quote({{.post.ID}})" class="backlink-click">{{.post.ID}}</a>
<span class="status-icons">
{{- if $.thread.Locked -}}<img src="{{webPath "/static/lock.png"}}" class="locked-icon" alt="Thread locked" title="Thread locked">{{end -}}
{{- if $.thread.Stickied -}}<img src="{{webPath "/static/sticky.png"}}" class="sticky-icon" alt="Sticky" title="Sticky">{{end -}}
{{- if $.thread.Locked}}<img src="{{webPath "/static/lock.png"}}" class="locked-icon" alt="Thread locked" title="Thread locked">{{end -}}
{{- if $.thread.Stickied}}<img src="{{webPath "/static/sticky.png"}}" class="sticky-icon" alt="Sticky" title="Sticky">{{end -}}
</span>
{{if $.is_board_page -}}
[<a href="{{$.post.ThreadPath}}">View</a>]
[<a href="{{.ThreadPath}}">View</a>]
{{end}}<br />
{{- end -}}
{{- if $.post.IsTopPost -}}
@ -37,7 +37,7 @@
<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="{{.post.ThumbnailPath}}" alt="{{.post.UploadPath}}" width="{{.post.ThumbnailWidth}}" height="{{.post.ThumbnailHeight}}" class="upload" /></a>
<a class="upload-container" href="{{.post.UploadPath}}"><img src="{{getThumbnailWebPath .post.ID}}" alt="{{.post.UploadPath}}" width="{{.post.ThumbnailWidth}}" height="{{.post.ThumbnailHeight}}" class="upload" /></a>
{{- end -}}
{{- if $.post.IsTopPost}}{{template "nameline" .}}{{end -}}
<div class="post-text">{{.post.Message}}</div>

View file

@ -31,7 +31,7 @@
{{- with .upload -}}
<tr><th class="postblock">Filename</th><td>{{.Filename}}</td></tr>
<tr><th class="postblock">Thumbnail</th><td>
<img src="{{webPath $.board.Dir "thumb" (.ThumbnailPath "reply")}}" alt="{{webPath $.board.Dir "src" .Filename}}" width="{{.ThumbnailWidth}}" height="{{.ThumbnailHeight}}" class="upload" />
<img src="{{getThumbnailWebPath $.post.ID}}" alt="{{webPath $.board.Dir "src" .Filename}}" width="{{.ThumbnailWidth}}" height="{{.ThumbnailHeight}}" class="upload" />
</td></tr>
{{- end -}}
<tr><th>Spoiler</th><td><input type="checkbox" name="spoiler" id="spoiler" {{with .upload}}{{if .IsSpoilered}}checked{{end}}{{end}}></td></tr>