mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-06 11:46:24 -07:00
Add fixthumbnails manage function
This commit is contained in:
parent
6c0926b4ec
commit
c573e26399
6 changed files with 132 additions and 66 deletions
|
@ -132,6 +132,9 @@ func GetBoardFromDir(dir string) (*Board, error) {
|
|||
func GetBoardIDFromDir(dir string) (id int, err error) {
|
||||
const query = `SELECT id FROM DBPREFIXboards WHERE dir = ?`
|
||||
err = QueryRowSQL(query, interfaceSlice(dir), interfaceSlice(&id))
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, ErrBoardDoesNotExist
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
|
|
|
@ -11,34 +11,35 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
Banpage *template.Template
|
||||
Captcha *template.Template
|
||||
Catalog *template.Template
|
||||
ErrorPage *template.Template
|
||||
FrontPage *template.Template
|
||||
BoardPage *template.Template
|
||||
JsConsts *template.Template
|
||||
ManageAppeals *template.Template
|
||||
ManageBans *template.Template
|
||||
ManageBoards *template.Template
|
||||
ManageThreadAttrs *template.Template
|
||||
ManageSections *template.Template
|
||||
ManageConfig *template.Template
|
||||
ManageDashboard *template.Template
|
||||
ManageFileBans *template.Template
|
||||
ManageNameBans *template.Template
|
||||
ManageIPSearch *template.Template
|
||||
ManageRecentPosts *template.Template
|
||||
ManageWordfilters *template.Template
|
||||
ManageLogin *template.Template
|
||||
ManageReports *template.Template
|
||||
ManageStaff *template.Template
|
||||
ManageViewLog *template.Template
|
||||
MoveThreadPage *template.Template
|
||||
PageHeader *template.Template
|
||||
PageFooter *template.Template
|
||||
PostEdit *template.Template
|
||||
ThreadPage *template.Template
|
||||
Banpage *template.Template
|
||||
Captcha *template.Template
|
||||
Catalog *template.Template
|
||||
ErrorPage *template.Template
|
||||
FrontPage *template.Template
|
||||
BoardPage *template.Template
|
||||
JsConsts *template.Template
|
||||
ManageAppeals *template.Template
|
||||
ManageBans *template.Template
|
||||
ManageBoards *template.Template
|
||||
ManageConfig *template.Template
|
||||
ManageDashboard *template.Template
|
||||
ManageFileBans *template.Template
|
||||
ManageFixThumbnails *template.Template
|
||||
ManageIPSearch *template.Template
|
||||
ManageLogin *template.Template
|
||||
ManageNameBans *template.Template
|
||||
ManageRecentPosts *template.Template
|
||||
ManageReports *template.Template
|
||||
ManageSections *template.Template
|
||||
ManageStaff *template.Template
|
||||
ManageThreadAttrs *template.Template
|
||||
ManageWordfilters *template.Template
|
||||
ManageViewLog *template.Template
|
||||
MoveThreadPage *template.Template
|
||||
PageHeader *template.Template
|
||||
PageFooter *template.Template
|
||||
PostEdit *template.Template
|
||||
ThreadPage *template.Template
|
||||
)
|
||||
|
||||
func LoadTemplate(files ...string) (*template.Template, error) {
|
||||
|
@ -236,6 +237,12 @@ func templateLoading(t string, buildAll bool) error {
|
|||
return templateError("manage_viewlog.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managefixthumbnails" {
|
||||
ManageFixThumbnails, err = LoadTemplate("manage_fixthumbnails.html")
|
||||
if err != nil {
|
||||
return templateError("manage_viewlog.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "movethreadpage" {
|
||||
MoveThreadPage, err = LoadTemplate("movethreadpage.html", "page_header.html", "topbar.html", "page_footer.html")
|
||||
if err != nil {
|
||||
|
|
|
@ -26,6 +26,17 @@ var (
|
|||
ErrInsufficientPermission = errors.New("insufficient account permission")
|
||||
)
|
||||
|
||||
type uploadInfo struct {
|
||||
PostID int
|
||||
OpID int
|
||||
Filename string
|
||||
Spoilered bool
|
||||
Width int
|
||||
Height int
|
||||
ThumbWidth int
|
||||
ThumbHeight int
|
||||
}
|
||||
|
||||
// manage actions that require admin-level permission go here
|
||||
|
||||
func registerAdminPages() {
|
||||
|
@ -377,6 +388,52 @@ func registerAdminPages() {
|
|||
output = pageBuffer.String()
|
||||
return
|
||||
}},
|
||||
Action{
|
||||
ID: "fixthumbnails",
|
||||
Title: "Regenerate thumbnails",
|
||||
Permissions: AdminPerms,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
board := request.FormValue("board")
|
||||
var uploads []uploadInfo
|
||||
if board != "" {
|
||||
const query = `SELECT p1.id as id, (SELECT id FROM DBPREFIXposts p2 WHERE p2.is_top_post AND p1.thread_id = p2.thread_id LIMIT 1) AS op,
|
||||
filename, is_spoilered, width, height, thumbnail_width, thumbnail_height
|
||||
FROM DBPREFIXposts p1
|
||||
JOIN DBPREFIXthreads t ON t.id = p1.thread_id
|
||||
JOIN DBPREFIXboards b ON b.id = t.board_id
|
||||
LEFT JOIN DBPREFIXfiles f ON f.post_id = p1.id
|
||||
WHERE dir = ? AND p1.is_deleted = FALSE AND filename IS NOT NULL AND filename != 'deleted'
|
||||
ORDER BY created_on DESC`
|
||||
rows, err := gcsql.QuerySQL(query, board)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var info uploadInfo
|
||||
if err = rows.Scan(
|
||||
&info.PostID, &info.OpID, &info.Filename, &info.Spoilered, &info.Width, &info.Height,
|
||||
&info.ThumbWidth, &info.ThumbHeight,
|
||||
); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
uploads = append(uploads, info)
|
||||
}
|
||||
}
|
||||
buffer := bytes.NewBufferString("")
|
||||
err = serverutil.MinifyTemplate(gctemplates.ManageFixThumbnails, map[string]any{
|
||||
"allBoards": gcsql.AllBoards,
|
||||
"board": board,
|
||||
"uploads": uploads,
|
||||
}, buffer, "text/html")
|
||||
if err != nil {
|
||||
errEv.Err(err).Str("template", "manage_fixthumbnails.html").Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
return buffer.String(), nil
|
||||
},
|
||||
},
|
||||
Action{
|
||||
ID: "rebuildfront",
|
||||
Title: "Rebuild front page",
|
||||
|
|
|
@ -13,7 +13,15 @@ import (
|
|||
"github.com/gochan-org/gochan/pkg/gcutil"
|
||||
)
|
||||
|
||||
func createImageThumbnail(imageObj image.Image, boardDir string, thumbType string) image.Image {
|
||||
type ThumbnailCategory int
|
||||
|
||||
const (
|
||||
ThumbnailOP ThumbnailCategory = iota
|
||||
ThumbnailReply
|
||||
ThumbnailCatalog
|
||||
)
|
||||
|
||||
func createImageThumbnail(imageObj image.Image, boardDir string, thumbType ThumbnailCategory) image.Image {
|
||||
thumbWidth, thumbHeight := getBoardThumbnailSize(boardDir, thumbType)
|
||||
|
||||
oldRect := imageObj.Bounds()
|
||||
|
@ -39,14 +47,14 @@ func createVideoThumbnail(video, thumb string, size int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func getBoardThumbnailSize(boardDir string, thumbType string) (int, int) {
|
||||
func getBoardThumbnailSize(boardDir string, thumbType ThumbnailCategory) (int, int) {
|
||||
boardCfg := config.GetBoardConfig(boardDir)
|
||||
switch thumbType {
|
||||
case "op":
|
||||
case ThumbnailOP:
|
||||
return boardCfg.ThumbWidth, boardCfg.ThumbHeight
|
||||
case "reply":
|
||||
case ThumbnailReply:
|
||||
return boardCfg.ThumbWidthReply, boardCfg.ThumbHeightReply
|
||||
case "catalog":
|
||||
case ThumbnailCatalog:
|
||||
return boardCfg.ThumbWidth, boardCfg.ThumbHeight
|
||||
}
|
||||
// todo: use reflect package to print location to error log, because this shouldn't happen
|
||||
|
@ -54,7 +62,7 @@ func getBoardThumbnailSize(boardDir string, thumbType string) (int, int) {
|
|||
}
|
||||
|
||||
// find out what out thumbnail's width and height should be, partially ripped from Kusaba X
|
||||
func getThumbnailSize(uploadWidth, uploadHeight int, boardDir string, thumbType string) (newWidth, newHeight int) {
|
||||
func getThumbnailSize(uploadWidth, uploadHeight int, boardDir string, thumbType ThumbnailCategory) (newWidth, newHeight int) {
|
||||
thumbWidth, thumbHeight := getBoardThumbnailSize(boardDir, thumbType)
|
||||
if uploadWidth < thumbWidth && uploadHeight < thumbHeight {
|
||||
newWidth = uploadWidth
|
||||
|
@ -74,7 +82,7 @@ func getThumbnailSize(uploadWidth, uploadHeight int, boardDir string, thumbType
|
|||
}
|
||||
return
|
||||
}
|
||||
func shouldCreateThumbnail(imgPath string, imgWidth int, imgHeight int, thumbWidth int, thumbHeight int) bool {
|
||||
func ShouldCreateThumbnail(imgPath string, imgWidth int, imgHeight int, thumbWidth int, thumbHeight int) bool {
|
||||
ext := strings.ToLower(path.Ext(imgPath))
|
||||
if ext == ".gif" {
|
||||
numFrames, err := numImageFrames(imgPath)
|
||||
|
|
|
@ -201,9 +201,9 @@ func AttachUploadFromRequest(request *http.Request, writer http.ResponseWriter,
|
|||
upload.FileSize = value
|
||||
}
|
||||
}
|
||||
thumbType := "reply"
|
||||
thumbType := ThumbnailReply
|
||||
if post.ThreadID == 0 {
|
||||
thumbType = "op"
|
||||
thumbType = ThumbnailOP
|
||||
}
|
||||
upload.ThumbnailWidth, upload.ThumbnailHeight = getThumbnailSize(
|
||||
upload.Width, upload.Height, postBoard.Dir, thumbType)
|
||||
|
@ -279,9 +279,9 @@ func AttachUploadFromRequest(request *http.Request, writer http.ResponseWriter,
|
|||
// Get image width and height, as well as thumbnail width and height
|
||||
upload.Width = img.Bounds().Max.X
|
||||
upload.Height = img.Bounds().Max.Y
|
||||
thumbType := "reply"
|
||||
thumbType := ThumbnailReply
|
||||
if post.ThreadID == 0 {
|
||||
thumbType = "op"
|
||||
thumbType = ThumbnailOP
|
||||
}
|
||||
upload.ThumbnailWidth, upload.ThumbnailHeight = getThumbnailSize(
|
||||
upload.Width, upload.Height, postBoard.Dir, thumbType)
|
||||
|
@ -308,15 +308,15 @@ func AttachUploadFromRequest(request *http.Request, writer http.ResponseWriter,
|
|||
}
|
||||
}
|
||||
|
||||
shouldThumb := shouldCreateThumbnail(filePath,
|
||||
shouldThumb := ShouldCreateThumbnail(filePath,
|
||||
upload.Width, upload.Height, upload.ThumbnailWidth, upload.ThumbnailHeight)
|
||||
if shouldThumb {
|
||||
var thumbnail image.Image
|
||||
var catalogThumbnail image.Image
|
||||
if post.ThreadID == 0 {
|
||||
// If this is a new thread, generate thumbnail and catalog thumbnail
|
||||
thumbnail = createImageThumbnail(img, postBoard.Dir, "op")
|
||||
catalogThumbnail = createImageThumbnail(img, postBoard.Dir, "catalog")
|
||||
thumbnail = createImageThumbnail(img, postBoard.Dir, ThumbnailOP)
|
||||
catalogThumbnail = createImageThumbnail(img, postBoard.Dir, ThumbnailCatalog)
|
||||
if err = imaging.Save(catalogThumbnail, catalogThumbPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("thumbPath", catalogThumbPath).
|
||||
|
@ -327,7 +327,7 @@ func AttachUploadFromRequest(request *http.Request, writer http.ResponseWriter,
|
|||
return nil, true
|
||||
}
|
||||
} else {
|
||||
thumbnail = createImageThumbnail(img, postBoard.Dir, "reply")
|
||||
thumbnail = createImageThumbnail(img, postBoard.Dir, ThumbnailReply)
|
||||
}
|
||||
if err = imaging.Save(thumbnail, thumbPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
|
@ -353,7 +353,7 @@ func AttachUploadFromRequest(request *http.Request, writer http.ResponseWriter,
|
|||
}
|
||||
if post.ThreadID == 0 {
|
||||
// Generate catalog thumbnail
|
||||
catalogThumbnail := createImageThumbnail(img, postBoard.Dir, "catalog")
|
||||
catalogThumbnail := createImageThumbnail(img, postBoard.Dir, ThumbnailCatalog)
|
||||
if err = imaging.Save(catalogThumbnail, catalogThumbPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("thumbPath", catalogThumbPath).
|
||||
|
@ -386,30 +386,9 @@ func stripImageMetadata(filePath string, boardConfig *config.BoardConfig) (err e
|
|||
return
|
||||
}
|
||||
|
||||
// func getVideoInfo(path string) (map[string]int, error) {
|
||||
// vidInfo := make(map[string]int)
|
||||
|
||||
// outputBytes, err := exec.Command("ffprobe", "-v quiet", "-show_format", "-show_streams", path).CombinedOutput()
|
||||
// if err == nil && outputBytes != nil {
|
||||
// outputStringArr := strings.Split(string(outputBytes), "\n")
|
||||
// for _, line := range outputStringArr {
|
||||
// lineArr := strings.Split(line, "=")
|
||||
// if len(lineArr) < 2 {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// if lineArr[0] == "width" || lineArr[0] == "height" || lineArr[0] == "size" {
|
||||
// value, _ := strconv.Atoi(lineArr[1])
|
||||
// vidInfo[lineArr[0]] = value
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return vidInfo, err
|
||||
// }
|
||||
|
||||
func getNewFilename() string {
|
||||
now := time.Now().Unix()
|
||||
rand.Seed(now)
|
||||
// rand.Seed(now)
|
||||
return strconv.Itoa(int(now)) + strconv.Itoa(rand.Intn(98)+1)
|
||||
}
|
||||
|
||||
|
|
12
templates/manage_fixthumbnails.html
Normal file
12
templates/manage_fixthumbnails.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<form action="{{webPath "manage/fixthumbnails"}}" method="GET">
|
||||
<select name="board">
|
||||
{{- range $b, $board := $.allBoards -}}
|
||||
<option value="{{$board.Dir}}" {{if eq $.board $board.Dir}}selected{{end}}>/{{$board.Dir}}/ - {{$board.Title}}</option>
|
||||
{{- end -}}
|
||||
</select>
|
||||
<input type="submit" value="Select board"/>
|
||||
</form>
|
||||
|
||||
{{range $_, $upload := $.uploads}}
|
||||
Post: <a href="{{webPath $.board "res" (intToString $upload.OpID)}}.html#{{$upload.PostID}}">/{{$.board}}/{{$upload.PostID}}</a>, Filename: {{$upload.Filename}}, Spoiler: {{$upload.Spoilered}}, Image size: {{$upload.Width}}x{{$upload.Height}}, Thumb size: {{$upload.ThumbWidth}}x{{$upload.ThumbHeight}}<br/>
|
||||
{{end}}
|
Loading…
Add table
Add a link
Reference in a new issue