mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 11:16:37 +08:00
126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type organizeTargetInput struct {
|
|
Root string
|
|
MediaType string
|
|
Category string
|
|
Title string
|
|
Source string
|
|
Ext string
|
|
Year int
|
|
Season int
|
|
Episode int
|
|
Series bool
|
|
}
|
|
|
|
type organizeTargetPath struct {
|
|
Dir string
|
|
Path string
|
|
EpisodeTag string
|
|
}
|
|
|
|
func (o *OrganizerService) buildOrganizeTargetPath(ctx context.Context, in organizeTargetInput) (organizeTargetPath, error) {
|
|
root := filepath.Clean(strings.TrimSpace(in.Root))
|
|
if root == "" || root == "." {
|
|
return organizeTargetPath{}, fmt.Errorf("organize target root required")
|
|
}
|
|
title := sanitizeFilename(strings.TrimSpace(in.Title))
|
|
if title == "" {
|
|
title = "Unknown"
|
|
}
|
|
ext := strings.TrimSpace(in.Ext)
|
|
if ext != "" && !strings.HasPrefix(ext, ".") {
|
|
ext = "." + ext
|
|
}
|
|
|
|
episodeTag := ""
|
|
if in.Series {
|
|
season := in.Season
|
|
if season < 0 {
|
|
season = 1
|
|
}
|
|
episode := in.Episode
|
|
if episode <= 0 {
|
|
episode = 1
|
|
}
|
|
episodeTag = fmt.Sprintf("S%02dE%02d", season, episode)
|
|
}
|
|
|
|
template := strings.TrimSpace(o.organizeNamingFormat(ctx, in.MediaType, in.Series))
|
|
var rel string
|
|
if template == "" {
|
|
rel = defaultOrganizeRelativePath(title, ext, in.Year, in.Season, in.Episode, in.Series)
|
|
} else {
|
|
rel = renderOrganizeNamingTemplate(template, organizeNamingData{
|
|
Title: title,
|
|
Year: in.Year,
|
|
Season: in.Season,
|
|
Episode: in.Episode,
|
|
Ext: strings.TrimPrefix(ext, "."),
|
|
FileExt: ext,
|
|
Category: sanitizeFilename(in.Category),
|
|
MediaType: normalizeOrganizeMediaType(in.MediaType),
|
|
EpisodeTag: episodeTag,
|
|
VideoFormat: extractOrganizeReleaseTag(in.Source),
|
|
Part: extractOrganizeReleaseTag(in.Source),
|
|
})
|
|
rel = cleanOrganizeRelativePath(rel)
|
|
if rel == "" {
|
|
rel = defaultOrganizeRelativePath(title, ext, in.Year, in.Season, in.Episode, in.Series)
|
|
}
|
|
if ext != "" && !strings.EqualFold(filepath.Ext(rel), ext) {
|
|
rel += ext
|
|
}
|
|
}
|
|
dst := filepath.Join(root, rel)
|
|
return organizeTargetPath{
|
|
Dir: filepath.Dir(dst),
|
|
Path: dst,
|
|
EpisodeTag: episodeTag,
|
|
}, nil
|
|
}
|
|
|
|
func (o *OrganizerService) organizeNamingFormat(ctx context.Context, mediaType string, series bool) string {
|
|
if o == nil || o.repo == nil || o.repo.Setting == nil {
|
|
return ""
|
|
}
|
|
key := "organize.movie_format"
|
|
if series {
|
|
if normalizeOrganizeMediaType(mediaType) == "anime" {
|
|
key = "organize.anime_format"
|
|
} else {
|
|
key = "organize.tv_format"
|
|
}
|
|
}
|
|
value, err := o.repo.Setting.Get(ctx, key)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(value)
|
|
}
|
|
|
|
func defaultOrganizeRelativePath(title, ext string, year, season, episode int, series bool) string {
|
|
if series {
|
|
if season < 0 {
|
|
season = 1
|
|
}
|
|
if episode <= 0 {
|
|
episode = 1
|
|
}
|
|
episodeTag := fmt.Sprintf("S%02dE%02d", season, episode)
|
|
return filepath.Join(title, fmt.Sprintf("Season %02d", season), fmt.Sprintf("%s - %s%s", title, episodeTag, ext))
|
|
}
|
|
folder := title
|
|
if year > 0 {
|
|
folder = fmt.Sprintf("%s (%d)", title, year)
|
|
}
|
|
return filepath.Join(folder, folder+ext)
|
|
}
|