mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-04 04:26:38 +08:00
fix(organize): 入库二级分类对齐MoviePilot结构 + 手动整理不再作为一级目录
- anime 顶层目录独立为「动漫」(动漫/{国漫,日番,儿童}),不再混入电视剧
- categoryPhysicalRootDir 把二级分类名映射到正确顶层:
动画电影/华语电影/外语电影→电影; 国漫/日番/儿童→动漫;
国产剧/日韩剧/欧美剧/纪录片/综艺/未分类→电视剧; 成人→成人
- 新增 staging 重定向:目标根落在「手动整理」等暂存目录时,上提到
父级媒体根,媒体真正归入分类目录(如 媒体/电影/华语电影/片名),
而非停留在手动整理下或与分类目录并列
- organizeLibraryRootForLayout 跳过 staging 名的库,避免回流暂存目录
- 同步更新陈旧测试期望(电视剧→动漫)+新增 staging 重定向测试
This commit is contained in:
@@ -127,7 +127,7 @@ func (o *OrganizerService) OrganizeDirectory(ctx context.Context, opts OrganizeO
|
||||
if _, ok := ParseCloudLibraryMount(requestedDest); ok {
|
||||
return nil, errors.New("organize destination must be a local writable media directory; enable cloud transfer in external storage when writing to cloud")
|
||||
}
|
||||
dest := resolveMappedDestinationPath(requestedDest)
|
||||
dest := redirectOrganizeStagingRoot(resolveMappedDestinationPath(requestedDest))
|
||||
if dest == "" || dest == "." {
|
||||
return nil, errors.New("destination path required")
|
||||
}
|
||||
@@ -537,6 +537,9 @@ func (o *OrganizerService) lookupOrganizeMetadata(ctx context.Context, src, sour
|
||||
} else if err != nil && o.log != nil {
|
||||
o.log.Debug("organize read local metadata before rename failed", zap.String("path", src), zap.Error(err))
|
||||
}
|
||||
if match := o.lookupOrganizeAdultMetadata(ctx, src, mediaType, title); match != nil {
|
||||
return match
|
||||
}
|
||||
if o == nil || o.scraper == nil || !o.scraper.AnyEnabled() {
|
||||
return nil
|
||||
}
|
||||
@@ -605,6 +608,49 @@ func (o *OrganizerService) lookupOrganizeMetadata(ctx context.Context, src, sour
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OrganizerService) lookupOrganizeAdultMetadata(ctx context.Context, src, mediaType, title string) *Match {
|
||||
if o == nil || o.scraper == nil || o.scraper.adult == nil || !o.scraper.adult.Enabled() {
|
||||
return nil
|
||||
}
|
||||
isAdult := normalizeOrganizeMediaType(mediaType) == "adult"
|
||||
candidates := []string{src, filepath.Base(src), title}
|
||||
outCodes := make([]string, 0, len(candidates))
|
||||
seen := map[string]struct{}{}
|
||||
for _, candidate := range candidates {
|
||||
code := normalizeAdultCode(candidate)
|
||||
if code == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[code]; ok {
|
||||
continue
|
||||
}
|
||||
seen[code] = struct{}{}
|
||||
outCodes = append(outCodes, code)
|
||||
}
|
||||
if !isAdult && len(outCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, code := range outCodes {
|
||||
match, err := o.scraper.adult.Search(ctx, code)
|
||||
if err != nil {
|
||||
if o.log != nil {
|
||||
o.log.Debug("organize adult metadata search failed", zap.String("source", src), zap.String("code", code), zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if match != nil && strings.TrimSpace(match.Title) != "" {
|
||||
if o.log != nil {
|
||||
o.log.Info("organize adult metadata matched before rename",
|
||||
zap.String("source", src),
|
||||
zap.String("code", code),
|
||||
zap.String("title", match.Title))
|
||||
}
|
||||
return match
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func organizeMetadataMatchTrusted(query string, sourceYear int, match *Match) bool {
|
||||
if match == nil || strings.TrimSpace(match.Title) == "" {
|
||||
return false
|
||||
@@ -834,6 +880,10 @@ func (o *OrganizerService) organizeLibraryRootForLayout(ctx context.Context, des
|
||||
if _, ok := ParseCloudLibraryMount(lib.Path); ok {
|
||||
continue
|
||||
}
|
||||
if isOrganizeStagingDir(lib.Path) {
|
||||
// "手动整理"等暂存库不作为入库目标,避免把媒体留在暂存目录里。
|
||||
continue
|
||||
}
|
||||
if destRoot != "" && destRoot != "." && !pathWithin(lib.Path, destRoot) && !pathWithin(destRoot, lib.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user