stash/pkg/models/model_gallery.go

117 lines
2.8 KiB
Go

package models
import (
"archive/zip"
"bytes"
"database/sql"
"github.com/disintegration/imaging"
"github.com/stashapp/stash/pkg/api/urlbuilders"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/utils"
"image"
"image/jpeg"
"io/ioutil"
"path/filepath"
"sort"
"strings"
)
type Gallery struct {
ID int `db:"id" json:"id"`
Path string `db:"path" json:"path"`
Checksum string `db:"checksum" json:"checksum"`
SceneID sql.NullInt64 `db:"scene_id,omitempty" json:"scene_id"`
CreatedAt SQLiteTimestamp `db:"created_at" json:"created_at"`
UpdatedAt SQLiteTimestamp `db:"updated_at" json:"updated_at"`
}
func (g *Gallery) GetFiles(baseURL string) []*GalleryFilesType {
var galleryFiles []*GalleryFilesType
filteredFiles, readCloser, err := g.listZipContents()
if err != nil {
return nil
}
defer readCloser.Close()
builder := urlbuilders.NewGalleryURLBuilder(baseURL, g.ID)
for i, file := range filteredFiles {
galleryURL := builder.GetGalleryImageURL(i)
galleryFile := GalleryFilesType{
Index: i,
Name: &file.Name,
Path: &galleryURL,
}
galleryFiles = append(galleryFiles, &galleryFile)
}
return galleryFiles
}
func (g *Gallery) GetImage(index int) []byte {
data, _ := g.readZipFile(index)
return data
}
func (g *Gallery) GetThumbnail(index int) []byte {
data, _ := g.readZipFile(index)
srcImage, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return data
}
resizedImage := imaging.Resize(srcImage, 100, 0, imaging.NearestNeighbor)
buf := new(bytes.Buffer)
err = jpeg.Encode(buf, resizedImage, nil)
if err != nil {
return data
}
return buf.Bytes()
}
func (g *Gallery) readZipFile(index int) ([]byte, error) {
filteredFiles, readCloser, err := g.listZipContents()
if err != nil {
return nil, err
}
defer readCloser.Close()
zipFile := filteredFiles[index]
zipFileReadCloser, err := zipFile.Open()
if err != nil {
logger.Warn("failed to read file inside zip file")
return nil, err
}
defer zipFileReadCloser.Close()
return ioutil.ReadAll(zipFileReadCloser)
}
func (g *Gallery) listZipContents() ([]*zip.File, *zip.ReadCloser, error) {
readCloser, err := zip.OpenReader(g.Path)
if err != nil {
logger.Warn("failed to read zip file")
return nil, nil, err
}
filteredFiles := make([]*zip.File, 0)
for _, file := range readCloser.File {
if file.FileInfo().IsDir() {
continue
}
ext := filepath.Ext(file.Name)
if ext != ".jpg" && ext != ".jpeg" && ext != ".png" && ext != ".gif" {
continue
}
if strings.Contains(file.Name, "__MACOSX") {
continue
}
filteredFiles = append(filteredFiles, file)
}
sort.Slice(filteredFiles, func(i, j int) bool {
a := filteredFiles[i]
b := filteredFiles[j]
return utils.NaturalCompare(a.Name, b.Name)
})
return filteredFiles, readCloser, nil
}