fix media organize and subscription workflows

This commit is contained in:
ShukeBta
2026-06-30 20:18:02 +08:00
parent b41f62d572
commit 941bb273b9
107 changed files with 5420 additions and 526 deletions
+36 -1
View File
@@ -9,7 +9,7 @@ import (
"github.com/ShukeBta/MediaStationGo/internal/model"
)
var episodicPathRE = regexp.MustCompile(`(?i)[\\/](?:电视剧|剧集|国产剧|欧美剧|日韩剧|日剧|韩剧|综艺|纪录片|儿童|动漫|番剧|国漫|日番|韩漫|美漫|欧美动漫|欧美动画|其他动漫|tv|series|shows?|season[\s._-]*\d|s\d{1,2}(?:[\s._-]|[\\/])|special[\s._-]*episodes?|specials?|sp|ovas?|oads?|extras?|bonus(?:es)?|omake|特别篇|特別篇|番外篇?|特典|外传|外傳|总集篇|總集篇)[\\/]`)
var episodicPathRE = regexp.MustCompile(`(?i)[\\/](?:电视剧|剧集|连续剧|短剧|国产剧|国剧|大陆剧|华语剧|国产电视剧|大陆电视剧|华语电视剧|欧美剧|欧美电视剧|美剧|英剧|日韩剧|日韩电视剧|日剧|韩剧|港剧|台剧|港台剧|泰剧|综艺|纪录片|儿童|动漫|番剧|国漫|日番|韩漫|美漫|欧美动漫|欧美动画|其他动漫|tv|series|shows?|season[\s._-]*\d|s\d{1,2}(?:[\s._-]|[\\/])|special[\s._-]*episodes?|specials?|sp|ovas?|oads?|extras?|bonus(?:es)?|omake|特别篇|特別篇|番外篇?|特典|外传|外傳|总集篇|總集篇)[\\/]`)
func mediaSeriesKey(media model.Media) string {
return compactSeriesKey(mediaSeriesRawKey(media))
@@ -21,6 +21,9 @@ func mediaSeriesRawKey(media model.Media) string {
if fromPath != "" {
return seriesFingerprint("library-path", mediaTargetLibraryID(media), fromPath)
}
if idKey := seriesExternalIDKeyFromPath(media.Path); idKey != "" {
return seriesFingerprint("library-path-id", mediaTargetLibraryID(media), idKey)
}
if media.TMDbID > 0 {
return fmt.Sprintf("tmdb:%d", media.TMDbID)
}
@@ -122,6 +125,9 @@ func seriesTitleFromMediaPath(path string) string {
return ""
}
dirIndex := len(parts) - 2
if last := parts[len(parts)-1]; !seriesPathPartLooksLikeFile(last) && !seriesSeasonDirRE.MatchString(filepath.Base(last)) {
dirIndex = len(parts) - 1
}
for dirIndex >= 0 && seriesSeasonDirRE.MatchString(filepath.Base(parts[dirIndex])) {
dirIndex--
}
@@ -135,6 +141,19 @@ func seriesTitleFromMediaPath(path string) string {
return title
}
func seriesPathPartLooksLikeFile(part string) bool {
ext := strings.ToLower(filepath.Ext(part))
if _, ok := videoExtensions[ext]; ok {
return true
}
switch ext {
case ".iso", ".nfo", ".srt", ".ass", ".ssa", ".vtt", ".sub", ".idx", ".jpg", ".jpeg", ".png", ".webp":
return true
default:
return false
}
}
func seriesDisplayTitle(media model.Media) string {
if fromPath := seriesTitleFromMediaPath(media.Path); fromPath != "" {
return fromPath
@@ -148,6 +167,22 @@ func seriesDisplayTitle(media model.Media) string {
return "未命名节目"
}
func seriesExternalIDKeyFromPath(path string) string {
_, hints := pathHintMetadata(path, true)
switch {
case hints.TMDbID > 0:
return fmt.Sprintf("tmdb:%d", hints.TMDbID)
case hints.BangumiID > 0:
return fmt.Sprintf("bgm:%d", hints.BangumiID)
case strings.TrimSpace(hints.DoubanID) != "":
return "douban:" + strings.TrimSpace(hints.DoubanID)
case strings.TrimSpace(hints.TheTVDBID) != "":
return "thetvdb:" + strings.TrimSpace(hints.TheTVDBID)
default:
return ""
}
}
func mediaTargetLibraryID(media model.Media) string {
if strings.TrimSpace(media.DisplayLibraryID) != "" {
return media.DisplayLibraryID