Selaa lähdekoodia

移除 Subhd 和 Zimuku 的代码,移除 Chrome 相关的功能,以后强制 Lite 模式

Signed-off-by: allan716 <[email protected]>
allan716 3 vuotta sitten
vanhempi
sitoutus
460bcde74c

+ 3 - 9
cmd/chinesesubfinder/main.go

@@ -60,7 +60,8 @@ func init() {
 		AppVersion += " Lite"
 		pkg.SetLiteMode(true)
 	} else {
-		pkg.SetLiteMode(false)
+		// 强制设置为 Lite 模式,取消 Chrome 的相关功能,交给外部的爬虫解决
+		pkg.SetLiteMode(true)
 	}
 
 	loggerBase.Infoln("ChineseSubFinder Version:", AppVersion)
@@ -146,14 +147,7 @@ func main() {
 			if err != nil {
 				loggerBase.Panicln("pre_job", err)
 			}
-		} else {
-			// 完整版模式,启用 Chrome 相关操作
-			err := pj.HotFix().ChangeSubNameFormat().ReloadBrowser().Wait()
-			if err != nil {
-				loggerBase.Panicln("pre_job", err)
-			}
 		}
-
 	}
 	// ----------------------------------------------
 	fileDownloader := file_downloader.NewFileDownloader(
@@ -198,7 +192,7 @@ var ExtEnCode = "abcdefg1234567890"
 // 针对制作群晖的 SPK 应用,无法写入默认的 /config 目录而给出的新的编译条件,直接指向这个目录到当前程序的目录
 var setLinuxConfigPathInSelfPathFlag = flag.String("setconfigselfpath", "", "针对制作群晖的 SPK 应用,无法写入默认的 /config 目录而给出的新的编译条件,直接指向这个目录到当前程序的目录")
 
-var setLiteModeFlag = flag.Bool("litemode", false, "设置为 Lite 模式,不启用 Chrome 相关操作")
+var setLiteModeFlag = flag.Bool("litemode", true, "设置为 Lite 模式,不启用 Chrome 相关操作")
 
 var (
 	BaseKey  = "0123456789123456789" // 基础的密钥,密钥会基于这个基础的密钥生成

+ 0 - 72
cmd/chrome_checker/main.go

@@ -1,72 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"os"
-
-	"github.com/go-rod/rod"
-	"github.com/go-rod/rod/lib/launcher"
-	"github.com/urfave/cli/v2"
-)
-
-/*
-	使用的命令:
-		chrome_checker -cbp ${chromeBinFPath}
-
-		${chromeBinFPath} -> Chrome 的二进制文件路径
-
-	程序返回值:
-		exit(0) success
-		exit(1) error
-*/
-
-func main() {
-
-	if recover() != nil {
-		fmt.Println("Check Chrome has panic")
-		os.Exit(1)
-	}
-
-	var chromeBinFPath string
-
-	app := &cli.App{
-		Name:  "Chrome Checker",
-		Usage: "Check Chrome has installed, if not will not auto download and install it",
-		Flags: []cli.Flag{
-			&cli.StringFlag{
-				Name:        "chromeBinFPath",
-				Aliases:     []string{"cbp"},
-				Usage:       "Bin of the browser binary path to launch",
-				Destination: &chromeBinFPath,
-				Required:    true,
-			},
-		},
-		Action: func(c *cli.Context) error {
-			err := rod.Try(func() {
-				purl := launcher.New().Bin(chromeBinFPath).MustLaunch()
-				browser := rod.New().ControlURL(purl).MustConnect()
-				page := browser.MustPage("https://www.baidu.com").MustWaitLoad()
-				defer func() {
-					_ = page.Close()
-				}()
-			})
-			if err != nil {
-				fmt.Println("Check Chrome has error", err.Error())
-				os.Exit(1)
-			}
-
-			fmt.Println("Check Chrome is ok")
-			os.Exit(0)
-
-			return nil
-		},
-	}
-
-	err := app.Run(os.Args)
-	if err != nil {
-		fmt.Println("Check Chrome has error", err.Error())
-		os.Exit(1)
-	}
-
-	os.Exit(0)
-}

+ 0 - 2
go.mod

@@ -4,7 +4,6 @@ go 1.17
 
 require (
 	github.com/PuerkitoBio/goquery v1.7.1
-	github.com/StalkR/imdb v1.0.10
 	github.com/Tnze/go.num/v2 v2.0.0-20191006170829-cb483d4c9152
 	github.com/abadojack/whatlanggo v1.0.1
 	github.com/allanpk716/fake-useragent v0.2.1
@@ -21,7 +20,6 @@ require (
 	github.com/go-git/go-git/v5 v5.4.2
 	github.com/go-resty/resty/v2 v2.6.0
 	github.com/go-rod/rod v0.106.8
-	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/google/uuid v1.3.0
 	github.com/grd/stat v0.0.0-20130623202159-138af3fd5012
 	github.com/huandu/go-clone v1.3.0

+ 0 - 6
go.sum

@@ -34,10 +34,6 @@ github.com/PuerkitoBio/goquery v1.7.1 h1:oE+T06D+1T7LNrn91B4aERsRIeCLJ/oPSa6xB9F
 github.com/PuerkitoBio/goquery v1.7.1/go.mod h1:XY0pP4kfraEmmV1O7Uf6XyjoslwsneBbgeDjLYuN8xY=
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
-github.com/StalkR/httpcache v1.0.0 h1:Px+QK86m7FEEvCfpfC+C0sNiUnRrLQyMVVJ6LKiXNvk=
-github.com/StalkR/httpcache v1.0.0/go.mod h1:yvbaYwH6w1USHPqgspMSwumbLwWE+B7jIZgfLYkTw1M=
-github.com/StalkR/imdb v1.0.10 h1:1u2kNUMbaBZ6Fp9klmrFuamrnEDh5c1ggqcjhWm1SZ4=
-github.com/StalkR/imdb v1.0.10/go.mod h1:nxQmP4/nGtTVICl2+UmwhCnosVwVClmksdyptjE5Lj8=
 github.com/Tnze/go.num/v2 v2.0.0-20191006170829-cb483d4c9152 h1:6Ny2zcG2k/0aOE8rLbDdLdPMr0o7lqMfdnYJe6pZj9w=
 github.com/Tnze/go.num/v2 v2.0.0-20191006170829-cb483d4c9152/go.mod h1:fNGLFjpxgDvBqQPv1HYSuGi6pRuI8wdKvvspYvUQufc=
 github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
@@ -231,8 +227,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=

+ 57 - 62
pkg/logic/cron_helper/cron_helper.go

@@ -1,12 +1,7 @@
 package cron_helper
 
 import (
-	"github.com/ChineseSubFinder/ChineseSubFinder/internal/dao"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/file_downloader"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/scan_played_video_subinfo"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
-
 	//"github.com/ChineseSubFinder/ChineseSubFinder/internal/logic/pre_job"
 	"sync"
 	"time"
@@ -21,21 +16,21 @@ import (
 )
 
 type CronHelper struct {
-	stopping                      bool                                                     // 正在停止
-	cronHelperRunning             bool                                                     // 这个是定时器启动的状态,它为true,不代表核心函数在执行
-	scanPlayedVideoSubInfo        *scan_played_video_subinfo.ScanPlayedVideoSubInfo        // 扫描已经播放过的视频的字幕信息
-	FileDownloader                *file_downloader.FileDownloader                          // 文件下载器
-	DownloadQueue                 *task_queue.TaskQueue                                    // 需要下载的视频的队列
-	Downloader                    *downloader.Downloader                                   // 下载者线程
-	videoScanAndRefreshHelper     *video_scan_and_refresh_helper.VideoScanAndRefreshHelper // 视频扫描和刷新的帮助类
-	cronLock                      sync.Mutex                                               // 锁
-	c                             *cron.Cron                                               // 定时器实例
-	Logger                        *logrus.Logger                                           // 日志实例
-	entryIDScanVideoProcess       cron.EntryID
-	entryIDSupplierCheck          cron.EntryID
-	entryIDQueueDownloader        cron.EntryID
-	entryIDScanPlayedVideoSubInfo cron.EntryID
-	entryIDUploadPlayedVideoSub   cron.EntryID
+	stopping          bool // 正在停止
+	cronHelperRunning bool // 这个是定时器启动的状态,它为true,不代表核心函数在执行
+	//scanPlayedVideoSubInfo    *scan_played_video_subinfo.ScanPlayedVideoSubInfo        // 扫描已经播放过的视频的字幕信息
+	FileDownloader            *file_downloader.FileDownloader                          // 文件下载器
+	DownloadQueue             *task_queue.TaskQueue                                    // 需要下载的视频的队列
+	Downloader                *downloader.Downloader                                   // 下载者线程
+	videoScanAndRefreshHelper *video_scan_and_refresh_helper.VideoScanAndRefreshHelper // 视频扫描和刷新的帮助类
+	cronLock                  sync.Mutex                                               // 锁
+	c                         *cron.Cron                                               // 定时器实例
+	Logger                    *logrus.Logger                                           // 日志实例
+	entryIDScanVideoProcess   cron.EntryID                                             // 建立视频缓存,扫描有那些视频需要进行字幕下载的定时器的 ID
+	entryIDSupplierCheck      cron.EntryID                                             // 检查字幕源有效性的定时器的 ID
+	entryIDQueueDownloader    cron.EntryID                                             // 下载队列的定时器的 ID
+	//entryIDScanPlayedVideoSubInfo cron.EntryID
+	//entryIDUploadPlayedVideoSub cron.EntryID
 }
 
 func NewCronHelper(fileDownloader *file_downloader.FileDownloader) *CronHelper {
@@ -47,13 +42,13 @@ func NewCronHelper(fileDownloader *file_downloader.FileDownloader) *CronHelper {
 		DownloadQueue: task_queue.NewTaskQueue(fileDownloader.CacheCenter),
 	}
 
-	var err error
+	//var err error
 	// ----------------------------------------------
 	// 扫描已播放
-	ch.scanPlayedVideoSubInfo, err = scan_played_video_subinfo.NewScanPlayedVideoSubInfo(ch.Logger, fileDownloader)
-	if err != nil {
-		ch.Logger.Panicln(err)
-	}
+	//ch.scanPlayedVideoSubInfo, err = scan_played_video_subinfo.NewScanPlayedVideoSubInfo(ch.Logger, fileDownloader)
+	//if err != nil {
+	//	ch.Logger.Panicln(err)
+	//}
 	// ----------------------------------------------
 	// 字幕扫描器
 	ch.videoScanAndRefreshHelper = video_scan_and_refresh_helper.NewVideoScanAndRefreshHelper(
@@ -139,10 +134,10 @@ func (ch *CronHelper) Start(runImmediately bool) {
 		ch.Logger.Panicln("CronHelper QueueDownloader, QueueDownloader Cron entryID:", ch.entryIDQueueDownloader, "Error:", err)
 	}
 	// 这个可以由 ch.scanPlayedVideoSubInfo.Cancel() 取消执行
-	ch.entryIDScanPlayedVideoSubInfo, err = ch.c.AddFunc("@every 24h", ch.scanPlayedVideoSub)
-	if err != nil {
-		ch.Logger.Panicln("CronHelper QueueDownloader, scanPlayedVideoSub Cron entryID:", ch.entryIDScanPlayedVideoSubInfo, "Error:", err)
-	}
+	//ch.entryIDScanPlayedVideoSubInfo, err = ch.c.AddFunc("@every 24h", ch.scanPlayedVideoSub)
+	//if err != nil {
+	//	ch.Logger.Panicln("CronHelper QueueDownloader, scanPlayedVideoSub Cron entryID:", ch.entryIDScanPlayedVideoSubInfo, "Error:", err)
+	//}
 	// 字幕的上传逻辑
 	if settings.Get().ExperimentalFunction.ShareSubSettings.ShareSubEnabled == true {
 		// 取消上传字幕的逻辑,目前评估的第一阶段已经完成,后续的逻辑需要重新评估
@@ -226,7 +221,7 @@ func (ch *CronHelper) Stop() {
 
 	ch.videoScanAndRefreshHelper.Cancel()
 	ch.Downloader.Cancel()
-	ch.scanPlayedVideoSubInfo.Cancel()
+	//ch.scanPlayedVideoSubInfo.Cancel()
 	// Stop stops the cron scheduler if it is running; otherwise it does nothing.
 	// A context is returned so the caller can wait for running jobs to complete.
 	nowContext := ch.c.Stop()
@@ -245,38 +240,38 @@ func (ch *CronHelper) Stop() {
 	ch.Logger.Infoln("CronHelper.Stop() Done.")
 }
 
-func (ch *CronHelper) scanPlayedVideoSub() {
-
-	ch.Logger.Infoln("Update Info...")
-	nowInfo := dao.UpdateInfo(pkg.AppVersion(), settings.Get())
-	_, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.FeedBack(
-		nowInfo.Id,
-		nowInfo.Version, nowInfo.MediaServer,
-		nowInfo.EnableShare, nowInfo.EnableApiKey)
-	if err != nil {
-		ch.Logger.Errorln("FeedBack Error:", err)
-		return
-	}
-
-	ch.Logger.Infoln("------------------------------------------------------")
-	ch.Logger.Infoln("scanPlayedVideoSub Start")
-	startT := time.Now()
-	defer func() {
-		ch.Logger.Infoln("scanPlayedVideoSub End, Cost:", time.Since(startT).Minutes(), "min")
-		ch.Logger.Infoln("------------------------------------------------------")
-	}()
-	bok, err := ch.scanPlayedVideoSubInfo.GetPlayedItemsSubtitle(settings.Get().EmbySettings, common.EmbyApiGetItemsLimitMax)
-	if err != nil {
-		ch.Logger.Errorln(err)
-	}
-	if bok == true {
-		ch.scanPlayedVideoSubInfo.Clear()
-		err = ch.scanPlayedVideoSubInfo.Scan()
-		if err != nil {
-			ch.Logger.Errorln(err)
-		}
-	}
-}
+//func (ch *CronHelper) scanPlayedVideoSub() {
+//
+//	ch.Logger.Infoln("Update Info...")
+//	nowInfo := dao.UpdateInfo(pkg.AppVersion(), settings.Get())
+//	_, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.FeedBack(
+//		nowInfo.Id,
+//		nowInfo.Version, nowInfo.MediaServer,
+//		nowInfo.EnableShare, nowInfo.EnableApiKey)
+//	if err != nil {
+//		ch.Logger.Errorln("FeedBack Error:", err)
+//		return
+//	}
+//
+//	ch.Logger.Infoln("------------------------------------------------------")
+//	ch.Logger.Infoln("scanPlayedVideoSub Start")
+//	startT := time.Now()
+//	defer func() {
+//		ch.Logger.Infoln("scanPlayedVideoSub End, Cost:", time.Since(startT).Minutes(), "min")
+//		ch.Logger.Infoln("------------------------------------------------------")
+//	}()
+//	bok, err := ch.scanPlayedVideoSubInfo.GetPlayedItemsSubtitle(settings.Get().EmbySettings, common.EmbyApiGetItemsLimitMax)
+//	if err != nil {
+//		ch.Logger.Errorln(err)
+//	}
+//	if bok == true {
+//		ch.scanPlayedVideoSubInfo.Clear()
+//		err = ch.scanPlayedVideoSubInfo.Scan()
+//		if err != nil {
+//			ch.Logger.Errorln(err)
+//		}
+//	}
+//}
 
 func (ch *CronHelper) CronHelperRunning() bool {
 

+ 0 - 17
pkg/logic/pre_job/pro_job.go

@@ -9,7 +9,6 @@ import (
 	common2 "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
 
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/hot_fix"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/rod_helper"
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_formatter"
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_formatter/common"
 	"github.com/sirupsen/logrus"
@@ -88,22 +87,6 @@ func (p *PreJob) ChangeSubNameFormat() *PreJob {
 	return p
 }
 
-func (p *PreJob) ReloadBrowser() *PreJob {
-
-	if p.gError != nil {
-		p.log.Infoln("Skip PreJob.ReloadBrowser()")
-		return p
-	}
-	defer func() {
-		p.log.Infoln("PreJob.ReloadBrowser() End")
-	}()
-	p.log.Infoln("PreJob.ReloadBrowser() Start...")
-	// ------------------------------------------------------------------------
-	// ReloadBrowser 提前把浏览器下载好
-	rod_helper.ReloadBrowser(p.log)
-	return p
-}
-
 func (p *PreJob) Wait() error {
 	defer func() {
 		p.log.Infoln("PreJob.Wait() Done.")

+ 0 - 2
pkg/logic/sub_supplier/subhd/.rod

@@ -1,2 +0,0 @@
-show
-devtools

+ 0 - 2
pkg/logic/sub_supplier/subhd/.rod.backup

@@ -1,2 +0,0 @@
-show
-devtools

BIN
pkg/logic/sub_supplier/subhd/result.png


+ 0 - 807
pkg/logic/sub_supplier/subhd/subhd.go

@@ -1,807 +0,0 @@
-package subhd
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"image/jpeg"
-	"math"
-	"net/url"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strings"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/local_http_proxy_server"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/search"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/language"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/series"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/supplier"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/file_downloader"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/rod_helper"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/mix_media_info"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/decode"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/notify_center"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_parser_hub"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/url_connectedness_helper"
-	"github.com/PuerkitoBio/goquery"
-	"github.com/Tnze/go.num/v2/zh"
-	"github.com/go-rod/rod"
-	"github.com/go-rod/rod/lib/proto"
-	"github.com/nfnt/resize"
-	"github.com/sirupsen/logrus"
-)
-
-type Supplier struct {
-	log            *logrus.Logger
-	fileDownloader *file_downloader.FileDownloader
-	tt             time.Duration
-	isAlive        bool
-}
-
-func NewSupplier(fileDownloader *file_downloader.FileDownloader) *Supplier {
-
-	sup := Supplier{}
-	sup.log = fileDownloader.Log
-	sup.fileDownloader = fileDownloader
-
-	if settings.Get().AdvancedSettings.Topic != common.DownloadSubsPerSite {
-		settings.Get().AdvancedSettings.Topic = common.DownloadSubsPerSite
-	}
-	sup.isAlive = true // 默认是可以使用的,如果 check 后,再调整状态
-
-	// 默认超时是 2 * 60s,如果是调试模式则是 5 min
-	sup.tt = common.BrowserTimeOut
-	if settings.Get().AdvancedSettings.DebugMode == true {
-		sup.tt = common.OneMovieProcessTimeOut
-	}
-
-	return &sup
-}
-
-func (s *Supplier) CheckAlive() (bool, int64) {
-
-	proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(
-		settings.Get().AdvancedSettings.SuppliersSettings.SubHD.RootUrl,
-		local_http_proxy_server.GetProxyUrl())
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "CheckAlive", "Error", err)
-		s.isAlive = false
-		return false, 0
-	}
-	if proxyStatus == false {
-		s.log.Errorln(s.GetSupplierName(), "CheckAlive", "Status != 200")
-		s.isAlive = false
-		return false, proxySpeed
-	}
-
-	s.isAlive = true
-	return true, proxySpeed
-}
-
-func (s *Supplier) IsAlive() bool {
-	return s.isAlive
-}
-
-func (s *Supplier) OverDailyDownloadLimit() bool {
-
-	return true
-
-	if settings.Get().AdvancedSettings.SuppliersSettings.SubHD.DailyDownloadLimit == 0 {
-		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit is 0, will Skip Download")
-		return true
-	}
-
-	// 需要查询今天的限额
-	count, err := s.fileDownloader.CacheCenter.DailyDownloadCountGet(s.GetSupplierName(),
-		pkg.GetPublicIP(s.log, settings.Get().AdvancedSettings.TaskQueue))
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "DailyDownloadCountGet", err)
-		return true
-	}
-	if count >= settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit {
-		// 超限了
-		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit:", settings.Get().AdvancedSettings.SuppliersSettings.SubHD.DailyDownloadLimit, "Now Is:", count)
-		return true
-	} else {
-		// 没有超限
-		s.log.Infoln(s.GetSupplierName(), "DailyDownloadLimit:", settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit, "Now Is:", count)
-		return false
-	}
-}
-
-func (s *Supplier) GetLogger() *logrus.Logger {
-	return s.log
-}
-
-func (s *Supplier) GetSupplierName() string {
-	return common.SubSiteSubHd
-}
-
-func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
-	return s.getSubListFromFile4Movie(filePath)
-}
-
-func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
-
-	var browser *rod.Browser
-	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	browser, err := rod_helper.NewBrowserEx(rod_helper.NewBrowserOptions(s.log, true, settings.Get()))
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.fileDownloader.MediaInfoDealers,
-		seriesInfo.EpList[0].FileFullPath, false,
-		settings.Get().AdvancedSettings.ProxySettings)
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), seriesInfo.EpList[0].FileFullPath, "GetMixMediaInfo", err)
-		return nil, err
-	}
-	// 优先中文查询
-	keyWord, err := mix_media_info.KeyWordSelect(mediaInfo, seriesInfo.EpList[0].FileFullPath, true, "cn")
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), seriesInfo.EpList[0].FileFullPath, "keyWordSelect", err)
-		return nil, err
-	}
-	if keyWord == "" {
-		// 更换英文译名
-		keyWord, err = mix_media_info.KeyWordSelect(mediaInfo, seriesInfo.EpList[0].FileFullPath, true, "en")
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), seriesInfo.EpList[0].FileFullPath, "keyWordSelect", err)
-			return nil, err
-		}
-	}
-	var subInfos = make([]supplier.SubInfo, 0)
-	var subList = make([]HdListItem, 0)
-	for value := range seriesInfo.NeedDlSeasonDict {
-		// 第一级界面,找到影片的详情界面
-		//keyword := seriesInfo.Name + " 第" + zh.Uint64(value).String() + "季"
-		keyword := keyWord + " 第" + zh.Uint64(value).String() + "季"
-		s.log.Infoln("Search Keyword:", keyword)
-		detailPageUrl, err := s.step0(browser, keyword)
-		if err != nil {
-			s.log.Errorln("subhd step0", keyword)
-			return nil, err
-		}
-		if detailPageUrl == "" {
-			// 如果只是搜索不到,则继续换关键词
-			s.log.Warning("subhd first search keyword", keyword, "not found")
-			keyword = seriesInfo.Name
-			s.log.Warning("subhd Retry", keyword)
-			s.log.Infoln("Search Keyword:", keyword)
-			detailPageUrl, err = s.step0(browser, keyword)
-			if err != nil {
-				s.log.Errorln("subhd step0", keyword)
-				return nil, err
-			}
-		}
-		if detailPageUrl == "" {
-			s.log.Warning("subhd search keyword", keyword, "not found")
-			continue
-		}
-		// 列举字幕
-		oneSubList, err := s.step1(browser, detailPageUrl, false)
-		if err != nil {
-			s.log.Errorln("subhd step1", keyword)
-			return nil, err
-		}
-
-		subList = append(subList, oneSubList...)
-	}
-	// 与剧集需要下载的集 List 进行比较,找到需要下载的列表
-	// 找到那些 Eps 需要下载字幕的
-	subInfoNeedDownload := s.whichEpisodeNeedDownloadSub(seriesInfo, subList)
-	// 下载字幕
-	for i, item := range subInfoNeedDownload {
-
-		subInfo, err := s.fileDownloader.GetEx(s.GetSupplierName(), browser, item.Url, int64(i), item.Season, item.Episode, s.DownFile)
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), "GetEx", item.Title, item.Season, item.Episode, err)
-			continue
-		}
-
-		subInfos = append(subInfos, *subInfo)
-	}
-
-	return subInfos, nil
-}
-
-func (s *Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
-	panic("not implemented")
-}
-
-func (s *Supplier) getSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
-	/*
-		虽然是传入视频文件路径,但是其实需要读取对应的视频文件目录下的
-		movie.xml 以及 *.nfo,找到 IMDB id
-		优先通过 IMDB id 去查找字幕
-		如果找不到,再靠文件名提取影片名称去查找
-	*/
-	// 找到这个视频文件,尝试得到 IMDB ID
-	// 目前测试来看,加入 年 这个关键词去搜索,对 2020 年后的影片有利,因为网站有统一的详细页面了,而之前的,没有,会影响识别
-	// 所以,year >= 2020 年,则可以多加一个关键词(年)去搜索影片
-	imdbInfo, err := decode.GetVideoNfoInfo4Movie(filePath)
-	if err != nil {
-		// 允许的错误,跳过,继续进行文件名的搜索
-		s.log.Errorln("model.GetImdbInfo", err)
-	}
-	var subInfoList []supplier.SubInfo
-
-	if imdbInfo.ImdbId != "" {
-		// 先用 imdb id 找
-		subInfoList, err = s.getSubListFromKeyword4Movie(imdbInfo.ImdbId)
-		if err != nil {
-			// 允许的错误,跳过,继续进行文件名的搜索
-			s.log.Errorln(s.GetSupplierName(), "keyword:", imdbInfo.ImdbId)
-			s.log.Errorln("getSubListFromKeyword4Movie", "IMDBID can not found sub", filePath, err)
-		}
-		// 如果有就优先返回
-		if len(subInfoList) > 0 {
-			return subInfoList, nil
-		}
-	}
-	s.log.Infoln(s.GetSupplierName(), filePath, "No subtitle found", "KeyWord:", imdbInfo.ImdbId)
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.fileDownloader.MediaInfoDealers,
-		filePath, true,
-		settings.Get().AdvancedSettings.ProxySettings)
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), filePath, "GetMixMediaInfo", err)
-		return nil, err
-	}
-	// 优先中文查询
-	keyWord, err := mix_media_info.KeyWordSelect(mediaInfo, filePath, true, "cn")
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), filePath, "keyWordSelect", err)
-		return nil, err
-	}
-	// 如果没有,那么就用文件名查找
-	searchKeyword := search.VideoNameSearchKeywordMaker(s.log, keyWord, imdbInfo.Year)
-	subInfoList, err = s.getSubListFromKeyword4Movie(searchKeyword)
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "keyword:", searchKeyword)
-		return nil, err
-	}
-	if len(subInfoList) < 1 {
-		// 切换到英文查询
-		s.log.Infoln(s.GetSupplierName(), filePath, "No subtitle found", "KeyWord:", searchKeyword)
-		keyWord, err = mix_media_info.KeyWordSelect(mediaInfo, filePath, true, "cn")
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), filePath, "keyWordSelect", err)
-			return nil, err
-		}
-		// 如果没有,那么就用文件名查找
-		searchKeyword = search.VideoNameSearchKeywordMaker(s.log, keyWord, imdbInfo.Year)
-		subInfoList, err = s.getSubListFromKeyword4Movie(searchKeyword)
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), "keyword:", searchKeyword)
-			return nil, err
-		}
-		if len(subInfoList) < 1 {
-			s.log.Infoln(s.GetSupplierName(), filePath, "No subtitle found", "KeyWord:", searchKeyword)
-		}
-	}
-
-	return subInfoList, nil
-}
-
-func (s *Supplier) getSubListFromKeyword4Movie(keyword string) ([]supplier.SubInfo, error) {
-
-	s.log.Infoln("Search Keyword:", keyword)
-	var browser *rod.Browser
-	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	browser, err := rod_helper.NewBrowserEx(rod_helper.NewBrowserOptions(s.log, true, settings.Get()))
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-	var subInfos []supplier.SubInfo
-	detailPageUrl, err := s.step0(browser, keyword)
-	if err != nil {
-		return nil, err
-	}
-	// 没有搜索到字幕
-	if detailPageUrl == "" {
-		return nil, nil
-	}
-	subList, err := s.step1(browser, detailPageUrl, true)
-	if err != nil {
-		return nil, err
-	}
-
-	for i, item := range subList {
-
-		subInfo, err := s.fileDownloader.GetEx(s.GetSupplierName(), browser, item.Url, int64(i), 0, 0, s.DownFile)
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), "GetEx", item.Title, item.Season, item.Episode, err)
-			continue
-		}
-
-		subInfos = append(subInfos, *subInfo)
-	}
-
-	return subInfos, nil
-}
-
-func (s *Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, allSubList []HdListItem) []HdListItem {
-	// 字幕很多,考虑效率,需要做成字典
-	// key SxEx - SubInfos
-	var allSubDict = make(map[string][]HdListItem)
-	// 全季的字幕列表
-	var oneSeasonSubDict = make(map[string][]HdListItem)
-	for _, subInfo := range allSubList {
-		_, season, episode, err := decode.GetSeasonAndEpisodeFromSubFileName(subInfo.Title)
-		if err != nil {
-			s.log.Errorln("whichEpisodeNeedDownloadSub.GetVideoInfoFromFileFullPath", subInfo.Title, err)
-			continue
-		}
-		subInfo.Season = season
-		subInfo.Episode = episode
-		epsKey := pkg.GetEpisodeKeyName(season, episode)
-		_, ok := allSubDict[epsKey]
-		if ok == false {
-			// 初始化
-			allSubDict[epsKey] = make([]HdListItem, 0)
-			if season != 0 && episode == 0 {
-				oneSeasonSubDict[epsKey] = make([]HdListItem, 0)
-			}
-		}
-		// 添加
-		allSubDict[epsKey] = append(allSubDict[epsKey], subInfo)
-		if season != 0 && episode == 0 {
-			oneSeasonSubDict[epsKey] = append(oneSeasonSubDict[epsKey], subInfo)
-		}
-	}
-	// 本地的视频列表,找到没有字幕的
-	// 需要进行下载字幕的列表
-	var subInfoNeedDownload = make([]HdListItem, 0)
-	// 有那些 Eps 需要下载的,按 SxEx 反回 epsKey
-	for epsKey, epsInfo := range seriesInfo.NeedDlEpsKeyList {
-		// 从一堆字幕里面找合适的
-		value, ok := allSubDict[epsKey]
-		// 是否有
-		if ok == true && len(value) > 0 {
-			value[0].Season = epsInfo.Season
-			value[0].Episode = epsInfo.Episode
-			subInfoNeedDownload = append(subInfoNeedDownload, value[0])
-		}
-	}
-	// 全季的字幕列表,也拼进去,后面进行下载
-	for _, infos := range oneSeasonSubDict {
-
-		if len(infos) < 1 {
-			continue
-		}
-		subInfoNeedDownload = append(subInfoNeedDownload, infos[0])
-	}
-
-	// 返回前,需要把每一个 Eps 的 Season Episode 信息填充到每个 SubInfo 中
-	return subInfoNeedDownload
-}
-
-// step0 找到这个影片的详情列表
-func (s *Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("subhd_step0", err.Error())
-		}
-	}()
-
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, fmt.Sprintf(settings.Get().AdvancedSettings.SuppliersSettings.SubHD.RootUrl+common.SubSubHDSearchUrl, url.QueryEscape(keyword)), s.tt)
-	if err != nil {
-		return "", err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	// 是否有查找到的结果,至少要有结果。根据这里这样下面才能判断是分析失效了,还是就是没有结果而已
-	re := regexp.MustCompile(`共\s*(\d+)\s*条`)
-	matched := re.FindAllStringSubmatch(result, -1)
-	if matched == nil || len(matched) < 1 {
-		return "", common.SubHDStep0SubCountElementNotFound
-	}
-	subCount, err := decode.GetNumber2int(matched[0][0])
-	if err != nil {
-		return "", err
-	}
-	// 如果所搜没有找到字幕,就要返回
-	if subCount < 1 {
-		return "", nil
-	}
-	// 这里是确认能继续分析的详细连接
-	doc, err := goquery.NewDocumentFromReader(strings.NewReader(result))
-	if err != nil {
-		return "", err
-	}
-	imgSelection := doc.Find("img.rounded-start")
-	_, ok := imgSelection.Attr("src")
-	if ok == true {
-
-		if len(imgSelection.Nodes) < 1 {
-			return "", common.SubHDStep0ImgParentLessThan1
-		}
-		step1Url := ""
-		if imgSelection.Nodes[0].Parent.Data == "a" {
-			// 第一个父级是不是超链接
-			for _, attribute := range imgSelection.Nodes[0].Parent.Attr {
-				if attribute.Key == "href" {
-					step1Url = attribute.Val
-					break
-				}
-			}
-		} else if imgSelection.Nodes[0].Parent.Parent.Data == "a" {
-			// 第二个父级是不是超链接
-			for _, attribute := range imgSelection.Nodes[0].Parent.Parent.Attr {
-				if attribute.Key == "href" {
-					step1Url = attribute.Val
-					break
-				}
-			}
-		}
-		if step1Url == "" {
-			return "", common.SubHDStep0HrefIsNull
-		}
-		return step1Url, nil
-	} else {
-		return "", common.SubHDStep0HrefIsNull
-	}
-}
-
-// step1 获取影片的详情字幕列表
-func (s *Supplier) step1(browser *rod.Browser, detailPageUrl string, isMovieOrSeries bool) ([]HdListItem, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("subhd_step1", err.Error())
-		}
-	}()
-	detailPageUrl = pkg.AddBaseUrl(settings.Get().AdvancedSettings.SuppliersSettings.SubHD.RootUrl, detailPageUrl)
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailPageUrl, s.tt)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	doc, err := goquery.NewDocumentFromReader(strings.NewReader(result))
-	if err != nil {
-		return nil, err
-	}
-	var lists []HdListItem
-
-	const subTableKeyword = ".pt-2"
-	const oneSubTrTitleKeyword = "a.link-dark"
-	const oneSubTrDownloadCountKeyword = "div.px-3"
-	const oneSubLangAndTypeKeyword = ".text-secondary"
-
-	doc.Find(subTableKeyword).EachWithBreak(func(i int, tr *goquery.Selection) bool {
-		if tr.Find(oneSubTrTitleKeyword).Size() == 0 {
-			return true
-		}
-		// 文件的下载页面,还需要分析
-		downUrl, exists := tr.Find(oneSubTrTitleKeyword).Eq(0).Attr("href")
-		if !exists {
-			return true
-		}
-		// 文件名
-		title := strings.TrimSpace(tr.Find(oneSubTrTitleKeyword).Text())
-		// 字幕类型
-		insideSubType := tr.Find(oneSubLangAndTypeKeyword).Text()
-		if sub_parser_hub.IsSubTypeWanted(insideSubType) == false {
-			return true
-		}
-		// 下载的次数
-		downCount, err := decode.GetNumber2int(tr.Find(oneSubTrDownloadCountKeyword).Eq(1).Text())
-		if err != nil {
-			return true
-		}
-
-		listItem := HdListItem{}
-		listItem.Url = downUrl
-		listItem.BaseUrl = settings.Get().AdvancedSettings.SuppliersSettings.SubHD.RootUrl
-		listItem.Title = title
-		listItem.DownCount = downCount
-
-		// 电影,就需要第一个
-		// 连续剧,需要多个
-		if isMovieOrSeries == true {
-
-			if len(lists) >= settings.Get().AdvancedSettings.Topic {
-				return false
-			}
-		}
-		lists = append(lists, listItem)
-		return true
-	})
-
-	return lists, nil
-}
-
-// DownFile 下载字幕 过防水墙
-func (s *Supplier) DownFile(browser *rod.Browser, subDownloadPageUrl string, TopN int64, Season, Episode int) (*supplier.SubInfo, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("subhd_DownFile", err.Error())
-		}
-	}()
-	subDownloadPageFullUrl := pkg.AddBaseUrl(settings.Get().AdvancedSettings.SuppliersSettings.SubHD.RootUrl, subDownloadPageUrl)
-
-	_, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageFullUrl, s.tt)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-
-	// 需要先判断是否先要输入验证码,然后才到下载界面
-	// 下载字幕
-	subInfo, err := s.downloadSubFile(browser, page, subDownloadPageUrl)
-	if err != nil {
-		return nil, err
-	}
-
-	subInfo.TopN = TopN
-	subInfo.Season = Season
-	subInfo.Episode = Episode
-
-	return subInfo, nil
-}
-
-func (s *Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page, subDownloadPageUrl string) (*supplier.SubInfo, error) {
-
-	var err error
-	var doc *goquery.Document
-	downloadSuccess := false
-	fileName := ""
-	fileByte := []byte{0}
-	err = rod.Try(func() {
-		tmpDir := filepath.Join(pkg.DefTmpFolder(), "downloads")
-		wait := browser.Timeout(30 * time.Second).WaitDownload(tmpDir)
-		getDownloadFile := func() ([]byte, string, error) {
-			info := wait()
-
-			if info == nil {
-				return nil, "", errors.New("download sub timeout")
-			}
-
-			downloadPath := filepath.Join(tmpDir, info.GUID)
-			defer func() { _ = os.Remove(downloadPath) }()
-			b, err := os.ReadFile(downloadPath)
-			if err != nil {
-				return nil, "", err
-			}
-			return b, info.SuggestedFilename, nil
-		}
-		// 初始化页面用于查询元素
-		pString := page.MustHTML()
-		doc, err = goquery.NewDocumentFromReader(strings.NewReader(pString))
-		if err != nil {
-			return
-		}
-		// 点击“验证获取下载地址”
-		s.log.Debugln("click '验证获取下载地址'")
-		clickCodeBtn := doc.Find(btnClickCodeBtn)
-		if len(clickCodeBtn.Nodes) < 1 {
-			return
-		}
-		element := page.MustElement(btnClickCodeBtn)
-
-		findInputCode, err := page.Element(InputCode)
-		if err != nil {
-			return
-		}
-		if findInputCode != nil {
-			s.log.Debugln("find '验证' 关键词")
-			// 那么需要填写验证码
-			element.MustClick()
-			time.Sleep(time.Second * 2)
-			// 填写“验证码”
-			s.log.Debugln("填写验证码")
-			el := page.MustElement(InputCode)
-			el.MustInput(common.SubhdCode)
-			//page.MustEval(`$("#gzhcode").attr("value","` + common2.SubhdCode + `");`)
-			// 是否有“完成验证”按钮
-			s.log.Debugln("查找是否有交验证码按钮1")
-			downBtn := doc.Find(btnCommitCode)
-			if len(downBtn.Nodes) < 1 {
-				return
-			}
-			s.log.Debugln("查找是否有交验证码按钮2")
-			element = page.MustElement(btnCommitCode)
-			benCommit := element.MustText()
-			if strings.Contains(benCommit, "验证") == false {
-				s.log.Errorln("btn not found 完整验证")
-				return
-			}
-			s.log.Debugln("点击提交验证码")
-			element.MustClick()
-			time.Sleep(time.Second * 2)
-
-			s.log.Debugln("点击下载按钮")
-			// 点击下载按钮
-			page.MustElement(btnClickCodeBtn).MustClick()
-
-			time.Sleep(time.Second * 2)
-		} else {
-
-			s.log.Debugln("点击下载按钮")
-			// 直接可以下载
-			element.MustClick()
-			time.Sleep(time.Second * 2)
-		}
-
-		// 更新 page 的实例对应的 doc Content
-		pString = page.MustHTML()
-		doc, err = goquery.NewDocumentFromReader(strings.NewReader(pString))
-		if err != nil {
-			return
-		}
-		// 是否有腾讯的防水墙
-		hasWaterWall := false
-		waterWall := doc.Find(TCode)
-		if len(waterWall.Nodes) >= 1 {
-			hasWaterWall = true
-		}
-		s.log.Debugln("Need pass WaterWall", hasWaterWall)
-		// 过墙
-		if hasWaterWall == true {
-			s.passWaterWall(page)
-		}
-		fileByte, fileName, err = getDownloadFile()
-		if err != nil {
-			return
-		}
-		downloadSuccess = true
-	})
-	if err != nil {
-		return nil, err
-	}
-	if downloadSuccess == false {
-		return nil, common.SubHDStep2ExCannotFindDownloadBtn
-	}
-	inSubInfo := supplier.NewSubInfo(s.GetSupplierName(), 1, fileName, language.ChineseSimple, subDownloadPageUrl, 0, 0, filepath.Ext(fileName), fileByte)
-
-	return inSubInfo, nil
-}
-
-func (s *Supplier) passWaterWall(page *rod.Page) {
-
-	const (
-		waterIFrame = "#tcaptcha_iframe"
-		dragBtn     = "#tcaptcha_drag_button"
-		slideBg     = "#slideBg"
-	)
-
-	//等待驗證碼窗體載入
-	page.MustElement(waterIFrame).MustWaitLoad()
-	//進入到iframe
-	iframe := page.MustElement(waterIFrame).MustFrame()
-	// see iframe bug, see  https://github.com/go-rod/rod/issues/548
-	p := page.Browser().MustPageFromTargetID(proto.TargetTargetID(iframe.FrameID))
-
-	//等待拖動條加載, 延遲500秒檢測變化, 以確認加載完畢
-	p.MustElement(dragBtn).MustWaitStable()
-	//等待缺口圖像載入
-	slideBgEl := p.MustElement(slideBg).MustWaitLoad()
-	slideBgEl = slideBgEl.MustWaitStable()
-	//取得帶缺口圖像
-	shadowbg := slideBgEl.MustResource()
-	// 取得原始圖像
-	src := slideBgEl.MustProperty("src")
-	fullbg, _, err := pkg.DownFile(s.log, strings.Replace(src.String(), "img_index=1", "img_index=0", 1))
-	if err != nil {
-		s.log.Errorln("passWaterWall.DownFile", err)
-		return
-	}
-	//取得img展示的真實尺寸
-	shape, err := slideBgEl.Shape()
-	if err != nil {
-		s.log.Errorln("passWaterWall.Shape", err)
-		return
-	}
-	bgbox := shape.Box()
-	height, width := uint(math.Round(bgbox.Height)), uint(math.Round(bgbox.Width))
-	//裁剪圖像
-	shadowbgImg, _ := jpeg.Decode(bytes.NewReader(shadowbg))
-	shadowbgImg = resize.Resize(width, height, shadowbgImg, resize.Lanczos3)
-	fullbgImg, _ := jpeg.Decode(bytes.NewReader(fullbg))
-	fullbgImg = resize.Resize(width, height, fullbgImg, resize.Lanczos3)
-
-	//啓始left,排除干擾部份,所以右移10個像素
-	left := fullbgImg.Bounds().Min.X + 10
-	//啓始top, 排除干擾部份, 所以下移10個像素
-	top := fullbgImg.Bounds().Min.Y + 10
-	//最大left, 排除干擾部份, 所以左移10個像素
-	maxleft := fullbgImg.Bounds().Max.X - 10
-	//最大top, 排除干擾部份, 所以上移10個像素
-	maxtop := fullbgImg.Bounds().Max.Y - 10
-	//rgb比较阈值, 超出此阈值及代表找到缺口位置
-	threshold := 20
-	//缺口偏移, 拖動按鈕初始會偏移27.5
-	distance := -27.5
-	//取絕對值方法
-	abs := func(n int) int {
-		if n < 0 {
-			return -n
-		}
-		return n
-	}
-search:
-	for i := left; i <= maxleft; i++ {
-		for j := top; j <= maxtop; j++ {
-			colorAR, colorAG, colorAB, _ := fullbgImg.At(i, j).RGBA()
-			colorBR, colorBG, colorBB, _ := shadowbgImg.At(i, j).RGBA()
-			colorAR, colorAG, colorAB = colorAR>>8, colorAG>>8, colorAB>>8
-			colorBR, colorBG, colorBB = colorBR>>8, colorBG>>8, colorBB>>8
-			if abs(int(colorAR)-int(colorBR)) > threshold ||
-				abs(int(colorAG)-int(colorBG)) > threshold ||
-				abs(int(colorAB)-int(colorBB)) > threshold {
-				distance += float64(i)
-				s.log.Debugln("對比完畢, 偏移量:", distance)
-				break search
-			}
-		}
-	}
-	//獲取拖動按鈕形狀
-	dragBtnBox := p.MustElement("#tcaptcha_drag_thumb").MustShape().Box()
-	//启用滑鼠功能
-	mouse := p.Mouse
-	//模擬滑鼠移動至拖動按鈕處, 右移3的原因: 拖動按鈕比滑塊圖大3個像素
-	mouse.MustMove(dragBtnBox.X+3, dragBtnBox.Y+(dragBtnBox.Height/2))
-	//按下滑鼠左鍵
-	mouse.MustDown("left")
-	//開始拖動
-	err = mouse.Move(dragBtnBox.X+distance, dragBtnBox.Y+(dragBtnBox.Height/2), 20)
-	if err != nil {
-		s.log.Errorln("mouse.Move", err)
-	}
-	//鬆開滑鼠左鍵, 拖动完毕
-	mouse.MustUp("left")
-
-	if settings.Get().AdvancedSettings.DebugMode == true {
-		//截圖保存
-		page.MustScreenshot(pkg.DefDebugFolder(), "result.png")
-	}
-}
-
-type HdListItem struct {
-	Url        string `json:"url"`
-	BaseUrl    string `json:"baseUrl"`
-	Title      string `json:"title"`
-	Ext        string `json:"ext"`
-	AuthorInfo string `json:"authorInfo"`
-	Lang       string `json:"lang"`
-	Rate       string `json:"rate"`
-	DownCount  int    `json:"downCount"`
-	Season     int    // 第几季,默认-1
-	Episode    int    // 第几集,默认-1
-}
-
-//type HdContent struct {
-//	Filename string `json:"filename"`
-//	Ext      string `json:"ext"`
-//	Data     []byte `json:"data"`
-//}
-
-const TCode = "#TencentCaptcha"
-const btnClickCodeBtn = "button.btn-danger"
-const btnCommitCode = "button.btn-primary"
-const InputCode = "#gzhcode" // id=gzhcode

