浏览代码

保存进度,需要把视频列表的功能移到 VideoScanAndRefreshHelper 单独实现

Signed-off-by: allan716 <[email protected]>
allan716 3 年之前
父节点
当前提交
dc6358db83

+ 1 - 0
internal/backend/backend.go

@@ -26,6 +26,7 @@ func StartBackEnd(fileDownloader *file_downloader.FileDownloader, httpPort int,
 	defer func() {
 		v1Router.Close()
 	}()
+
 	engine.GET("/", func(c *gin.Context) {
 		c.Header("content-type", "text/html;charset=utf-8")
 		c.String(http.StatusOK, string(dist.SpaIndexHtml))

+ 27 - 8
internal/backend/controllers/base/backend_static_file_system.go

@@ -12,18 +12,25 @@ import (
 )
 
 type StaticFileSystemBackEnd struct {
-	logger  *logrus.Logger
-	running bool
-	srv     *http.Server
-	locker  sync.Mutex
+	logger     *logrus.Logger
+	running    bool
+	srv        *http.Server
+	locker     sync.Mutex
+	pathUrlMap map[string]string
 }
 
 func NewStaticFileSystemBackEnd(logger *logrus.Logger) *StaticFileSystemBackEnd {
 	return &StaticFileSystemBackEnd{
-		logger: logger,
+		logger:     logger,
+		pathUrlMap: make(map[string]string),
 	}
 }
 
+// GetPathUrlMap x://电影 -- /movie_dir_0  or x://电视剧 -- /series_dir_0
+func (s *StaticFileSystemBackEnd) GetPathUrlMap() map[string]string {
+	return s.pathUrlMap
+}
+
 func (s *StaticFileSystemBackEnd) Start(commonSettings *settings.CommonSettings) {
 	defer s.locker.Unlock()
 	s.locker.Lock()
@@ -39,11 +46,17 @@ func (s *StaticFileSystemBackEnd) Start(commonSettings *settings.CommonSettings)
 
 	// 添加电影的
 	for i, path := range commonSettings.MoviePaths {
-		router.StaticFS("/movie_dir_"+fmt.Sprintf("%d", i), http.Dir(path))
+
+		nowUrl := "/movie_dir_" + fmt.Sprintf("%d", i)
+		s.pathUrlMap[path] = nowUrl
+		router.StaticFS(nowUrl, http.Dir(path))
 	}
 	// 添加连续剧的
 	for i, path := range commonSettings.SeriesPaths {
-		router.StaticFS("/series_dir_"+fmt.Sprintf("%d", i), http.Dir(path))
+
+		nowUrl := "/series_dir_" + fmt.Sprintf("%d", i)
+		s.pathUrlMap[path] = nowUrl
+		router.StaticFS(nowUrl, http.Dir(path))
 	}
 	s.srv = &http.Server{
 		Addr:    ":" + commonSettings.LocalStaticFilePort,
@@ -59,7 +72,9 @@ func (s *StaticFileSystemBackEnd) Start(commonSettings *settings.CommonSettings)
 }
 
 func (s *StaticFileSystemBackEnd) Stop() {
-	defer s.locker.Unlock()
+	defer func() {
+		s.locker.Unlock()
+	}()
 	s.locker.Lock()
 
 	if s.running == false {
@@ -67,6 +82,10 @@ func (s *StaticFileSystemBackEnd) Stop() {
 		return
 	}
 
+	defer func() {
+		s.pathUrlMap = make(map[string]string)
+	}()
+
 	s.running = false
 
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

+ 2 - 1
internal/backend/controllers/v1/controller_base.go

@@ -19,8 +19,8 @@ type ControllerBase struct {
 	videoScanAndRefreshHelper           *video_scan_and_refresh_helper.VideoScanAndRefreshHelper
 	videoScanAndRefreshHelperIsRunning  bool
 	videoScanAndRefreshHelperLocker     lock.Lock
-	scanVideoResult                     *video_scan_and_refresh_helper.ScanVideoResult
 	videoScanAndRefreshHelperErrMessage string
+	MovieInfo                           []backend.MovieInfo
 }
 
 func NewControllerBase(log *logrus.Logger, cronHelper *cron_helper.CronHelper) *ControllerBase {
@@ -31,6 +31,7 @@ func NewControllerBase(log *logrus.Logger, cronHelper *cron_helper.CronHelper) *
 		// 这里因为不进行任务的添加,仅仅是扫描,所以 downloadQueue 可以为 nil
 		videoScanAndRefreshHelper:       video_scan_and_refresh_helper.NewVideoScanAndRefreshHelper(cronHelper.FileDownloader, nil),
 		videoScanAndRefreshHelperLocker: lock.NewLock(),
+		MovieInfo:                       make([]backend.MovieInfo, 0),
 	}
 }
 

+ 55 - 2
internal/backend/controllers/v1/video_list.go

@@ -1,10 +1,14 @@
 package v1
 
 import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sort_things"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/video_scan_and_refresh_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/backend"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/task_queue"
 	"github.com/gin-gonic/gin"
 	"net/http"
+	"path/filepath"
+	"strings"
 )
 
 func (cb *ControllerBase) RefreshVideoListStatusHandler(c *gin.Context) {
@@ -52,19 +56,68 @@ func (cb *ControllerBase) RefreshVideoListHandler(c *gin.Context) {
 		cb.log.Infoln("Video Scan Started By webui...")
 		// 先进行扫描
 		var err2 error
+		var scanVideoResult *video_scan_and_refresh_helper.ScanVideoResult
 		cb.videoScanAndRefreshHelperErrMessage = ""
-		cb.scanVideoResult, err2 = cb.videoScanAndRefreshHelper.ScanNormalMovieAndSeries()
+		scanVideoResult, err2 = cb.videoScanAndRefreshHelper.ScanNormalMovieAndSeries()
 		if err2 != nil {
 			cb.log.Errorln("ScanNormalMovieAndSeries", err2)
 			cb.videoScanAndRefreshHelperErrMessage = err2.Error()
 			return
 		}
-		err2 = cb.videoScanAndRefreshHelper.ScanEmbyMovieAndSeries(cb.scanVideoResult)
+		err2 = cb.videoScanAndRefreshHelper.ScanEmbyMovieAndSeries(scanVideoResult)
 		if err2 != nil {
 			cb.log.Errorln("ScanEmbyMovieAndSeries", err2)
 			cb.videoScanAndRefreshHelperErrMessage = err2.Error()
 			return
 		}
+
+		pathUrlMap := cb.StaticFileSystemBackEnd.GetPathUrlMap()
+		// 排序得到匹配上的路径,最长的那个
+		sortMoviePaths := sort_things.SortStringSliceByLength(cb.cronHelper.Settings.CommonSettings.MoviePaths)
+		sortSeriesPaths := sort_things.SortStringSliceByLength(cb.cronHelper.Settings.CommonSettings.SeriesPaths)
+
+		if cb.cronHelper.Settings.EmbySettings.Enable == true {
+			// Emby 情况
+			if scanVideoResult.Emby == nil {
+				return
+			}
+
+		} else {
+			// Normal 情况
+			if scanVideoResult.Normal == nil {
+				return
+			}
+			replaceIndexMap := make(map[int]int)
+			for _, orgPrePath := range sortMoviePaths {
+				for i, oneMovieFPath := range scanVideoResult.Normal.MovieFileFullPathList {
+
+					_, found := replaceIndexMap[i]
+					if found == true {
+						// 替换过了,跳过
+						continue
+					}
+					if strings.HasPrefix(oneMovieFPath, orgPrePath.Path) == true {
+
+						desUrl, found := pathUrlMap[orgPrePath.Path]
+						if found == false {
+							// 没有找到对应的 URL
+							continue
+						}
+						// 匹配上了前缀就替换这个,并记录
+						movieFUrl := strings.ReplaceAll(oneMovieFPath, orgPrePath.Path, desUrl)
+						oneMovieInfo := backend.MovieInfo{
+							Name:       filepath.Base(movieFUrl),
+							DirRootUrl: filepath.Dir(movieFUrl),
+							VideoUrl:   movieFUrl,
+						}
+						replaceIndexMap[i] = i
+						cb.MovieInfo = append(cb.MovieInfo, oneMovieInfo)
+					}
+				}
+			}
+		}
+
+		println("haha")
 		// 这里会把得到的 Normal 和 Emby 的结果都放入 cb.scanVideoResult
 		// 根据 用户的情况,选择行返回是 Emby Or Normal 的结果
 		// 并且如果是 Emby 那么会在页面上出现一个刷新字幕列表的按钮(这个需要 Emby 中video 的 ID)

+ 5 - 5
internal/backend/routers/base_router.go

@@ -38,6 +38,11 @@ func InitRouter(fileDownloader *file_downloader.FileDownloader, router *gin.Engi
 	// v1路由: /v1/xxx
 	GroupV1 := router.Group("/" + cbV1.GetVersion())
 	{
+		GroupV1.POST("/video/list/refresh", cbV1.RefreshVideoListHandler)
+		GroupV1.GET("/video/list/refresh", cbV1.RefreshVideoListStatusHandler)
+		GroupV1.GET("/video/list/movies", cbV1.MovieListHandler)
+		GroupV1.GET("/video/list/series", cbV1.SeriesListHandler)
+
 		GroupV1.Use(middle.CheckAuth())
 
 		GroupV1.GET("/settings", cbV1.SettingsHandler)
@@ -50,11 +55,6 @@ func InitRouter(fileDownloader *file_downloader.FileDownloader, router *gin.Engi
 		GroupV1.GET("/jobs/list", cbV1.JobsListHandler)
 		GroupV1.POST("/jobs/change-job-status", cbV1.ChangeJobStatusHandler)
 		GroupV1.POST("/jobs/log", cbV1.JobLogHandler)
-
-		GroupV1.POST("/video/list/refresh", cbV1.RefreshVideoListHandler)
-		GroupV1.GET("/video/list/refresh", cbV1.RefreshVideoListStatusHandler)
-		GroupV1.GET("/video/list/movies", cbV1.MovieListHandler)
-		GroupV1.GET("/video/list/series", cbV1.SeriesListHandler)
 	}
 
 	return cbV1

+ 3 - 23
internal/logic/emby_helper/embyhelper.go

@@ -7,6 +7,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/path_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sort_things"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
 	"github.com/allanpk716/ChineseSubFinder/internal/types"
 	common2 "github.com/allanpk716/ChineseSubFinder/internal/types/common"
@@ -17,7 +18,6 @@ import (
 	"golang.org/x/net/context"
 	"path"
 	"path/filepath"
-	"sort"
 	"strings"
 	"sync"
 	"time"
@@ -309,7 +309,7 @@ func (em *EmbyHelper) findMappingPath(fileFPathWithEmby string, isMovieOrSeries
 	}
 
 	// 排序得到匹配上的路径,最长的那个
-	pathSlices := sortStringSliceByLength(matchedEmbyPaths)
+	pathSlices := sort_things.SortStringSliceByLength(matchedEmbyPaths)
 	// 然后还需要从这个最长的路径,从 map 中找到对应的物理路径
 	// nowPhRootPath 这个路径是映射的根目录,如果里面再次嵌套 子文件夹 再到连续剧目录,则是个问题,会丢失子文件夹目录
 	nowPhRootPath := ""
@@ -513,7 +513,7 @@ func (em *EmbyHelper) findMappingPathWithMixInfo(mixInfo *emby.EmbyMixInfo, isMo
 		return false
 	}
 	// 排序得到匹配上的路径,最长的那个
-	pathSlices := sortStringSliceByLength(matchedEmbyPaths)
+	pathSlices := sort_things.SortStringSliceByLength(matchedEmbyPaths)
 	// 然后还需要从这个最长的路径,从 map 中找到对应的物理路径
 	// nowPhRootPath 这个路径是映射的根目录,如果里面再次嵌套 子文件夹 再到连续剧目录,则是个问题,会丢失子文件夹目录
 	nowPhRootPath := ""
@@ -983,26 +983,6 @@ 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"

+ 2 - 2
internal/logic/sub_supplier/subSupplierHub.go

@@ -87,7 +87,7 @@ func (d *SubSupplierHub) MovieNeedDlSub(videoFullPath string, forcedScanAndDownl
 }
 
 // SeriesNeedDlSub 连续剧是否符合要求需要下载字幕
-func (d *SubSupplierHub) SeriesNeedDlSub(seriesRootPath string, forcedScanAndDownloadSub bool) (bool, *series.SeriesInfo, error) {
+func (d *SubSupplierHub) SeriesNeedDlSub(seriesRootPath string, forcedScanAndDownloadSub bool, need2AnalyzeSub bool) (bool, *series.SeriesInfo, error) {
 
 	if forcedScanAndDownloadSub == false {
 		if d.settings.AdvancedSettings.ScanLogic.SkipChineseSeries == true {
@@ -108,7 +108,7 @@ func (d *SubSupplierHub) SeriesNeedDlSub(seriesRootPath string, forcedScanAndDow
 	seriesInfo, err := seriesHelper.ReadSeriesInfoFromDir(d.log, seriesRootPath,
 		d.settings.AdvancedSettings.TaskQueue.ExpirationTime,
 		forcedScanAndDownloadSub,
-		false)
+		need2AnalyzeSub)
 	if err != nil {
 		return false, nil, errors.Newf("ReadSeriesInfoFromDir %v %v", seriesRootPath, err)
 	}

+ 24 - 0
internal/pkg/sort_things/sort_things.go

@@ -0,0 +1,24 @@
+package sort_things
+
+import "sort"
+
+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] }
+
+// SortStringSliceByLength 排序得到匹配上的路径,最长的那个
+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
+}

+ 30 - 0
internal/pkg/sort_things/sort_things_test.go

@@ -0,0 +1,30 @@
+package sort_things
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestSortStringSliceByLength(t *testing.T) {
+	type args struct {
+		m []string
+	}
+	tests := []struct {
+		name string
+		args args
+		want PathSlices
+	}{
+		{name: "00", args: args{m: []string{"1", "12", "123"}}, want: PathSlices{
+			PathSlice{"123"},
+			PathSlice{"12"},
+			PathSlice{"1"},
+		}},
+	}
+	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)
+			}
+		})
+	}
+}

+ 12 - 2
internal/pkg/video_scan_and_refresh_helper/video_scan_and_refresh_helper.go

@@ -20,6 +20,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/types/emby"
 	TTaskqueue "github.com/allanpk716/ChineseSubFinder/internal/types/task_queue"
 	"github.com/emirpasic/gods/maps/treemap"
+	"github.com/huandu/go-clone"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/net/context"
 	"path/filepath"
@@ -171,7 +172,15 @@ func (v *VideoScanAndRefreshHelper) ScanEmbyMovieAndSeries(scanVideoResult *Scan
 	if v.settings.EmbySettings.Enable == false {
 		v.embyHelper = nil
 	} else {
-		v.embyHelper = embyHelper.NewEmbyHelper(v.log, v.settings)
+
+		if v.NeedForcedScanAndDownSub == true {
+			// 如果是强制,那么就临时修改 Setting 的 Emby MaxRequestVideoNumber 参数为 1000000
+			tmpSetting := clone.Clone(v.settings).(*settings.Settings)
+			tmpSetting.EmbySettings.MaxRequestVideoNumber = 1000000
+			v.embyHelper = embyHelper.NewEmbyHelper(v.log, tmpSetting)
+		} else {
+			v.embyHelper = embyHelper.NewEmbyHelper(v.log, v.settings)
+		}
 	}
 	var err error
 
@@ -402,7 +411,8 @@ func (v *VideoScanAndRefreshHelper) filterMovieAndSeriesNeedDownloadNormal(norma
 		taskData := inData.(*task_control.TaskData)
 		seriesInputData := taskData.DataEx.(TaskInputData)
 		// 因为可能回去 Web 获取 IMDB 信息,所以这里的错误不返回
-		bNeedDlSub, seriesInfo, err := v.subSupplierHub.SeriesNeedDlSub(seriesInputData.InputPath, v.NeedForcedScanAndDownSub)
+		bNeedDlSub, seriesInfo, err := v.subSupplierHub.SeriesNeedDlSub(seriesInputData.InputPath,
+			v.NeedForcedScanAndDownSub, false)
 		if err != nil {
 			v.log.Errorln("filterMovieAndSeriesNeedDownloadNormal.SeriesNeedDlSub", err)
 			return err

+ 12 - 0
internal/types/backend/reply_movie_list.go

@@ -0,0 +1,12 @@
+package backend
+
+type ReplyMovieList struct {
+	Movies []MovieInfo `json:"movies"`
+}
+
+type MovieInfo struct {
+	Name                     string `json:"name"`
+	DirRootUrl               string `json:"dir_root_url"`
+	VideoUrl                 string `json:"video_url"`
+	MediaServerInsideVideoID string `json:"media_server_inside_video_id"`
+}

+ 17 - 0
internal/types/backend/reply_series_list.go

@@ -0,0 +1,17 @@
+package backend
+
+type ReplySeriesList struct {
+	Movies []MovieInfo `json:"movies"`
+}
+
+type SeasonInfo struct {
+	Name                     string `json:"name"`
+	Url                      string `json:"dir_root_url"`
+	MediaServerInsideVideoID string `json:"media_server_inside_video_id"`
+}
+
+type EpsInfo struct {
+	Name                     string `json:"name"`
+	Url                      string `json:"dir_root_url"`
+	MediaServerInsideVideoID string `json:"media_server_inside_video_id"`
+}