1
0
Эх сурвалжийг харах

修复 embyhelper

Signed-off-by: allan716 <[email protected]>
allan716 3 жил өмнө
parent
commit
d8a8dcbac3

+ 1 - 0
.gitignore

@@ -69,3 +69,4 @@ TestData/
 /internal/backend/settings.db
 /internal/pkg/settings/testfile.json
 /internal/types/backend/reply_check_proxy.json
+/internal/logic/emby_helper/Logs

+ 102 - 43
internal/logic/emby_helper/embyhelper.go

@@ -13,6 +13,7 @@ import (
 	"golang.org/x/net/context"
 	"path"
 	"path/filepath"
+	"sort"
 	"strings"
 	"sync"
 	"time"
@@ -38,17 +39,13 @@ func (em *EmbyHelper) GetRecentlyAddVideoList() ([]emby.EmbyMixInfo, map[string]
 
 	// 获取最近的影片列表
 	items, err := em.embyApi.GetRecentlyItems()
-
+	if err != nil {
+		return nil, nil, err
+	}
 	// 获取电影和连续剧的文件夹名称
-	movieFolderName := filepath.Base(movieRootDir)
-	seriesFolderName := filepath.Base(seriesRootDir)
-
 	var EpisodeIdList = make([]string, 0)
 	var MovieIdList = make([]string, 0)
 
-	if err != nil {
-		return nil, nil, err
-	}
 	log_helper.GetLogger().Debugln("-----------------")
 	log_helper.GetLogger().Debugln("GetRecentlyAddVideoList - GetRecentlyItems Count", len(items.Items))
 
@@ -68,11 +65,11 @@ func (em *EmbyHelper) GetRecentlyAddVideoList() ([]emby.EmbyMixInfo, map[string]
 	}
 
 	// 过滤出有效的电影、连续剧的资源出来
-	filterMovieList, err := em.filterEmbyVideoList(movieFolderName, MovieIdList, true)
+	filterMovieList, err := em.filterEmbyVideoList(MovieIdList, true)
 	if err != nil {
 		return nil, nil, err
 	}
-	filterSeriesList, err := em.filterEmbyVideoList(seriesFolderName, EpisodeIdList, false)
+	filterSeriesList, err := em.filterEmbyVideoList(EpisodeIdList, false)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -109,14 +106,6 @@ func (em *EmbyHelper) GetRecentlyAddVideoList() ([]emby.EmbyMixInfo, map[string]
 	for index, info := range filterSeriesList {
 		log_helper.GetLogger().Debugln(index, info.VideoFileName)
 	}
-
-	// 拼接绝对路径
-	for i, info := range noSubMovieList {
-		noSubMovieList[i].VideoFileFullPath = filepath.Join(movieRootDir, info.VideoFileRelativePath)
-	}
-	for i, info := range noSubSeriesList {
-		noSubSeriesList[i].VideoFileFullPath = filepath.Join(seriesRootDir, info.VideoFileRelativePath)
-	}
 	// 需要将连续剧零散的每一集,进行合并到一个连续剧下面,也就是这个连续剧有那些需要更新的
 	var seriesMap = make(map[string][]emby.EmbyMixInfo)
 	for _, info := range noSubSeriesList {
@@ -143,7 +132,62 @@ func (em *EmbyHelper) RefreshEmbySubList() (bool, error) {
 	return true, nil
 }
 
-func (em *EmbyHelper) filterEmbyVideoList(videoFolderName string, videoIdList []string, isMovieOrSeries bool) ([]emby.EmbyMixInfo, error) {
+// findMappingPath 从 Emby 内置路径匹配到物理路径
+// X:\电影    - /mnt/share1/电影
+// X:\连续剧  - /mnt/share1/连续剧
+func (em *EmbyHelper) findMappingPath(videoEmbyFullPath string, isMovieOrSeries bool) (bool, string) {
+	// 这里进行路径匹配的时候需要考虑嵌套路径的问题
+	// 比如,映射了 /电影  以及 /电影/AA ,那么如果有一部电影 /电影/AA/xx/xx.mkv 那么,应该匹配的是最长的路径 /电影/AA
+	matchedEmbyPaths := make([]string, 0)
+	if isMovieOrSeries == true {
+		// 电影的情况
+		for _, embyPath := range em.EmbyConfig.MoviePathsMapping {
+			if strings.Contains(videoEmbyFullPath, embyPath) == true {
+				matchedEmbyPaths = append(matchedEmbyPaths, embyPath)
+			}
+		}
+	} else {
+		// 连续剧的情况
+		for _, embyPath := range em.EmbyConfig.MoviePathsMapping {
+			if strings.Contains(videoEmbyFullPath, embyPath) == true {
+				matchedEmbyPaths = append(matchedEmbyPaths, embyPath)
+			}
+		}
+	}
+	if len(matchedEmbyPaths) < 1 {
+		return false, ""
+	}
+	// 排序得到匹配上的路径,最长的那个
+	pathSlices := sortStringSliceByLength(matchedEmbyPaths)
+	// 然后还需要从这个最长的路径,从 map 中找到对应的物理路径
+	nowPhPath := ""
+	if isMovieOrSeries == true {
+		// 电影的情况
+		for physicalPath, embyPath := range em.EmbyConfig.MoviePathsMapping {
+			if embyPath == pathSlices[0].Path {
+				nowPhPath = physicalPath
+				break
+			}
+		}
+	} else {
+		// 连续剧的情况
+		for physicalPath, embyPath := range em.EmbyConfig.MoviePathsMapping {
+			if embyPath == pathSlices[0].Path {
+				nowPhPath = physicalPath
+				break
+			}
+		}
+	}
+	// 如果匹配不上
+	if nowPhPath == "" {
+		return false, ""
+	}
+
+	outPhPath := strings.ReplaceAll(videoEmbyFullPath, pathSlices[0].Path, nowPhPath)
+	return true, outPhPath
+}
+
+func (em *EmbyHelper) filterEmbyVideoList(videoIdList []string, isMovieOrSeries bool) ([]emby.EmbyMixInfo, error) {
 	var filterVideoEmbyInfo = make([]emby.EmbyMixInfo, 0)
 
 	queryFunc := func(m string) (*emby.EmbyMixInfo, error) {
@@ -158,43 +202,38 @@ func (em *EmbyHelper) filterEmbyVideoList(videoFolderName string, videoIdList []
 		mixInfo := emby.EmbyMixInfo{Ancestors: ancs, VideoInfo: info}
 		if isMovieOrSeries == true {
 			// 电影
-			// 过滤掉不符合要求的
-			if len(mixInfo.Ancestors) < 2 {
-				return nil, err
-			}
-
-			// 过滤掉不符合要求的
-			ancestorsCount := len(mixInfo.Ancestors)
-			usefulAncestorIndex := ancestorsCount - 2
-			if mixInfo.Ancestors[usefulAncestorIndex].Name != videoFolderName || mixInfo.Ancestors[usefulAncestorIndex].Type != "Folder" {
+			// 过滤掉不符合要求的,拼接绝对路径
+			isFit, physicalPath := em.findMappingPath(info.Path, isMovieOrSeries)
+			if isFit == false {
 				return nil, err
 			}
-
+			mixInfo.VideoFileFullPath = physicalPath
 			// 这个电影的文件夹
 			mixInfo.VideoFolderName = filepath.Base(filepath.Dir(mixInfo.VideoInfo.Path))
 			mixInfo.VideoFileName = filepath.Base(mixInfo.VideoInfo.Path)
-			// 这里需要注意,仅仅这样是不能够解决嵌套文件夹问题的。
-			//mixInfo.VideoFileRelativePath = filepath.Join(mixInfo.VideoFolderName, mixInfo.VideoFileName)
-			// 需要从上面得到的 Ancestors 对应的“电影”根目录的 index 处,拿到 Path,然后用 info 这个实例的 Path 剪掉前面那个 Path,就是相对路径了
-			mixInfo.VideoFileRelativePath = strings.ReplaceAll(info.Path, mixInfo.Ancestors[usefulAncestorIndex].Path, "")
 		} else {
 			// 连续剧
-			// 过滤掉不符合要求的
-			if len(mixInfo.Ancestors) < 4 {
+			// 过滤掉不符合要求的,拼接绝对路径
+			isFit, physicalPath := em.findMappingPath(info.Path, isMovieOrSeries)
+			if isFit == false {
 				return nil, err
 			}
-			// 过滤掉不符合要求的
-			if mixInfo.Ancestors[0].Type != "Season" ||
-				mixInfo.Ancestors[1].Type != "Series" ||
-				mixInfo.Ancestors[2].Type != "Folder" ||
-				mixInfo.Ancestors[2].Name != videoFolderName {
+			mixInfo.VideoFileFullPath = physicalPath
+			// 这个剧集的文件夹
+			ancestorIndex := -1
+			// 找到连续剧文件夹这一层
+			for i, ancestor := range mixInfo.Ancestors {
+				if ancestor.Type == "Series" {
+					ancestorIndex = i
+					break
+				}
+			}
+			if ancestorIndex == -1 {
+				// 说明没有找到连续剧文件夹的名称,那么就应该跳过
 				return nil, err
 			}
-			// 这个剧集的文件夹
-			mixInfo.VideoFolderName = filepath.Base(mixInfo.Ancestors[1].Path)
+			mixInfo.VideoFolderName = filepath.Base(mixInfo.Ancestors[ancestorIndex].Path)
 			mixInfo.VideoFileName = filepath.Base(mixInfo.VideoInfo.Path)
-			seasonName := filepath.Base(mixInfo.Ancestors[0].Path)
-			mixInfo.VideoFileRelativePath = filepath.Join(mixInfo.VideoFolderName, seasonName, mixInfo.VideoFileName)
 		}
 
 		return &mixInfo, nil
@@ -466,6 +505,26 @@ type OutData struct {
 	Err  error
 }
 
+type PathSlice struct {
+	Path string
+}
+type PathSlices []PathSlice
+
+func (a PathSlices) Len() int           { return len(a) }
+func (a PathSlices) Less(i, j int) bool { return len(a[i].Path) < len(a[j].Path) }
+func (a PathSlices) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+func sortStringSliceByLength(m []string) PathSlices {
+	p := make(PathSlices, len(m))
+	i := 0
+	for _, v := range m {
+		p[i] = PathSlice{v}
+		i++
+	}
+	sort.Sort(sort.Reverse(p))
+	return p
+}
+
 const (
 	videoTypeEpisode = "Episode"
 	videoTypeMovie   = "Movie"

+ 45 - 3
internal/logic/emby_helper/embyhelper_test.go

@@ -1,14 +1,23 @@
 package emby_helper
 
 import (
+	"reflect"
 	"testing"
 )
 
 // TODO 暂不方便在其他环境进行单元测试
 func TestEmbyHelper_GetRecentlyAddVideoList(t *testing.T) {
-	//config := config.GetConfig()
-	//em := NewEmbyHelper(config.EmbyConfig)
-	//movieList, seriesList, err := em.GetRecentlyAddVideoList(config.MovieFolder, config.SeriesFolder)
+
+	//embyConfig := settings.NewEmbySettings()
+	//embyConfig.Enable = true
+	//embyConfig.AddressUrl = "http://123:8096"
+	//embyConfig.APIKey = "123"
+	//embyConfig.SkipWatched = true
+	//embyConfig.MoviePathsMapping["X:\\电影"] = "/mnt/share1/电影"
+	//embyConfig.MoviePathsMapping["X:\\连续剧"] = "/mnt/share1/连续剧"
+	//
+	//em := NewEmbyHelper(*embyConfig)
+	//movieList, seriesList, err := em.GetRecentlyAddVideoList()
 	//if err != nil {
 	//	t.Fatal(err)
 	//}
@@ -44,3 +53,36 @@ func TestEmbyHelper_GetInternalEngSubAndExSub(t *testing.T) {
 	//
 	//println(internalEngSub[0].FileName, exCh_EngSub[0].FileName)
 }
+
+func Test_sortStringSliceByLength(t *testing.T) {
+	type args struct {
+		m []string
+	}
+	tests := []struct {
+		name string
+		args args
+		want PathSlices
+	}{
+		{
+			name: "00",
+			args: args{
+				[]string{"/aa/bb/cc", "/aa", "/aa/bb"},
+			},
+			want: []PathSlice{{
+				Path: "/aa/bb/cc",
+			}, {
+				Path: "/aa/bb",
+			}, {
+				Path: "/aa",
+			},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := sortStringSliceByLength(tt.args.m); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("sortStringSliceByLength() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}

+ 5 - 6
internal/types/emby/type.go

@@ -151,12 +151,11 @@ func (info EmbyVideoInfoByUserId) GetDefaultSubIndex() int {
 }
 
 type EmbyMixInfo struct {
-	VideoFolderName       string // 电影就是电影的文件夹名称,连续剧就是对应的剧集的 root 文件夹
-	VideoFileName         string // 视频文件名
-	VideoFileRelativePath string // 视频文件的相对路径(注意,这里还是需要补齐 x:/电影 这样的 root 路径的,仅仅算相对路径)
-	VideoFileFullPath     string
-	Ancestors             []EmbyItemsAncestors
-	VideoInfo             EmbyVideoInfo
+	VideoFolderName   string // 电影就是电影的文件夹名称,连续剧就是对应的剧集的 root 文件夹
+	VideoFileName     string // 视频文件名
+	VideoFileFullPath string
+	Ancestors         []EmbyItemsAncestors
+	VideoInfo         EmbyVideoInfo
 }
 
 type Time time.Time