+ 0 - 154
pkg/logic/sub_supplier/subhd/subhd_test.go

@@ -1,154 +0,0 @@
-package subhd
-
-import (
-	"fmt"
-	"path/filepath"
-	"testing"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/media_info_dealers"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/subtitle_best_api"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	commonValue "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/file_downloader"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/series_helper"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/cache_center"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/log_helper"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/random_auth_key"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/something_static"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/unit_test_helper"
-)
-
-var (
-	authKey random_auth_key.AuthKey
-	dealers *media_info_dealers.Dealers
-)
-
-func defInstance() {
-	pkg.ReadCustomAuthFile(log_helper.GetLogger4Tester())
-	authKey = random_auth_key.AuthKey{
-		BaseKey:  pkg.BaseKey(),
-		AESKey16: pkg.AESKey16(),
-		AESIv16:  pkg.AESIv16(),
-	}
-	dealers = media_info_dealers.NewDealers(log_helper.GetLogger4Tester(),
-		subtitle_best_api.NewSubtitleBestApi(log_helper.GetLogger4Tester(), authKey))
-}
-
-// 无需关注这个测试用例,这个方案暂时弃用
-func TestSupplier_GetSubListFromFile(t *testing.T) {
-
-	//movie1 := "X:\\电影\\The Devil All the Time (2020)\\The Devil All the Time (2020) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\Luca (2021)\\Luca (2021) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\The Boss Baby Family Business (2021)\\The Boss Baby Family Business (2021) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\Oslo (2021)\\Oslo (2021) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\Spiral From the Book of Saw (2021)\\Spiral From the Book of Saw (2021) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\消失爱人 (2016)\\消失爱人 (2016) 720p AAC.rmvb"
-	//movie1 := "X:\\电影\\机动战士Z高达:星之继承者 (2005)\\机动战士Z高达:星之继承者 (2005) 1080p TrueHD.mkv"
-	getCode()
-	defInstance()
-	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
-	movie1 := filepath.Join(rootDir, "zimuku", "movies", "消失爱人 (2016)", "消失爱人 (2016) 720p AAC.rmvb")
-
-	subhd := NewSupplier(file_downloader.NewFileDownloader(cache_center.NewCacheCenter("test", log_helper.GetLogger4Tester()), authKey))
-	outList, err := subhd.getSubListFromFile4Movie(movie1)
-	if err != nil {
-		t.Error(err)
-	}
-	println(outList)
-
-	if len(outList) == 0 {
-		println("now sub found")
-	}
-
-	for i, sublist := range outList {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, sublist.FileUrl, len(sublist.Data))
-	}
-
-	alive, _ := subhd.CheckAlive()
-	if alive == false {
-		t.Fatal("CheckAlive == false")
-	}
-}
-
-// 无需关注这个测试用例,这个方案暂时弃用
-func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
-
-	//ser := "X:\\连续剧\\The Bad Batch"	// tt12708542
-	//ser := "X:\\连续剧\\瑞克和莫蒂 (2013)" //
-	//ser := "X:\\连续剧\\杀死伊芙 (2018)"	// tt7016936
-	//ser := "X:\\连续剧\\Money.Heist"
-	//ser := "X:\\连续剧\\黑钱胜地 (2017)"
-	getCode()
-	defInstance()
-	// 可以指定几集去调试
-	epsMap := make(map[int][]int, 0)
-	epsMap[4] = []int{1}
-	//epsMap[1] = []int{1, 2, 3}
-	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
-	ser := filepath.Join(rootDir, "zimuku", "series", "黄石 (2018)")
-	// 读取本地的视频和字幕信息
-	seriesInfo, err := series_helper.ReadSeriesInfoFromDir(dealers, ser, 90, false, false, epsMap)
-	if err != nil {
-		t.Fatal(err)
-	}
-	s := NewSupplier(file_downloader.NewFileDownloader(cache_center.NewCacheCenter("test", log_helper.GetLogger4Tester()), authKey))
-	outList, err := s.GetSubListFromFile4Series(seriesInfo)
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i, sublist := range outList {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-}
-
-// 无需关注这个测试用例,这个方案暂时弃用
-func TestSupplier_getSubListFromKeyword4Movie(t *testing.T) {
-
-	//imdbID := "tt12708542" // 星球大战:残次品
-	//imdbID := "tt7016936" // 杀死伊芙
-	imdbID := "tt2990738" // 恐怖直播
-	//imdbID := "tt3032476" 	// 风骚律师
-	//imdbID := "tt6468322" 	// 纸钞屋
-	//imdbID := "tt15299712" // 云南虫谷
-	//imdbID := "tt3626476" // Vacation Friends (2021)
-	getCode()
-	defInstance()
-	subhd := NewSupplier(file_downloader.NewFileDownloader(cache_center.NewCacheCenter("test", log_helper.GetLogger4Tester()), authKey))
-	subInfos, err := subhd.getSubListFromKeyword4Movie(imdbID)
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i, sublist := range subInfos {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-}
-
-func getCode() {
-
-	if pkg.ReadCustomAuthFile(log_helper.GetLogger4Tester()) == false {
-		println("read auth file failed")
-		return
-	}
-	fileDownloader := file_downloader.NewFileDownloader(
-		cache_center.NewCacheCenter("local_task_queue", log_helper.GetLogger4Tester()),
-		random_auth_key.AuthKey{
-			BaseKey:  pkg.BaseKey(),
-			AESKey16: pkg.AESKey16(),
-			AESIv16:  pkg.AESIv16(),
-		})
-
-	nowTT := time.Now()
-	nowTimeFileNamePrix := fmt.Sprintf("%d%d%d", nowTT.Year(), nowTT.Month(), nowTT.Day())
-	updateTimeString, code, err := something_static.GetCodeFromWeb(log_helper.GetLogger4Tester(), nowTimeFileNamePrix, fileDownloader)
-	if err != nil {
-		commonValue.SubhdCode = ""
-	} else {
-		commonValue.SubhdCode = code
-	}
-	fmt.Println("UpdateTime", updateTimeString)
-}

BIN
pkg/logic/sub_supplier/zimuku/download_sub_cache/000001.vlog


BIN
pkg/logic/sub_supplier/zimuku/download_sub_cache/00001.mem


BIN
pkg/logic/sub_supplier/zimuku/download_sub_cache/DISCARD


+ 0 - 1
pkg/logic/sub_supplier/zimuku/download_sub_cache/KEYREGISTRY

@@ -1 +0,0 @@
-YùÚGo§ŽÙÕ‡éZ¼>XHello Badger

BIN
pkg/logic/sub_supplier/zimuku/download_sub_cache/MANIFEST


BIN
pkg/logic/sub_supplier/zimuku/task_queue/000001.vlog


BIN
pkg/logic/sub_supplier/zimuku/task_queue/00001.mem


BIN
pkg/logic/sub_supplier/zimuku/task_queue/DISCARD


+ 0 - 1
pkg/logic/sub_supplier/zimuku/task_queue/KEYREGISTRY

@@ -1 +0,0 @@
-güÖhB%ŞNq“öË_$Hello Badger

BIN
pkg/logic/sub_supplier/zimuku/task_queue/MANIFEST


+ 0 - 779
pkg/logic/sub_supplier/zimuku/zimuku.go

@@ -1,779 +0,0 @@
-package zimuku
-
-import (
-	"errors"
-	"fmt"
-	"net/url"
-	"os"
-	"path/filepath"
-	"regexp"
-	"sort"
-	"strings"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/search"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/common"
-	language2 "github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/language"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/series"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/types/supplier"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/rod_helper"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/file_downloader"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/decode"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/language"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/notify_center"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_parser_hub"
-	"github.com/PuerkitoBio/goquery"
-	"github.com/Tnze/go.num/v2/zh"
-	"github.com/go-rod/rod"
-	"github.com/sirupsen/logrus"
-)
-
-type Supplier struct {
-	log            *logrus.Logger
-	fileDownloader *file_downloader.FileDownloader
-	tt             time.Duration
-	isAlive        bool
-}
-
-func NewSupplier(fileDownloader *file_downloader.FileDownloader) *Supplier {
-
-	sup := Supplier{}
-	sup.log = fileDownloader.Log
-	sup.fileDownloader = fileDownloader
-	sup.isAlive = true // 默认是可以使用的,如果 check 后,再调整状态
-
-	if settings.Get().AdvancedSettings.Topic != common.DownloadSubsPerSite {
-		settings.Get().AdvancedSettings.Topic = common.DownloadSubsPerSite
-	}
-
-	// 默认超时是 2 * 60s,如果是调试模式则是 5 min
-	sup.tt = common.BrowserTimeOut
-	if settings.Get().AdvancedSettings.DebugMode == true {
-		sup.tt = common.OneMovieProcessTimeOut
-	}
-	return &sup
-}
-
-func (s *Supplier) CheckAlive() (bool, int64) {
-
-	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-
-	opt := rod_helper.NewBrowserOptions(s.log, true, settings.Get())
-	opt.SetPreLoadUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	browser, err := rod_helper.NewBrowserEx(opt)
-	if err != nil {
-		return false, 0
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	begin := time.Now() //判断代理访问时间
-	_, page, err := rod_helper.HttpGetFromBrowser(browser, settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl, 15*time.Second)
-	if err != nil {
-		return false, 0
-	}
-	_ = page.Close()
-	speed := time.Now().Sub(begin).Nanoseconds() / 1000 / 1000 //ms
-	s.isAlive = true
-	return true, speed
-}
-
-func (s *Supplier) IsAlive() bool {
-	return s.isAlive
-}
-
-func (s *Supplier) OverDailyDownloadLimit() bool {
-
-	return true
-
-	if settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit == 0 {
-		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit is 0, will Skip Download")
-		return true
-	}
-	// 需要查询今天的限额
-	count, err := s.fileDownloader.CacheCenter.DailyDownloadCountGet(s.GetSupplierName(),
-		pkg.GetPublicIP(s.log, settings.Get().AdvancedSettings.TaskQueue))
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "DailyDownloadCountGet", err)
-		return true
-	}
-	if count >= settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit {
-		// 超限了
-		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit:", settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit, "Now Is:", count)
-		return true
-	} else {
-		// 没有超限
-		s.log.Infoln(s.GetSupplierName(), "DailyDownloadLimit:", settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.DailyDownloadLimit, "Now Is:", count)
-		return false
-	}
-}
-
-func (s *Supplier) GetLogger() *logrus.Logger {
-	return s.log
-}
-
-func (s *Supplier) GetSupplierName() string {
-	return common.SubSiteZiMuKu
-}
-
-func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
-
-	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	opt := rod_helper.NewBrowserOptions(s.log, true, settings.Get())
-	opt.SetPreLoadUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	browser, err := rod_helper.NewBrowserEx(opt)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	return s.getSubListFromMovie(browser, filePath)
-}
-
-func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
-
-	defer func() {
-		s.log.Debugln(s.GetSupplierName(), seriesInfo.Name, "End...")
-	}()
-
-	s.log.Debugln(s.GetSupplierName(), seriesInfo.Name, "Start...")
-
-	var err error
-	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	opt := rod_helper.NewBrowserOptions(s.log, true, settings.Get())
-	opt.SetPreLoadUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	browser, err := rod_helper.NewBrowserEx(opt)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-	/*
-		去网站搜索的时候,有个比较由意思的逻辑,有些剧集,哪怕只有一季,sonarr 也会给它命名为 Season 1
-		但是在 zimuku 搜索的时候,如果你加上 XXX 第一季 就搜索不出来,那么目前比较可行的办法是查询两次
-		第一次优先查询 XXX 第一季 ,如果返回的列表是空的,那么再查询 XXX
-	*/
-	// 这里打算牺牲效率,提高代码的复用度,不然后续得维护一套电影的查询逻辑,一套剧集的查询逻辑
-	// 比如,其实可以搜索剧集名称,应该可以得到多个季的列表,然后分析再继续
-	// 现在粗暴点,直接一季搜索一次,跟电影的搜索一样,在首个影片就停止,然后继续往下
-	AllSeasonSubResult := SubResult{}
-	for value := range seriesInfo.NeedDlSeasonDict {
-
-		/*
-			经过网友的测试反馈,每一季 zimuku 是支持这一季的第一集的 IMDB ID 可以搜索到这一季的信息 #253
-			1. 那么在搜索某一集的时候,需要根据这一集去找这一季的第一集,然后读取它的 IMDB ID 信息,然后优先用于搜索这一季的信息
-			2. 如果是搜索季,就直接推算到达季文件夹的位置,搜索所有文件找到第一集,获取它的 IMDB ID
-			是不是有点绕···
-		*/
-		findSeasonFirstEpsIMDBId := ""
-		videoList, err := search.MatchedVideoFile(s.log, seriesInfo.DirPath)
-		if err != nil {
-			s.log.Errorln("GetSubListFromFile4Series.MatchedVideoFile, Season:", value, "Error:", err)
-			continue
-		}
-		for _, oneVideoFPath := range videoList {
-			oneVideoInfo, err := decode.GetVideoNfoInfo4OneSeriesEpisode(oneVideoFPath)
-			if err != nil {
-				s.log.Errorln("GetVideoInfoFromFileName", oneVideoInfo, err)
-				continue
-			}
-			if oneVideoInfo.Season == value && oneVideoInfo.Episode == 1 {
-				// 这一季的第一集
-				findSeasonFirstEpsIMDBId = oneVideoInfo.ImdbId
-				break
-			}
-		}
-
-		filmDetailPageUrl := ""
-		if findSeasonFirstEpsIMDBId != "" {
-			// 第一级界面,找到影片的详情界面
-			// 使用上面得到的这一季第一集的 IMDB ID 进行搜索这一季的信息
-			keyword := findSeasonFirstEpsIMDBId
-			s.log.Debugln(s.GetSupplierName(), "step 0", "1 times", "keyword:", keyword)
-			filmDetailPageUrl, err = s.step0(browser, keyword)
-			if err != nil {
-				s.log.Errorln(s.GetSupplierName(), "step 0", "0 times", "keyword:", keyword, err)
-				// 如果只是搜索不到,则继续换关键词
-				if err != common.ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound {
-					s.log.Errorln(s.GetSupplierName(), "ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound", keyword, err)
-					continue
-				}
-			}
-		}
-		// 如果上面找到了,那么 filmDetailPageUrl 就应该不为空,如果没有找到就是空
-		if filmDetailPageUrl == "" {
-			// 第一级界面,找到影片的详情界面
-			keyword := seriesInfo.Name + " 第" + zh.Uint64(value).String() + "季"
-			s.log.Debugln(s.GetSupplierName(), "step 0", "0 times", "keyword:", keyword)
-			filmDetailPageUrl, err = s.step0(browser, keyword)
-			if err != nil {
-				s.log.Errorln(s.GetSupplierName(), "step 0", "0 times", "keyword:", keyword, err)
-				// 如果只是搜索不到,则继续换关键词
-				if err != common.ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound {
-					s.log.Errorln(s.GetSupplierName(), "ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound", keyword, err)
-					continue
-				}
-
-				// 直接更换为这个剧目的 Name 的搜索,不带季度关键词信息
-				keyword = seriesInfo.Name
-				s.log.Debugln(s.GetSupplierName(), "step 0", "1 times", "keyword:", keyword)
-				filmDetailPageUrl, err = s.step0(browser, keyword)
-				if err != nil {
-					s.log.Errorln(s.GetSupplierName(), "1 times", "keyword:", keyword, err)
-					continue
-				}
-			}
-		}
-
-		// 第二级界面,有多少个字幕
-		s.log.Debugln(s.GetSupplierName(), "step 1", filmDetailPageUrl)
-		subResult, err := s.step1(browser, filmDetailPageUrl)
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), "step 1", filmDetailPageUrl, err)
-			continue
-		}
-
-		if AllSeasonSubResult.Title == "" {
-			AllSeasonSubResult = subResult
-		} else {
-			AllSeasonSubResult.SubInfos = append(AllSeasonSubResult.SubInfos, subResult.SubInfos...)
-		}
-	}
-	// 找到最大的优先级的字幕下载
-	sort.Sort(SortByPriority{AllSeasonSubResult.SubInfos})
-	// 找到那些 Eps 需要下载字幕的
-	subInfoNeedDownload := s.whichEpisodeNeedDownloadSub(seriesInfo, AllSeasonSubResult)
-	// 剩下的部分跟 GetSubListFroKeyword 一样,就是去下载了
-	outSubInfoList := s.whichSubInfoNeedDownload(browser, subInfoNeedDownload, err)
-
-	// 返回前,需要把每一个 Eps 的 Season Episode 信息填充到每个 SubInfo 中
-	return outSubInfoList, nil
-}
-
-func (s *Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
-	panic("not implemented")
-}
-
-func (s *Supplier) getSubListFromMovie(browser *rod.Browser, fileFPath string) ([]supplier.SubInfo, error) {
-
-	defer func() {
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "End...")
-	}()
-
-	s.log.Debugln(s.GetSupplierName(), fileFPath, "Start...")
-	/*
-		虽然是传入视频文件路径,但是其实需要读取对应的视频文件目录下的
-		movie.xml 以及 *.nfo,找到 IMDB id
-		优先通过 IMDB id 去查找字幕
-		如果找不到,再靠文件名提取影片名称去查找
-	*/
-	// 找到这个视频文件,尝试得到 IMDB ID
-	// 目前测试来看,加入 年 这个关键词去搜索,对 2020 年后的影片有利,因为网站有统一的详细页面了,而之前的,没有,会影响识别
-	// 所以,year >= 2020 年,则可以多加一个关键词(年)去搜索影片
-	imdbInfo, err := decode.GetVideoNfoInfo4Movie(fileFPath)
-	if err != nil {
-		// 允许的错误,跳过,继续进行文件名的搜索
-		s.log.Errorln("model.GetImdbInfo", err)
-	} else {
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "GetVideoNfoInfo4Movie -> Title:", imdbInfo.Title)
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "GetVideoNfoInfo4Movie -> OriginalTitle:", imdbInfo.OriginalTitle)
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "GetVideoNfoInfo4Movie -> Year:", imdbInfo.Year)
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "GetVideoNfoInfo4Movie -> ImdbId:", imdbInfo.ImdbId)
-	}
-
-	var subInfoList []supplier.SubInfo
-
-	if imdbInfo.ImdbId != "" {
-		// 先用 imdb id 找
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "getSubListFromKeyword -> Search By IMDB ID:", imdbInfo.ImdbId)
-		subInfoList, err = s.getSubListFromKeyword(browser, imdbInfo.ImdbId)
-		if err != nil {
-			// 允许的错误,跳过,继续进行文件名的搜索
-			s.log.Errorln(s.GetSupplierName(), "keyword:", imdbInfo.ImdbId)
-			s.log.Errorln("getSubListFromKeyword", "IMDBID can not found sub", fileFPath, err)
-		}
-
-		s.log.Debugln(s.GetSupplierName(), fileFPath, "getSubListFromKeyword -> Search By IMDB ID, subInfoList Count:", len(subInfoList))
-		// 如果有就优先返回
-		if len(subInfoList) > 0 {
-			return subInfoList, nil
-		}
-	}
-	// 如果没有,那么就用文件名查找
-	searchKeyword := search.VideoNameSearchKeywordMaker(s.log, imdbInfo.Title, imdbInfo.Year)
-
-	s.log.Debugln(s.GetSupplierName(), fileFPath, "VideoNameSearchKeywordMaker Keyword:", searchKeyword)
-
-	subInfoList, err = s.getSubListFromKeyword(browser, searchKeyword)
-	if err != nil {
-		s.log.Errorln(s.GetSupplierName(), "keyword:", searchKeyword)
-		return nil, err
-	}
-
-	s.log.Debugln(s.GetSupplierName(), fileFPath, "getSubListFromKeyword -> Search By Keyword, subInfoList Count:", len(subInfoList))
-	return subInfoList, nil
-}
-
-// getSubListFromKeyword 目前是给电影使用的,搜索返回的字幕列表可能很多,需要挑选一下,比如 Top 1 下来就好了
-func (s *Supplier) getSubListFromKeyword(browser *rod.Browser, keyword string) ([]supplier.SubInfo, error) {
-
-	s.log.Infoln("Search Keyword:", keyword)
-	var outSubInfoList []supplier.SubInfo
-	// 第一级界面,找到影片的详情界面
-	filmDetailPageUrl, err := s.step0(browser, keyword)
-	if err != nil {
-		return nil, err
-	}
-	s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step0 -> filmDetailPageUrl:", filmDetailPageUrl)
-	// 第二级界面,有多少个字幕
-	subResult, err := s.step1(browser, filmDetailPageUrl)
-	if err != nil {
-		return nil, err
-	}
-	// 第三级界面,单个字幕详情
-	// 找到最大的优先级的字幕下载
-	sort.Sort(SortByPriority{subResult.SubInfos})
-
-	// 强制把找到的列表缩少到 Top 5
-	subResult.SubInfos = subResult.SubInfos[:5]
-
-	s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> subResult.Title:", subResult.Title)
-	s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> subResult.OtherName:", subResult.OtherName)
-	for i, info := range subResult.SubInfos {
-		s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> info.Name", i, info.Name)
-		s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> info.DownloadUrl:", i, info.DownloadUrl)
-		s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> info.DetailUrl:", i, info.DetailUrl)
-		s.log.Debugln(s.GetSupplierName(), "getSubListFromKeyword -> step1 -> info.DownloadTimes:", i, info.DownloadTimes)
-	}
-
-	outSubInfoList = s.whichSubInfoNeedDownload(browser, subResult.SubInfos, err)
-
-	return outSubInfoList, nil
-}
-
-func (s *Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, AllSeasonSubResult SubResult) []SubInfo {
-	// 字幕很多,考虑效率,需要做成字典
-	// key SxEx - SubInfos
-	var allSubDict = make(map[string]SubInfos)
-	// 全季的字幕列表
-	var oneSeasonSubDict = make(map[string]SubInfos)
-	for _, subInfo := range AllSeasonSubResult.SubInfos {
-		_, season, episode, err := decode.GetSeasonAndEpisodeFromSubFileName(subInfo.Name)
-		if err != nil {
-			s.log.Errorln("whichEpisodeNeedDownloadSub.GetVideoInfoFromFileFullPath", subInfo.Name, err)
-			continue
-		}
-		subInfo.Season = season
-		subInfo.Episode = episode
-		epsKey := pkg.GetEpisodeKeyName(season, episode)
-		_, ok := allSubDict[epsKey]
-		if ok == false {
-			// 初始化
-			allSubDict[epsKey] = SubInfos{}
-			if season != 0 && episode == 0 {
-				oneSeasonSubDict[epsKey] = SubInfos{}
-			}
-		}
-		// 添加
-		allSubDict[epsKey] = append(allSubDict[epsKey], subInfo)
-		if season != 0 && episode == 0 {
-			oneSeasonSubDict[epsKey] = append(oneSeasonSubDict[epsKey], subInfo)
-		}
-	}
-	// 本地的视频列表,找到没有字幕的
-	// 需要进行下载字幕的列表
-	var subInfoNeedDownload = make([]SubInfo, 0)
-	// 有那些 Eps 需要下载的,按 SxEx 反回 epsKey
-	for epsKey, epsInfo := range seriesInfo.NeedDlEpsKeyList {
-		// 从一堆字幕里面找合适的
-		value, ok := allSubDict[epsKey]
-		// 是否有
-		if ok == true && len(value) > 0 {
-			value[0].Season = epsInfo.Season
-			value[0].Episode = epsInfo.Episode
-			subInfoNeedDownload = append(subInfoNeedDownload, value[0])
-		}
-	}
-	// 全季的字幕列表,也拼进去,后面进行下载
-	for _, infos := range oneSeasonSubDict {
-		if len(infos) < 1 {
-			continue
-		}
-		subInfoNeedDownload = append(subInfoNeedDownload, infos[0])
-	}
-
-	// 返回前,需要把每一个 Eps 的 Season Episode 信息填充到每个 SubInfo 中
-	return subInfoNeedDownload
-}
-
-func (s *Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInfos, err error) []supplier.SubInfo {
-
-	var outSubInfoList = make([]supplier.SubInfo, 0)
-	for i := range subInfos {
-
-		err = s.step2(browser, &subInfos[i])
-		if err != nil {
-			s.log.Error(s.GetSupplierName(), "step 2", subInfos[i].Name, err)
-			continue
-		}
-		s.log.Debugln(s.GetSupplierName(), "whichSubInfoNeedDownload -> step2 -> info.SubDownloadPageUrl:", i, subInfos[i].SubDownloadPageUrl)
-	}
-
-	// TODO 这里需要考虑,可以设置为高级选项,不够就用 unknow 来补充
-	// 首先过滤出中文的字幕,同时需要满足是支持的字幕
-	var tmpSubInfo = make([]SubInfo, 0)
-	for _, subInfo := range subInfos {
-		tmpLang := language.LangConverter4Sub_Supplier(subInfo.Lang)
-		if language.HasChineseLang(tmpLang) == true && sub_parser_hub.IsSubTypeWanted(subInfo.Ext) == true {
-			tmpSubInfo = append(tmpSubInfo, subInfo)
-		}
-	}
-
-	// 看字幕够不够
-	if len(tmpSubInfo) < settings.Get().AdvancedSettings.Topic {
-		for _, subInfo := range subInfos {
-			if len(tmpSubInfo) >= settings.Get().AdvancedSettings.Topic {
-				break
-			}
-			tmpLang := language.LangConverter4Sub_Supplier(subInfo.Lang)
-			if language.HasChineseLang(tmpLang) == false {
-				tmpSubInfo = append(tmpSubInfo, subInfo)
-			}
-		}
-	}
-
-	s.log.Debugln(s.GetSupplierName(), "step2 -> tmpSubInfo.Count", len(tmpSubInfo))
-	for i, info := range tmpSubInfo {
-
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.Name:", i, info.Name)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DownloadUrl:", i, info.DownloadUrl)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DetailUrl:", i, info.DetailUrl)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DownloadTimes:", i, info.DownloadTimes)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.SubDownloadPageUrl:", i, info.SubDownloadPageUrl)
-	}
-
-	// 看字幕是不是太多了,超出 topic 的限制了
-	if len(tmpSubInfo) > settings.Get().AdvancedSettings.Topic {
-		tmpSubInfo = tmpSubInfo[:settings.Get().AdvancedSettings.Topic]
-	}
-	s.log.Debugln(s.GetSupplierName(), "step2 -> tmpSubInfo.Count with topic limit", len(tmpSubInfo))
-	for i, info := range tmpSubInfo {
-
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.Name:", i, info.Name)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DownloadUrl:", i, info.DownloadUrl)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DetailUrl:", i, info.DetailUrl)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.DownloadTimes:", i, info.DownloadTimes)
-		s.log.Debugln(s.GetSupplierName(), "ChineseSubs -> tmpSubInfo.SubDownloadPageUrl:", i, info.SubDownloadPageUrl)
-	}
-
-	// 第四级界面,具体字幕下载
-	for i, subInfo := range tmpSubInfo {
-
-		s.log.Debugln(s.GetSupplierName(), "GetEx:", i, subInfo.SubDownloadPageUrl)
-
-		getSubInfo, err := s.fileDownloader.GetEx(s.GetSupplierName(), browser, subInfo.SubDownloadPageUrl, int64(i), subInfo.Season, subInfo.Episode, s.DownFile)
-		if err != nil {
-			s.log.Errorln(s.GetSupplierName(), "GetEx", "GetEx", subInfo.Name, subInfo.Season, subInfo.Episode, err)
-			continue
-		}
-
-		outSubInfoList = append(outSubInfoList, *getSubInfo)
-	}
-
-	for i, info := range outSubInfoList {
-		s.log.Debugln(s.GetSupplierName(), "DownFile -> Downloaded File Info", i, "FileName:", info.Name, "FileUrl:", info.FileUrl)
-	}
-
-	// 返回前,需要把每一个 Eps 的 Season Episode 信息填充到每个 SubInfo 中
-	return outSubInfoList
-}
-
-// step0 先在查询界面找到字幕对应第一个影片的详情界面,需要解决自定义错误 ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound
-func (s *Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("zimuku_step0", err.Error())
-		}
-	}()
-
-	desUrl := fmt.Sprintf(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl+common.SubZiMuKuSearchFormatUrl, url.QueryEscape(keyword))
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, desUrl, s.tt)
-	if err != nil {
-		return "", err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	// 找到对应影片的详情界面
-	re := regexp.MustCompile(`<p\s+class="tt\s+clearfix"><a\s+href="(/subs/[\w]+\.html)"\s+target="_blank"><b>(.*?)</b></a></p>`)
-	matched := re.FindAllStringSubmatch(result, -1)
-	if matched == nil || len(matched) < 1 {
-		return "", common.ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound
-	}
-	// 影片的详情界面 url
-	filmDetailPageUrl := matched[0][1]
-	return filmDetailPageUrl, nil
-}
-
-// step1 分析详情界面,找到有多少个字幕
-func (s *Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResult, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("zimuku_step1", err.Error())
-		}
-	}()
-
-	var subResult SubResult
-	subResult.SubInfos = SubInfos{}
-
-	filmDetailPageUrl = pkg.AddBaseUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl, filmDetailPageUrl)
-
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, filmDetailPageUrl, s.tt)
-	if err != nil {
-		return subResult, err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	doc, err := goquery.NewDocumentFromReader(strings.NewReader(result))
-	if err != nil {
-		return SubResult{}, err
-	}
-
-	counterIndex := 3
-	// 先找到页面”下载“关键词是第几列,然后下面的下载量才能正确的解析。否则,电影是[3],而在剧集中,因为多了字幕组的筛选,则为[4]
-	doc.Find("#subtb thead tr th").Each(func(i int, th *goquery.Selection) {
-		if th.Text() == "下载" {
-			counterIndex = i
-		}
-	})
-
-	doc.Find("#subtb tbody tr").Each(func(i int, tr *goquery.Selection) {
-		// 字幕下载页面地址
-		href, exists := tr.Find("a").Attr("href")
-		if !exists {
-			return
-		}
-		// 标题
-		title, exists := tr.Find("a").Attr("title")
-		if !exists {
-			return
-		}
-		// 扩展名
-		ext := tr.Find(".label-info").Text()
-		// 作者信息
-		authorInfos := tr.Find(".gray")
-		authorInfo := ""
-		authorInfos.Each(func(a_i int, a_lb *goquery.Selection) {
-			authorInfo += a_lb.Text() + ","
-		})
-		authorInfoLen := len(authorInfo)
-		if authorInfoLen > 0 {
-			authorInfo = authorInfo[0 : authorInfoLen-3]
-		}
-		// 语言
-		lang, exists := tr.Find("img").First().Attr("alt")
-		if !exists {
-			lang = ""
-		}
-		// 投票
-		rate, exists := tr.Find(".rating-star").First().Attr("data-original-title")
-		if !exists {
-			rate = ""
-		}
-		vote, err := decode.GetNumber2Float(rate)
-		if err != nil {
-			return
-		}
-		// 下载次数统计
-		downCountNub := 0
-		downCount := tr.Find("td").Eq(counterIndex).Text()
-		if strings.Contains(downCount, "万") {
-			fNumb, err := decode.GetNumber2Float(downCount)
-			if err != nil {
-				return
-			}
-			downCountNub = int(fNumb * 10000)
-		} else {
-			downCountNub, err = decode.GetNumber2int(downCount)
-			if err != nil {
-				return
-			}
-		}
-
-		var subInfo SubInfo
-		subResult.Title = title
-		subInfo.Name = title
-		subInfo.DetailUrl = href
-		subInfo.Ext = ext
-		subInfo.AuthorInfo = authorInfo
-		subInfo.Lang = lang
-		subInfo.DownloadTimes = downCountNub
-
-		subInfo.Score = vote
-		// 计算优先级
-		subInfo.Priority = subInfo.Score * float32(subInfo.DownloadTimes)
-
-		subResult.SubInfos = append(subResult.SubInfos, subInfo)
-	})
-	return subResult, nil
-}
-
-// step2 第二级界面,单个字幕详情,需要判断 ZiMuKuDownloadUrlStep2NotFound 这个自定义错误
-func (s *Supplier) step2(browser *rod.Browser, subInfo *SubInfo) error {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("zimuku_step2", err.Error())
-		}
-	}()
-	detailUrl := pkg.AddBaseUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl, subInfo.DetailUrl)
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailUrl, s.tt)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	// 找到下载地址
-	re := regexp.MustCompile(`<a\s+id="down1"\s+href="([^"]*/dld/[\w]+\.html)"`)
-	matched := re.FindAllStringSubmatch(result, -1)
-	if matched == nil || len(matched) == 0 || len(matched[0]) == 0 {
-		s.log.Warnln("Step2,sub download url not found", detailUrl)
-		return common.ZiMuKuDownloadUrlStep2NotFound
-	}
-	if strings.Contains(matched[0][1], "://") {
-		subInfo.SubDownloadPageUrl = matched[0][1]
-	} else {
-		subInfo.SubDownloadPageUrl = fmt.Sprintf("%s%s", settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl, matched[0][1])
-	}
-	return nil
-}
-
-// DownFile 第三级界面,具体字幕下载 ZiMuKuDownloadUrlStep3NotFound ZiMuKuDownloadUrlDownFileFailed
-func (s *Supplier) DownFile(browser *rod.Browser, subDownloadPageUrl string, TopN int64, Season, Episode int) (*supplier.SubInfo, error) {
-	var err error
-	defer func() {
-		if err != nil {
-			notify_center.Notify.Add("zimuku_DownFile", err.Error())
-		}
-	}()
-	subDownloadPageFullUrl := pkg.AddBaseUrl(settings.Get().AdvancedSettings.SuppliersSettings.Zimuku.RootUrl, subDownloadPageUrl)
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageFullUrl, s.tt)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-	re := regexp.MustCompile(`<li><a\s+rel="nofollow"\s+href="([^"]*/download/[^"]+)"`)
-	matched := re.FindAllStringSubmatch(result, -1)
-	if matched == nil || len(matched) == 0 || len(matched[0]) == 0 {
-		s.log.Debugln("Step3,sub download url not found", subDownloadPageFullUrl)
-		return nil, common.ZiMuKuDownloadUrlStep3NotFound
-	}
-
-	fileName := ""
-	fileByte := []byte{0}
-	downloadSuccess := false
-	err = rod.Try(func() {
-		tmpDir := filepath.Join(pkg.DefTmpFolder(), "downloads")
-		wait := browser.Timeout(30 * time.Second).WaitDownload(tmpDir)
-		getDownloadFile := func() ([]byte, string, error) {
-			info := wait()
-			if info == nil {
-				return nil, "", errors.New("download sub timeout")
-			}
-			downloadPath := filepath.Join(tmpDir, info.GUID)
-			defer func() { _ = os.Remove(downloadPath) }()
-			b, err := os.ReadFile(downloadPath)
-			if err != nil {
-				return nil, "", err
-			}
-			return b, info.SuggestedFilename, nil
-		}
-		// 初始化页面用于查询元素
-		element := page.MustElement(btnClickDownload)
-		// 直接可以下载
-		element.MustClick()
-		fileByte, fileName, err = getDownloadFile()
-		if err != nil {
-			return
-		}
-
-		downloadSuccess = true
-	})
-	if err != nil {
-		s.log.Errorln("ZiMuKu DownFile DownloadFile", err)
-		return nil, err
-	}
-	if downloadSuccess == true {
-		s.log.Debugln("Step3,DownFile, FileName:", fileName, "DataLen:", len(fileByte))
-
-		inSubInfo := supplier.NewSubInfo(s.GetSupplierName(), 1, fileName, language2.ChineseSimple,
-			subDownloadPageUrl, 0, 0, filepath.Ext(fileName), fileByte)
-
-		inSubInfo.TopN = TopN
-		inSubInfo.Season = Season
-		inSubInfo.Episode = Episode
-
-		return inSubInfo, nil
-	} else {
-		s.log.Debugln("Step3,sub download url not found", subDownloadPageFullUrl)
-		return nil, common.ZiMuKuDownloadUrlDownFileFailed
-	}
-}
-
-type SubResult struct {
-	Title     string   // 字幕的标题
-	OtherName string   // 影片又名
-	SubInfos  SubInfos // 字幕的列表
-}
-
-type SubInfo struct {
-	Name               string  // 字幕的名称
-	Lang               string  // 语言
-	AuthorInfo         string  // 作者
-	Ext                string  // 后缀名
-	Score              float32 // 评分
-	DownloadTimes      int     // 下载的次数
-	Priority           float32 // 优先级,使用评分和次数乘积而来,类似于 Score 投票
-	DetailUrl          string  // 字幕的详情界面,需要再次分析具体的下载地址,地址需要拼接网站的根地址上去
-	SubDownloadPageUrl string  // 字幕的具体的下载页面,会有多个下载可用的链接
-	DownloadUrl        string  // 字幕的下载地址
-	Season             int     // 第几季,默认-1
-	Episode            int     // 第几集,默认-1
-}
-
-// SubInfos 实现自定义排序
-type SubInfos []SubInfo
-
-func (s SubInfos) Len() int {
-	return len(s)
-}
-func (s SubInfos) Less(i, j int) bool {
-	return s[i].Priority > s[j].Priority
-}
-func (s SubInfos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-type SortByPriority struct{ SubInfos }
-
-// Less 根据元素的优先级降序排序
-func (s SortByPriority) Less(i, j int) bool {
-	return s.SubInfos[i].Priority > s.SubInfos[j].Priority
-}
-
-const btnClickDownload = "a.btn-danger"

+ 0 - 197
pkg/logic/sub_supplier/zimuku/zimuku_test.go

@@ -1,197 +0,0 @@
-package zimuku
-
-import (
-	"path/filepath"
-	"testing"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/media_info_dealers"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/subtitle_best_api"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/rod_helper"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/cache_center"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/log_helper"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/file_downloader"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/series_helper"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/random_auth_key"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_helper"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/unit_test_helper"
-)
-
-func TestSupplier_GetSubListFromKeyword(t *testing.T) {
-
-	defInstance()
-	browser, err := rod_helper.NewBrowserBase(log_helper.GetLogger4Tester(), "", "", true, settings.NewSettings(pkg.ConfigRootDirFPath()).AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	//imdbId1 := "tt3228774"
-	videoName := "黑白魔女库伊拉"
-	outList, err := zimukuInstance.getSubListFromKeyword(browser, videoName)
-	if err != nil {
-		t.Error(err)
-	}
-	println(outList)
-	for i, sublist := range outList {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-}
-
-func TestSupplier_GetSubListFromFile(t *testing.T) {
-
-	opt := rod_helper.NewBrowserOptions(log_helper.GetLogger4Tester(), true, settings.NewSettings(pkg.ConfigRootDirFPath()))
-	opt.SetPreLoadUrl(settings.NewSettings(pkg.ConfigRootDirFPath()).AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	browser, err := rod_helper.NewBrowserEx(opt)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	//movie1 := "X:\\电影\\The Devil All the Time (2020)\\The Devil All the Time (2020) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\龙猫 (1988)\\龙猫 (1988) 1080p DTS.mkv"
-	//movie1 := "X:\\电影\\消失爱人 (2016)\\消失爱人 (2016) 720p AAC.rmvb"
-	//movie1 := "X:\\电影\\Spiral From the Book of Saw (2021)\\Spiral From the Book of Saw (2021) WEBDL-1080p.mkv"
-	//movie1 := "X:\\电影\\机动战士Z高达:星之继承者 (2005)\\机动战士Z高达:星之继承者 (2005) 1080p TrueHD.mkv"
-	//movie1 := "X:\\连续剧\\The Bad Batch\\Season 1\\The Bad Batch - S01E01 - Aftermath WEBDL-1080p.mkv"
-
-	defInstance()
-	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
-	movie1 := filepath.Join(rootDir, "zimuku", "movies", "The Devil All the Time (2020)", "The Devil All the Time (2020) WEBDL-1080p.mkv")
-	outList, err := zimukuInstance.getSubListFromMovie(browser, movie1)
-	if err != nil {
-		t.Error(err)
-	}
-	println(outList)
-	for i, sublist := range outList {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-}
-
-func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
-
-	//ser := "X:\\连续剧\\The Bad Batch" // tt12708542
-	//ser := "X:\\连续剧\\杀死伊芙 (2018)"	// tt12708542
-	//ser := "X:\\连续剧\\Money.Heist"
-	//ser := "X:\\连续剧\\黄石 (2018)"
-
-	// 可以指定几集去调试
-	epsMap := make(map[int][]int, 0)
-	epsMap[4] = []int{1}
-	//epsMap[1] = []int{1, 2, 3}
-
-	rootDir := unit_test_helper.GetTestDataResourceRootPath([]string{"sub_spplier"}, 5, true)
-	ser := filepath.Join(rootDir, "zimuku", "series", "黄石 (2018)")
-	// 读取本地的视频和字幕信息
-	seriesInfo, err := series_helper.ReadSeriesInfoFromDir(dealers,
-		ser,
-		90,
-		false,
-		false,
-		epsMap)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	defInstance()
-	outList, err := zimukuInstance.GetSubListFromFile4Series(seriesInfo)
-	if err != nil {
-		t.Fatal(err)
-	}
-	println(outList)
-	for i, sublist := range outList {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-
-	organizeSubFiles, err := sub_helper.OrganizeDlSubFiles(log_helper.GetLogger4Tester(), filepath.Base(seriesInfo.DirPath), outList, false)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	for s2, strings := range organizeSubFiles {
-		println(s2, strings)
-	}
-}
-
-func TestSupplier_getSubListFromKeyword(t *testing.T) {
-
-	opt := rod_helper.NewBrowserOptions(log_helper.GetLogger4Tester(), true, settings.NewSettings(pkg.ConfigRootDirFPath()))
-	opt.SetPreLoadUrl(settings.NewSettings(pkg.ConfigRootDirFPath()).AdvancedSettings.SuppliersSettings.Zimuku.RootUrl)
-	browser, err := rod_helper.NewBrowserEx(opt)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	//imdbID := "tt12708542" // 星球大战:残次品
-	//imdbID := "tt7016936" // 杀死伊芙
-	//imdbID := "tt2990738" // 恐怖直播
-	//imdbID := "tt3032476" 	// 风骚律师
-	//imdbID := "tt6468322" 	// 纸钞屋
-	//imdbID := "tt15299712" // 云南虫谷
-	//imdbID := "tt3626476"  // Vacation Friends (2021)
-	imdbID := "tt11192306" // Superman.and.Lois
-
-	defInstance()
-	subInfos, err := zimukuInstance.getSubListFromKeyword(browser, imdbID)
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i, sublist := range subInfos {
-		println(i, sublist.Name, sublist.Ext, sublist.Language.String(), sublist.Score, len(sublist.Data))
-	}
-}
-
-func TestSupplier_step3(t *testing.T) {
-	// 调试用,不作为单元测试的一个考核,因为可能不可控
-	//dlUrl := "https://zmk.pw/dld/162150.html"
-	//s := Supplier{}
-	//fileName, datas, err := s.DownFile(dlUrl)
-	//if err != nil {
-	//	t.Fatal(err)
-	//}
-	//
-	//println(fileName)
-	//println(len(datas))
-}
-
-func TestSupplier_CheckAlive(t *testing.T) {
-
-	defInstance()
-	alive, _ := zimukuInstance.CheckAlive()
-	if alive == false {
-		t.Fatal("CheckAlive == false")
-	}
-}
-
-var (
-	zimukuInstance *Supplier
-	dealers        *media_info_dealers.Dealers
-)
-
-func defInstance() {
-
-	pkg.ReadCustomAuthFile(log_helper.GetLogger4Tester())
-
-	authKey := random_auth_key.AuthKey{
-		BaseKey:  pkg.BaseKey(),
-		AESKey16: pkg.AESKey16(),
-		AESIv16:  pkg.AESIv16(),
-	}
-
-	zimukuInstance = NewSupplier(file_downloader.NewFileDownloader(
-		cache_center.NewCacheCenter("test", log_helper.GetLogger4Tester()), authKey))
-
-	dealers = media_info_dealers.NewDealers(log_helper.GetLogger4Tester(),
-		subtitle_best_api.NewSubtitleBestApi(log_helper.GetLogger4Tester(), authKey))
-}

BIN
pkg/rod_helper/assets/adblock_4_43_0_0.zip


+ 0 - 154
pkg/rod_helper/multi_browser.go

@@ -1,154 +0,0 @@
-package rod_helper
-
-import (
-	_ "embed"
-	"errors"
-	"fmt"
-	"strconv"
-	"sync"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/sirupsen/logrus"
-
-	"github.com/go-rod/rod"
-)
-
-type Browser struct {
-	log             *logrus.Logger
-	rodOptions      *BrowserOptions // 参数
-	multiBrowser    []*rod.Browser  // 多浏览器实例
-	browserIndex    int             // 当前使用的浏览器的索引
-	browserLocker   sync.Mutex      // 浏览器的锁
-	httpProxyIndex  int             // 当前使用的 http 代理的索引
-	httpProxyLocker sync.Mutex      // http 代理的锁
-	LbHttpUrl       string          // 负载均衡的 http proxy url
-	LBPort          int             //负载均衡 http 端口
-	httpProxyUrls   []string        // XrayPool 中的代理信息
-	socksProxyUrls  []string        // XrayPool 中的代理信息
-}
-
-// NewMultiBrowser 面向与爬虫的时候使用 Browser
-func NewMultiBrowser(browserOptions *BrowserOptions) *Browser {
-
-	// 从配置中,判断 XrayPool 是否启动
-	if browserOptions.XrayPoolUrl() == "" {
-		browserOptions.Log.Errorf("XrayPoolUrl is empty")
-		return nil
-	}
-	if browserOptions.XrayPoolPort() == "" {
-		browserOptions.Log.Errorf("XrayPoolPort is empty")
-		return nil
-	}
-	// 尝试从本地的 XrayPoolUrl 获取 代理信息
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		browserOptions.Log.Error(errors.New("NewHttpClient error:" + err.Error()))
-		return nil
-	}
-
-	var proxyResult ProxyResult
-	_, err = httpClient.R().
-		SetResult(&proxyResult).
-		Get(httpPrefix +
-			browserOptions.XrayPoolUrl() +
-			":" +
-			browserOptions.XrayPoolPort() +
-			"/v1/proxy_list")
-	if err != nil {
-		browserOptions.Log.Error(errors.New("Get error:" + err.Error()))
-		return nil
-	}
-
-	if proxyResult.Status == "stopped" || len(proxyResult.OpenResultList) == 0 {
-		browserOptions.Log.Error("XrayPool Not Started!")
-		return nil
-	}
-
-	b := &Browser{
-		log:          browserOptions.Log,
-		rodOptions:   browserOptions,
-		multiBrowser: make([]*rod.Browser, 0),
-	}
-
-	for _, result := range proxyResult.OpenResultList {
-		b.httpProxyUrls = append(b.httpProxyUrls, httpPrefix+browserOptions.XrayPoolUrl()+":"+strconv.Itoa(result.HttpPort))
-		b.socksProxyUrls = append(b.socksProxyUrls, socksPrefix+browserOptions.XrayPoolUrl()+":"+strconv.Itoa(result.SocksPort))
-	}
-	b.LBPort = proxyResult.LbPort
-
-	b.LbHttpUrl = fmt.Sprintf(httpPrefix + browserOptions.XrayPoolUrl() + ":" + strconv.Itoa(b.LBPort))
-	for i := 0; i < browserOptions.BrowserInstanceCount(); i++ {
-
-		oneBrowser, err := NewBrowserBase(b.log, "", b.LbHttpUrl, browserOptions.LoadAdblock)
-		if err != nil {
-			b.log.Error(errors.New("NewBrowserBase error:" + err.Error()))
-			return nil
-		}
-		b.multiBrowser = append(b.multiBrowser, oneBrowser)
-	}
-
-	return b
-}
-
-// GetLBBrowser 这里获取到的 Browser 使用的代理是负载均衡的代理
-func (b *Browser) GetLBBrowser() *rod.Browser {
-
-	b.browserLocker.Lock()
-	defer func() {
-		b.browserIndex++
-		b.browserLocker.Unlock()
-	}()
-
-	if b.browserIndex >= len(b.multiBrowser) {
-		b.browserIndex = 0
-	}
-
-	return b.multiBrowser[b.browserIndex]
-}
-
-// NewBrowser 每次新建一个 Browser ,使用 HttpProxy 列表中的一个作为代理
-func (b *Browser) NewBrowser() (*rod.Browser, error) {
-
-	b.httpProxyLocker.Lock()
-	defer func() {
-		b.httpProxyIndex++
-		b.httpProxyLocker.Unlock()
-	}()
-
-	if b.httpProxyIndex >= len(b.httpProxyUrls) {
-		b.httpProxyIndex = 0
-	}
-
-	oneBrowser, err := NewBrowserBase(b.log, "", b.httpProxyUrls[b.httpProxyIndex], b.rodOptions.LoadAdblock)
-	if err != nil {
-		return nil, errors.New("NewBrowser.NewBrowserBase error:" + err.Error())
-	}
-
-	return oneBrowser, nil
-}
-
-func (b *Browser) Close() {
-
-	for _, oneBrowser := range b.multiBrowser {
-		oneBrowser.Close()
-	}
-
-	b.multiBrowser = make([]*rod.Browser, 0)
-}
-
-type ProxyResult struct {
-	Status         string `json:"status"`
-	LbPort         int    `json:"lb_port"`
-	OpenResultList []struct {
-		Name       string `json:"name"`
-		ProtoModel string `json:"proto_model"`
-		SocksPort  int    `json:"socks_port"`
-		HttpPort   int    `json:"http_port"`
-	} `json:"open_result_list"`
-}
-
-const (
-	httpPrefix  = "http://"
-	socksPrefix = "socks5://"
-)

+ 0 - 27
pkg/rod_helper/multi_browser_test.go

@@ -1,27 +0,0 @@
-package rod_helper
-
-import (
-	"testing"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/log_helper"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-)
-
-func TestNewMultiBrowser(t *testing.T) {
-
-	browserOptions := NewBrowserOptions(log_helper.GetLogger4Tester(), true, settings.Get())
-	browserOptions.SetXrayPoolUrl("127.0.0.1")
-	browserOptions.SetXrayPoolPort("19035")
-	b := NewMultiBrowser(browserOptions)
-
-	for i := 0; i < 5; i++ {
-		page, _, _, err := NewPageNavigateWithProxy(b.GetLBBrowser(), b.LbHttpUrl, "https://www.ipaddress.my/", 10*time.Second)
-		if err != nil {
-			return
-		}
-		page.Close()
-	}
-
-	println(b)
-}

+ 0 - 54
pkg/rod_helper/options.go

@@ -1,54 +0,0 @@
-package rod_helper
-
-import (
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-	"github.com/sirupsen/logrus"
-)
-
-type BrowserOptions struct {
-	Log                  *logrus.Logger     // 日志
-	LoadAdblock          bool               // 是否加载 adblock
-	Settings             *settings.Settings // 配置
-	preLoadUrl           string             // 预加载的url
-	xrayPoolUrl          string             // xray pool url
-	xrayPoolPort         string             // xray pool port
-	browserInstanceCount int                // 浏览器最大的实例,xrayPoolUrl 有值的时候生效,用于爬虫。因为每启动一个实例就试用一个固定的代理,所以需要多个才行
-}
-
-func NewBrowserOptions(log *logrus.Logger, loadAdblock bool, settings *settings.Settings) *BrowserOptions {
-	return &BrowserOptions{Log: log, LoadAdblock: loadAdblock, Settings: settings, browserInstanceCount: 1}
-}
-
-func (r *BrowserOptions) SetPreLoadUrl(url string) {
-	r.preLoadUrl = url
-}
-func (r *BrowserOptions) PreLoadUrl() string {
-	return r.preLoadUrl
-}
-
-// SetXrayPoolUrl 127.0.0.1
-func (r *BrowserOptions) SetXrayPoolUrl(xrayUrl string) {
-	r.xrayPoolUrl = xrayUrl
-}
-
-// XrayPoolUrl 127.0.0.1
-func (r *BrowserOptions) XrayPoolUrl() string {
-	return r.xrayPoolUrl
-}
-
-// SetXrayPoolPort 19035
-func (r *BrowserOptions) SetXrayPoolPort(xrayPort string) {
-	r.xrayPoolPort = xrayPort
-}
-
-// XrayPoolPort 19035
-func (r *BrowserOptions) XrayPoolPort() string {
-	return r.xrayPoolPort
-}
-
-func (r *BrowserOptions) SetBrowserInstanceCount(count int) {
-	r.browserInstanceCount = count
-}
-func (r *BrowserOptions) BrowserInstanceCount() int {
-	return r.browserInstanceCount
-}

+ 0 - 505
pkg/rod_helper/rod_base.go

@@ -1,505 +0,0 @@
-package rod_helper
-
-import (
-	"crypto/tls"
-	_ "embed"
-	"errors"
-	"net/http"
-	"net/url"
-	"os"
-	"path/filepath"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/local_http_proxy_server"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/regex_things"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/random_useragent"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
-	"github.com/go-rod/rod"
-	"github.com/go-rod/rod/lib/launcher"
-	"github.com/go-rod/rod/lib/proto"
-	"github.com/mholt/archiver/v3"
-	"github.com/sirupsen/logrus"
-)
-
-// NewBrowserEx 创建一个 Browser 并且初始化
-func NewBrowserEx(rodOptions *BrowserOptions) (*rod.Browser, error) {
-
-	if rodOptions.Settings.ExperimentalFunction.RemoteChromeSettings.Enable == false {
-
-		localChromeFPath := ""
-		if rodOptions.Settings.ExperimentalFunction.LocalChromeSettings.Enabled == true {
-			localChromeFPath = rodOptions.Settings.ExperimentalFunction.LocalChromeSettings.LocalChromeExeFPath
-		}
-		return NewBrowserBase(rodOptions.Log,
-			localChromeFPath,
-			local_http_proxy_server.GetProxyUrl(),
-			rodOptions.LoadAdblock,
-			rodOptions.PreLoadUrl())
-	} else {
-		return NewBrowserBaseFromDocker(local_http_proxy_server.GetProxyUrl(),
-			rodOptions.Settings.ExperimentalFunction.RemoteChromeSettings.RemoteDockerURL,
-			rodOptions.Settings.ExperimentalFunction.RemoteChromeSettings.RemoteAdblockPath,
-			rodOptions.Settings.ExperimentalFunction.RemoteChromeSettings.ReMoteUserDataDir,
-			rodOptions.LoadAdblock,
-			rodOptions.PreLoadUrl())
-	}
-}
-
-func NewBrowserBase(log *logrus.Logger, localChromeFPath, httpProxyURL string, loadAdblock bool, preLoadUrl ...string) (*rod.Browser, error) {
-
-	var err error
-
-	once.Do(func() {
-		adblockSavePath, err = releaseAdblock(log)
-		if err != nil {
-			log.Errorln("releaseAdblock", err)
-			log.Panicln("releaseAdblock", err)
-		}
-	})
-
-	// 随机的 rod 子文件夹名称
-	nowUserData := filepath.Join(pkg.DefRodTmpRootFolder(), pkg.RandStringBytesMaskImprSrcSB(20))
-	var browser *rod.Browser
-
-	if localChromeFPath != "" {
-		// 如果有指定的 chrome 路径,则使用指定的 chrome 路径
-		if pkg.IsFile(localChromeFPath) == false {
-			log.Errorln(errors.New("localChromeFPath is not a file, localChromePath:" + localChromeFPath))
-			panic(errors.New("localChromeFPath is not a file, localChromePath:" + localChromeFPath))
-		}
-		err = rod.Try(func() {
-			purl := ""
-			if loadAdblock == true {
-				purl = launcher.New().Bin(localChromeFPath).
-					Delete("disable-extensions").
-					Set("load-extension", adblockSavePath).
-					Proxy(httpProxyURL).
-					Headless(false). // 插件模式需要设置这个
-					UserDataDir(nowUserData).
-					//XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16").
-					//XVFB("-ac :99", "-screen 0 1280x1024x16").
-					MustLaunch()
-			} else {
-				purl = launcher.New().Bin(localChromeFPath).
-					Proxy(httpProxyURL).
-					UserDataDir(nowUserData).
-					MustLaunch()
-			}
-
-			browser = rod.New().ControlURL(purl).MustConnect()
-		})
-	} else {
-		// 如果没有指定 chrome 的路径,则使用 rod 自行下载的 chrome
-		err = rod.Try(func() {
-			purl := ""
-			if loadAdblock == true {
-				purl = launcher.New().
-					Delete("disable-extensions").
-					Set("load-extension", adblockSavePath).
-					Proxy(httpProxyURL).
-					Headless(false). // 插件模式需要设置这个
-					UserDataDir(nowUserData).
-					//XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16").
-					//XVFB("-ac :99", "-screen 0 1280x1024x16").
-					MustLaunch()
-			} else {
-				purl = launcher.New().
-					Proxy(httpProxyURL).
-					UserDataDir(nowUserData).
-					MustLaunch()
-			}
-
-			browser = rod.New().ControlURL(purl).MustConnect()
-		})
-	}
-
-	if err != nil {
-		return nil, err
-	}
-
-	// 如果加载了插件,那么就需要进行一定的耗时操作,等待其第一次的加载完成
-	if loadAdblock == true {
-		_, _, err := HttpGetFromBrowser(browser, "https://www.qq.com", 15*time.Second)
-		if err != nil {
-			if browser != nil {
-				browser.Close()
-			}
-			return nil, err
-		}
-
-		//if page != nil {
-		//	_ = page.Close()
-		//}
-	}
-	if len(preLoadUrl) > 0 && preLoadUrl[0] != "" {
-		_, _, err := HttpGetFromBrowser(browser, preLoadUrl[0], 15*time.Second)
-		if err != nil {
-			if browser != nil {
-				browser.Close()
-			}
-			return nil, err
-		}
-
-		//if page != nil {
-		//	_ = page.Close()
-		//}
-	}
-
-	return browser, nil
-}
-
-func NewBrowserBaseFromDocker(httpProxyURL, remoteDockerURL string, remoteAdblockPath, reMoteUserDataDir string,
-	loadAdblock bool, preLoadUrl ...string) (*rod.Browser, error) {
-	var browser *rod.Browser
-
-	err := rod.Try(func() {
-
-		purl := ""
-		var l *launcher.Launcher
-		if loadAdblock == true {
-			l = launcher.MustNewManaged(remoteDockerURL)
-			purl = l.Delete("disable-extensions").
-				Set("load-extension", remoteAdblockPath).
-				Proxy(httpProxyURL).
-				Headless(false). // 插件模式需要设置这个
-				UserDataDir(reMoteUserDataDir).
-				MustLaunch()
-		} else {
-			l = launcher.MustNewManaged(remoteDockerURL)
-			purl = l.
-				Proxy(httpProxyURL).
-				UserDataDir(reMoteUserDataDir).
-				MustLaunch()
-		}
-
-		browser = rod.New().Client(l.MustClient()).ControlURL(purl).MustConnect()
-	})
-	if err != nil {
-		return nil, err
-	}
-
-	// 如果加载了插件,那么就需要进行一定的耗时操作,等待其第一次的加载完成
-	if loadAdblock == true {
-		_, page, err := HttpGetFromBrowser(browser, "https://www.qq.com", 15*time.Second)
-		if err != nil {
-			if browser != nil {
-				browser.Close()
-			}
-			return nil, err
-		}
-
-		if page != nil {
-			_ = page.Close()
-		}
-	}
-
-	if len(preLoadUrl) > 0 && preLoadUrl[0] != "" {
-		_, page, err := HttpGetFromBrowser(browser, preLoadUrl[0], 15*time.Second)
-		if err != nil {
-			if browser != nil {
-				browser.Close()
-			}
-			return nil, err
-		}
-
-		if page != nil {
-			_ = page.Close()
-		}
-	}
-
-	return browser, nil
-}
-
-func NewPageNavigate(browser *rod.Browser, desURL string, timeOut time.Duration, debugMode ...bool) (*rod.Page, int, string, error) {
-
-	addSleepTime := time.Second * 5
-
-	if len(debugMode) > 0 && debugMode[0] == true {
-		addSleepTime = 0 * time.Second
-	}
-
-	page, err := newPage(browser)
-	if err != nil {
-		return nil, 0, "", err
-	}
-
-	return PageNavigate(page, desURL, timeOut+addSleepTime)
-}
-
-func NewPageNavigateWithProxy(browser *rod.Browser, proxyUrl string, desURL string, timeOut time.Duration) (*rod.Page, int, string, error) {
-
-	page, err := newPage(browser)
-	if err != nil {
-		return nil, 0, "", err
-	}
-
-	return PageNavigateWithProxy(page, proxyUrl, desURL, timeOut)
-}
-
-func PageNavigate(page *rod.Page, desURL string, timeOut time.Duration) (*rod.Page, int, string, error) {
-
-	err := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{
-		UserAgent: random_useragent.RandomUserAgent(true),
-	})
-	if err != nil {
-		if page != nil {
-			page.Close()
-		}
-		return nil, 0, "", err
-	}
-	var e proto.NetworkResponseReceived
-	wait := page.WaitEvent(&e)
-	page = page.Timeout(timeOut)
-	err = rod.Try(func() {
-		page.MustNavigate(desURL)
-		wait()
-	})
-	if err != nil {
-		if page != nil {
-			page.Close()
-		}
-		return nil, 0, "", err
-	}
-	// 出去前把 TimeOUt 取消了
-	page = page.CancelTimeout()
-
-	Status := e.Response.Status
-	ResponseURL := e.Response.URL
-	//if Status >= 400 {
-	//	publicIP := "xx.xx.xx.xx"
-	//	publicIP, err = GetPublicIP(page, timeOut, nil)
-	//	if err != nil {
-	//		return nil, 0, "", errors.New(fmt.Sprintf("status code >= 400, PublicIP: %v, Status is %d, ResponseURL is %v", publicIP, Status, ResponseURL))
-	//	}
-	//	if page != nil {
-	//		_ = page.Close()
-	//	}
-	//	return nil, Status, ResponseURL, errors.New(fmt.Sprintf("status code >= 400, PublicIP: %v, Status is %d, ResponseURL is %v", publicIP, Status, ResponseURL))
-	//}
-	return page, Status, ResponseURL, nil
-}
-
-func PageNavigateWithProxy(page *rod.Page, proxyUrl string, desURL string, timeOut time.Duration) (*rod.Page, int, string, error) {
-
-	router := page.HijackRequests()
-	defer router.Stop()
-
-	router.MustAdd("*", func(ctx *rod.Hijack) {
-		px, _ := url.Parse(proxyUrl)
-		err := ctx.LoadResponse(&http.Client{
-			Transport: &http.Transport{
-				Proxy:           http.ProxyURL(px),
-				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-			},
-		}, true)
-		if err != nil {
-			return
-		}
-	})
-	go router.Run()
-
-	err := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{
-		UserAgent: random_useragent.RandomUserAgent(true),
-	})
-	if err != nil {
-		if page != nil {
-			page.Close()
-		}
-		return nil, 0, "", err
-	}
-
-	var e proto.NetworkResponseReceived
-	wait := page.WaitEvent(&e)
-	page = page.Timeout(timeOut)
-	err = rod.Try(func() {
-		page.MustNavigate(desURL)
-		wait()
-	})
-	if err != nil {
-		if page != nil {
-			page.Close()
-		}
-		return nil, 0, "", err
-	}
-
-	// 出去前把 TimeOUt 取消了
-	page = page.CancelTimeout()
-
-	Status := e.Response.Status
-	ResponseURL := e.Response.URL
-
-	//if Status >= 400 {
-	//
-	//	publicIP := "xx.xx.xx.xx"
-	//	publicIP, err = GetPublicIP(page, timeOut, nil)
-	//	if err != nil {
-	//		return nil, 0, "", errors.New(fmt.Sprintf("status code >= 400, PublicIP: %v, Status is %d, ResponseURL is %v", publicIP, Status, ResponseURL))
-	//	}
-	//	if page != nil {
-	//		_ = page.Close()
-	//	}
-	//	return nil, Status, ResponseURL, errors.New(fmt.Sprintf("status code >= 400, PublicIP: %v, Status is %d, ResponseURL is %v", publicIP, Status, ResponseURL))
-	//}
-
-	return page, Status, ResponseURL, nil
-}
-
-func GetPublicIP(page *rod.Page, timeOut time.Duration, customDectIPSites []string) (string, error) {
-	defPublicIPSites := []string{
-		"https://myip.biturl.top/",
-		"https://ip4.seeip.org/",
-		"https://ipecho.net/plain",
-		"https://api-ipv4.ip.sb/ip",
-		"https://api.ipify.org/",
-		"http://myexternalip.com/raw",
-	}
-
-	customPublicIPSites := make([]string, 0)
-	if customDectIPSites != nil {
-		customPublicIPSites = append(customPublicIPSites, customDectIPSites...)
-	} else {
-		customPublicIPSites = append(customPublicIPSites, defPublicIPSites...)
-	}
-
-	for _, publicIPSite := range customPublicIPSites {
-
-		publicIPPage, _, _, err := PageNavigate(page, publicIPSite, timeOut)
-		if err != nil {
-			return "", err
-		}
-		html, err := publicIPPage.HTML()
-		if err != nil {
-			return "", err
-		}
-		matcheds := regex_things.ReMatchIP.FindAllString(html, -1)
-		if html != "" && matcheds != nil && len(matcheds) >= 1 {
-			return matcheds[0], nil
-		}
-	}
-
-	return "", errors.New("get public ip failed")
-}
-
-func HttpGetFromBrowser(browser *rod.Browser, inputUrl string, tt time.Duration, debugMode ...bool) (string, *rod.Page, error) {
-
-	page, _, _, err := NewPageNavigate(browser, inputUrl, tt, debugMode...)
-	if err != nil {
-		return "", nil, err
-	}
-	pageString, err := page.HTML()
-	if err != nil {
-		if page != nil {
-			page.Close()
-		}
-		return "", nil, err
-	}
-	// 每次搜索间隔
-	if len(debugMode) > 0 && debugMode[0] == true {
-		//time.Sleep(my_util.RandomSecondDuration(0, 1))
-	} else {
-		time.Sleep(pkg.RandomSecondDuration(2, 5))
-	}
-
-	if strings.Contains(strings.ToLower(pageString), "<title>403 forbidden</title>") == true {
-		if page != nil {
-			page.Close()
-		}
-		return "", nil, errors.New("403 forbidden")
-	}
-
-	return pageString, page, nil
-}
-
-// ReloadBrowser 提前把浏览器下载好
-func ReloadBrowser(log *logrus.Logger) {
-	newBrowser, err := NewBrowserEx(NewBrowserOptions(log, true, settings.Get()))
-	if err != nil {
-		return
-	}
-	defer func() {
-		_ = newBrowser.Close()
-	}()
-	page, _, _, err := NewPageNavigate(newBrowser, "https://www.baidu.com", 30*time.Second)
-	if err != nil {
-		return
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-}
-
-// Clear 清理缓存
-func Clear(log *logrus.Logger) {
-	err := pkg.ClearRodTmpRootFolder()
-	if err != nil {
-		log.Errorln("ClearRodTmpRootFolder", err)
-		return
-	}
-
-	log.Infoln("ClearRodTmpRootFolder Done")
-}
-
-func newPage(browser *rod.Browser) (*rod.Page, error) {
-	page, err := browser.Page(proto.TargetCreateTarget{URL: ""})
-	if err != nil {
-		return nil, err
-	}
-	return page, err
-}
-
-// releaseAdblock 从程序中释放 adblock 插件出来到本地路径
-func releaseAdblock(log *logrus.Logger) (string, error) {
-
-	defer func() {
-		log.Infoln("releaseAdblock end")
-	}()
-
-	log.Infoln("releaseAdblock start")
-
-	adblockFolderPath := pkg.AdblockTmpFolder()
-	err := os.MkdirAll(filepath.Join(adblockFolderPath), os.ModePerm)
-	if err != nil {
-		return "", err
-	}
-	desPath := filepath.Join(adblockFolderPath, "RunAdblock")
-	// 清理之前缓存的信息
-	_ = pkg.ClearFolder(desPath)
-	// 具体把 adblock zip 解压下载到哪里
-	outZipFileFPath := filepath.Join(adblockFolderPath, "adblock.zip")
-	adblockZipFile, err := os.Create(outZipFileFPath)
-	if err != nil {
-		return "", err
-	}
-	defer func() {
-		_ = adblockZipFile.Close()
-		_ = os.Remove(outZipFileFPath)
-	}()
-	_, err = adblockZipFile.Write(adblockFolder)
-	if err != nil {
-		return "", err
-	}
-	_ = adblockZipFile.Close()
-
-	r := archiver.NewZip()
-	err = r.Unarchive(outZipFileFPath, desPath)
-	if err != nil {
-		return "", err
-	}
-	return filepath.Join(desPath, adblockInsideName), err
-}
-
-const adblockInsideName = "adblock"
-
-var once sync.Once
-
-// 这个文件内有一个子文件夹 adblock ,制作的时候务必注意
-//go:embed assets/adblock_4_43_0_0.zip
-var adblockFolder []byte
-
-var adblockSavePath string

+ 0 - 68
pkg/rod_helper/rod_base_test.go

@@ -1,68 +0,0 @@
-package rod_helper
-
-import (
-	"testing"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/log_helper"
-	"github.com/go-rod/rod/lib/launcher"
-	"github.com/go-rod/rod/lib/proto"
-)
-
-func TestNewBrowser(t *testing.T) {
-
-	bPath, bok := launcher.LookPath()
-	println(bok, bPath)
-	desURL := "https://google.com"
-	httpProxyURL := "http://127.0.0.1:63204"
-	browser, err := NewBrowserBase(log_helper.GetLogger4Tester(), "", httpProxyURL, true)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		_ = browser.Close()
-	}()
-
-	page, status, responseUrl, err := NewPageNavigateWithProxy(browser, httpProxyURL, desURL, 10*time.Second)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	println("Status:", status, "ResponseUrl:", responseUrl)
-
-	page, err = browser.Page(proto.TargetCreateTarget{URL: desURL})
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		_ = page.Close()
-	}()
-}
-
-func TestNewBrowserFromDocker(t *testing.T) {
-	//desURL := "https://www.wikipedia.org/"
-	//httpProxyURL := "http://127.0.0.1:10809"
-	//remoteDockerURL := "ws://192.168.50.135:9222"
-	//
-	//browser, err := NewBrowserBaseFromDocker(httpProxyURL, remoteDockerURL)
-	//if err != nil {
-	//	t.Fatal(err)
-	//}
-	//defer func() {
-	//	_ = browser.Close()
-	//}()
-	//page, err := browser.Page(proto.TargetCreateTarget{URL: desURL})
-	//if err != nil {
-	//	t.Fatal(err)
-	//}
-	//defer func() {
-	//	_ = page.Close()
-	//}()
-}
-
-func TestClear(t *testing.T) {
-	Clear(log_helper.GetLogger4Tester())
-}