258 lines
6 KiB
Go
258 lines
6 KiB
Go
package gallery
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Gallery struct {
|
|
images []string
|
|
uuid string
|
|
title string
|
|
jpTitle string
|
|
tags []Tag
|
|
source Source
|
|
CTime time.Time
|
|
artists []string
|
|
groups []string
|
|
parodies []string
|
|
}
|
|
|
|
func (g *Gallery) Name() string { return g.title }
|
|
func (g *Gallery) JpName() string { return g.jpTitle }
|
|
func (g *Gallery) Uuid() string { return g.uuid }
|
|
func (g *Gallery) Images() []string { return g.images }
|
|
func (g *Gallery) Tags() []Tag { return g.tags }
|
|
func (g *Gallery) Source() Source { return g.source }
|
|
func (g *Gallery) Artists() []string { return g.artists }
|
|
func (g *Gallery) Groups() []string { return g.groups }
|
|
func (g *Gallery) Parodies() []string { return g.parodies }
|
|
|
|
func newGallery(
|
|
images []string, uuid string, title string, jpTitle string, tags []Tag,
|
|
source Source, CTime time.Time, artists []string, groups []string, parodies []string,
|
|
) Gallery {
|
|
return Gallery{
|
|
images: images,
|
|
uuid: uuid,
|
|
title: title,
|
|
jpTitle: jpTitle,
|
|
tags: tags,
|
|
source: source,
|
|
CTime: CTime,
|
|
artists: artists,
|
|
groups: groups,
|
|
parodies: parodies,
|
|
}
|
|
}
|
|
|
|
type Source string
|
|
|
|
const (
|
|
Nhentai Source = "nhentai"
|
|
Exhentai = "exhentai"
|
|
Hitomi = "hitomi"
|
|
)
|
|
|
|
type Gender string
|
|
|
|
const (
|
|
Male Gender = "male"
|
|
Female Gender = "female"
|
|
Any Gender = "any"
|
|
)
|
|
|
|
type Tag struct {
|
|
Name string
|
|
Sex Gender
|
|
}
|
|
|
|
func newTag(name string, sex Gender) Tag {
|
|
return Tag{
|
|
Name: strings.ToLower(name),
|
|
Sex: sex,
|
|
}
|
|
}
|
|
|
|
func genUuid(title string) string {
|
|
return fmt.Sprintf("%x", md5.Sum([]byte(title)))
|
|
}
|
|
|
|
func filterImages(root string, galleryDir []fs.DirEntry) []string {
|
|
var paths []string
|
|
for _, file := range galleryDir {
|
|
if file.IsDir() {
|
|
continue
|
|
}
|
|
name := file.Name()
|
|
|
|
// fixme
|
|
isJpeg := strings.HasSuffix(name, ".jpeg") || strings.HasSuffix(name, ".jpg")
|
|
isPng := strings.HasSuffix(name, ".png")
|
|
isWebp := strings.HasSuffix(name, ".webp")
|
|
isJson := strings.HasSuffix(name, ".json")
|
|
|
|
if isJson {
|
|
continue
|
|
}
|
|
if isJpeg || isPng || isWebp {
|
|
paths = append(paths, filepath.Join(root, name))
|
|
}
|
|
}
|
|
return paths
|
|
}
|
|
|
|
func NewNhentaiGallery(infoBinary []byte, root string, galleryDir []fs.DirEntry) (Gallery, error) {
|
|
var data struct {
|
|
Title string
|
|
Title_en string `json:"title_en"`
|
|
Title_ja string
|
|
// Gallery_id string `json:"gallery_id"` // troublesome
|
|
Media_id int
|
|
Date int64
|
|
Scanlator string
|
|
Artist, Group, Parody, Characters, Tags []string
|
|
Type, Lang, Language, Category, Subcategory string
|
|
Count int
|
|
}
|
|
err := json.Unmarshal(infoBinary, &data)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
var tags []Tag
|
|
for _, t := range data.Tags {
|
|
tags = append(tags, newTag(t, Any))
|
|
}
|
|
images := filterImages(root, galleryDir)
|
|
d, err := os.Stat(root)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
g := newGallery(
|
|
images, genUuid(data.Title), data.Title, data.Title_ja, tags,
|
|
Nhentai, d.ModTime(), data.Artist, data.Group, data.Parody,
|
|
)
|
|
return g, nil
|
|
}
|
|
|
|
func NewExhentaiGallery(infoBinary []byte, root string, galleryDir []fs.DirEntry) (Gallery, error) {
|
|
var data struct {
|
|
Gid int
|
|
Token string
|
|
Thumb string
|
|
Title string
|
|
Title_jpn string
|
|
Eh_category string
|
|
Uploader string
|
|
Date string
|
|
Parent string
|
|
Language string
|
|
Filecount string
|
|
Favorites string
|
|
Rating string
|
|
Torrentcount string
|
|
Lang string
|
|
Category string
|
|
Subcategory string
|
|
Expunged bool
|
|
Filesize int
|
|
Tags []string
|
|
}
|
|
err := json.Unmarshal(infoBinary, &data)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
var (
|
|
tags []Tag
|
|
artists []string
|
|
groups []string
|
|
parodies []string
|
|
)
|
|
for _, t := range data.Tags {
|
|
switch {
|
|
case strings.HasPrefix(t, "female:"):
|
|
tags = append(tags, newTag(t[7:], Female))
|
|
case strings.HasPrefix(t, "male:"):
|
|
tags = append(tags, newTag(t[5:], Male))
|
|
case strings.HasPrefix(t, "artist:"):
|
|
artists = append(artists, t[7:])
|
|
case strings.HasPrefix(t, "group:"):
|
|
groups = append(groups, t[6:])
|
|
case strings.HasPrefix(t, "parody:"):
|
|
parodies = append(parodies, t[7:])
|
|
}
|
|
}
|
|
d, err := os.Stat(root)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
g := newGallery(
|
|
filterImages(root, galleryDir), genUuid(data.Title), data.Title, data.Title_jpn,
|
|
tags, Exhentai, d.ModTime(), artists, groups, parodies,
|
|
)
|
|
return g, nil
|
|
}
|
|
|
|
func NewHitomiGallery(infoBinary []byte, root string, galleryDir []fs.DirEntry) (Gallery, error) {
|
|
var data struct {
|
|
Gallery_id int
|
|
Title string
|
|
Title_jpn string
|
|
Type string
|
|
Language string
|
|
Lang string
|
|
Date string
|
|
Tags []string
|
|
Artist []string
|
|
Group []string
|
|
Parody []string
|
|
Characters []string
|
|
Count int
|
|
Category string
|
|
Subcategory string
|
|
}
|
|
err := json.Unmarshal(infoBinary, &data)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
var tags []Tag
|
|
for _, t := range data.Tags {
|
|
sex := Any
|
|
name := t
|
|
if strings.HasSuffix(t, "♀") {
|
|
sex = Female
|
|
name = t[:len(t)-3]
|
|
} else if strings.HasSuffix(t, "♂") {
|
|
sex = Male
|
|
name = t[:len(t)-3]
|
|
}
|
|
tags = append(tags, newTag(name, sex))
|
|
}
|
|
d, err := os.Stat(root)
|
|
if err != nil {
|
|
return Gallery{}, err
|
|
}
|
|
g := newGallery(
|
|
filterImages(root, galleryDir), genUuid(data.Title), data.Title, data.Title_jpn,
|
|
tags, Hitomi, d.ModTime(), data.Artist, data.Group, data.Parody,
|
|
)
|
|
return g, nil
|
|
}
|
|
|
|
func NewGallery(source Source, infoBinary []byte, root string, galleryDir []fs.DirEntry) (Gallery, error) {
|
|
switch source {
|
|
case Nhentai:
|
|
return NewNhentaiGallery(infoBinary, root, galleryDir)
|
|
case Exhentai:
|
|
return NewExhentaiGallery(infoBinary, root, galleryDir)
|
|
case Hitomi:
|
|
return NewHitomiGallery(infoBinary, root, galleryDir)
|
|
}
|
|
panic(source)
|
|
}
|