mirror of https://github.com/stashapp/stash.git
117 lines
2.8 KiB
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
|
|
}
|