This commit is contained in:
icefox 2025-12-26 13:04:49 -03:00
parent 4af3988df9
commit b4bbe2a7c6
No known key found for this signature in database
2 changed files with 40 additions and 25 deletions

52
main.go
View file

@ -10,12 +10,28 @@ import (
"math/rand" "math/rand"
"net/http" "net/http"
"net/url" "net/url"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
var imageExtensions = map[string]bool{
".png": true,
".jpg": true,
".jpeg": true,
".gif": true,
".webp": true,
".bmp": true,
".avif": true,
}
func isImageFile(path string) bool {
ext := strings.ToLower(filepath.Ext(path))
return imageExtensions[ext]
}
//go:embed templates/* //go:embed templates/*
var templatesFS embed.FS var templatesFS embed.FS
@ -23,9 +39,8 @@ var templatesFS embed.FS
var assetsFS embed.FS var assetsFS embed.FS
type CoverData struct { type CoverData struct {
Comic int Comic int
Path string Path string
Prefix string
} }
var ( var (
@ -84,7 +99,7 @@ func handleRandom(w http.ResponseWriter, r *http.Request) {
// If accessing /random without chapter, shuffle and redirect to /random/0 // If accessing /random without chapter, shuffle and redirect to /random/0
if path == "" { if path == "" {
query := ` query := `
select page.id_comic, comic.directory || '/' || page.filename path, page.prefix select page.id_comic, comic.directory || '/' || page.filename path
from page from page
join comic on comic.id_comic = page.id_comic join comic on comic.id_comic = page.id_comic
where page.number = 0 where page.number = 0
@ -99,7 +114,7 @@ func handleRandom(w http.ResponseWriter, r *http.Request) {
randomCovers = nil randomCovers = nil
for rows.Next() { for rows.Next() {
var c CoverData var c CoverData
if err := rows.Scan(&c.Comic, &c.Path, &c.Prefix); err != nil { if err := rows.Scan(&c.Comic, &c.Path); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@ -140,7 +155,7 @@ func handleRandom(w http.ResponseWriter, r *http.Request) {
all := make([]Cover, 0, limit*2) all := make([]Cover, 0, limit*2)
for _, c := range randomCovers[start:end] { for _, c := range randomCovers[start:end] {
var coverUrl string var coverUrl string
if c.Prefix == "imaginary" { if isImageFile(c.Path) {
coverUrl = fmt.Sprintf("%s/smartcrop?width=300&height=370&file=%s", imaginaryURL, url.QueryEscape(c.Path)) coverUrl = fmt.Sprintf("%s/smartcrop?width=300&height=370&file=%s", imaginaryURL, url.QueryEscape(c.Path))
} else { } else {
coverUrl = "/static/" + c.Path coverUrl = "/static/" + c.Path
@ -180,7 +195,7 @@ func handleGallery(w http.ResponseWriter, r *http.Request) {
} }
query := ` query := `
select comic.title, comic.directory || '/' || page.filename, page.prefix select comic.title, comic.directory || '/' || page.filename
from page from page
join comic on page.id_comic = comic.id_comic join comic on page.id_comic = comic.id_comic
where comic.id_comic = ? where comic.id_comic = ?
@ -193,20 +208,15 @@ func handleGallery(w http.ResponseWriter, r *http.Request) {
} }
defer rows.Close() defer rows.Close()
type Page struct {
Path string
Prefix string
}
var title string var title string
var pages []Page var pages []string
for rows.Next() { for rows.Next() {
var path, prefix string var path string
if err := rows.Scan(&title, &path, &prefix); err != nil { if err := rows.Scan(&title, &path); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
pages = append(pages, Page{Path: path, Prefix: prefix}) pages = append(pages, path)
} }
if len(pages) == 0 { if len(pages) == 0 {
@ -216,7 +226,7 @@ func handleGallery(w http.ResponseWriter, r *http.Request) {
data := struct { data := struct {
Title string Title string
Pages []Page Pages []string
ImaginaryURL string ImaginaryURL string
}{title, pages, imaginaryURL} }{title, pages, imaginaryURL}
@ -239,7 +249,7 @@ func handleIndex(w http.ResponseWriter, r *http.Request) {
offset := chapter * limit offset := chapter * limit
query := ` query := `
select page.id_comic, comic.directory || '/' || page.filename path, page.prefix select page.id_comic, comic.directory || '/' || page.filename path
from page from page
join comic on comic.id_comic = page.id_comic join comic on comic.id_comic = page.id_comic
where page.number = 0 where page.number = 0
@ -262,13 +272,13 @@ func handleIndex(w http.ResponseWriter, r *http.Request) {
all := make([]Cover, 0, limit*2) all := make([]Cover, 0, limit*2)
for rows.Next() { for rows.Next() {
var comic int var comic int
var path, prefix string var path string
if err := rows.Scan(&comic, &path, &prefix); err != nil { if err := rows.Scan(&comic, &path); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
var coverUrl string var coverUrl string
if prefix == "imaginary" { if isImageFile(path) {
coverUrl = fmt.Sprintf("%s/smartcrop?width=300&height=370&file=%s", imaginaryURL, url.QueryEscape(path)) coverUrl = fmt.Sprintf("%s/smartcrop?width=300&height=370&file=%s", imaginaryURL, url.QueryEscape(path))
} else { } else {
coverUrl = "/static/" + path coverUrl = "/static/" + path

View file

@ -31,15 +31,20 @@
width: 1080, width: 1080,
height: 1920, height: 1920,
imaginary: '{{.ImaginaryURL}}', imaginary: '{{.ImaginaryURL}}',
pages: [{{range $i, $p := .Pages}}{{if $i}},{{end}}{path: '{{$p.Path}}', prefix: '{{$p.Prefix}}'}{{end}}], pages: [{{range $i, $p := .Pages}}{{if $i}},{{end}}'{{$p}}'{{end}}],
urls: [], urls: [],
prefetched: new Set(), prefetched: new Set(),
imageExts: ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.avif'],
isImage(path) {
const ext = path.substring(path.lastIndexOf('.')).toLowerCase();
return this.imageExts.includes(ext);
},
buildUrls() { buildUrls() {
this.urls = this.pages.map(p => { this.urls = this.pages.map(p => {
if (p.prefix === 'imaginary') { if (this.isImage(p)) {
return this.imaginary + '/fit?width=' + this.width + '&height=' + this.height + '&file=' + encodeURIComponent(p.path); return this.imaginary + '/fit?width=' + this.width + '&height=' + this.height + '&file=' + encodeURIComponent(p);
} }
return '/static/' + p.path; return '/static/' + p;
}); });
this.prefetched.clear(); this.prefetched.clear();
}, },