Browse Source

新增,每个字幕源的每日下载统计(粗略)

Signed-off-by: allan716 <[email protected]>
allan716 3 years ago
parent
commit
9ee88d6f39

+ 1 - 0
.gitignore

@@ -83,3 +83,4 @@ TestData/
 /internal/logic/sub_supplier/subhd/cache
 /internal/logic/sub_supplier/zimuku/cache
 /internal/logic/movie_helper/Logs
+/TestCode/Logs

+ 1 - 1
cmd/chinesesubfinder/main.go

@@ -27,7 +27,7 @@ func init() {
 
 func main() {
 
-	cronHelper := cron_helper.NewCronHelper()
+	cronHelper := cron_helper.NewCronHelper(log_helper.GetLogger(), settings.GetSettings())
 	if settings.GetSettings().UserInfo.Username == "" || settings.GetSettings().UserInfo.Password == "" {
 		// 如果没有完成,那么就不开启
 		log_helper.GetLogger().Infoln("Need do Setup")

+ 5 - 1
go.mod

@@ -57,7 +57,7 @@ require (
 	github.com/ysmood/gson v0.7.0 // indirect
 	golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
 	golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d
-	golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
+	golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 // indirect
 	golang.org/x/text v0.3.7
 	gonum.org/v1/gonum v0.9.3
 	gopkg.in/errgo.v2 v2.1.0
@@ -78,6 +78,7 @@ require (
 	github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
 	github.com/bodgit/plumbing v1.1.0 // indirect
 	github.com/bodgit/windows v1.0.0 // indirect
+	github.com/bwmarrin/snowflake v0.3.0 // indirect
 	github.com/connesc/cipherio v0.2.1 // indirect
 	github.com/dsnet/compress v0.0.1 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
@@ -116,6 +117,9 @@ require (
 	github.com/ugorji/go/codec v1.2.6 // indirect
 	github.com/xanzy/ssh-agent v0.3.0 // indirect
 	github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
+	github.com/xujiajun/mmap-go v1.0.1 // indirect
+	github.com/xujiajun/nutsdb v0.8.0 // indirect
+	github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b // indirect
 	github.com/ysmood/goob v0.3.0 // indirect
 	github.com/ysmood/leakless v0.7.0 // indirect
 	go4.org v0.0.0-20200411211856-f5505b9728dd // indirect

+ 13 - 0
go.sum

@@ -94,11 +94,14 @@ github.com/bodgit/sevenzip v1.1.0/go.mod h1:vRCJlX/FVjbcwUG9lyX1YQPbQA4Xxw/7puzc
 github.com/bodgit/windows v1.0.0 h1:rLQ/XjsleZvx4fR1tB/UxQrK+SJ2OFHzfPjLWWOhDIA=
 github.com/bodgit/windows v1.0.0/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
+github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
+github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
 github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -579,6 +582,13 @@ github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6e
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xujiajun/gorouter v1.2.0/go.mod h1:yJrIta+bTNpBM/2UT8hLOaEAFckO+m/qmR3luMIQygM=
+github.com/xujiajun/mmap-go v1.0.1 h1:7Se7ss1fLPPRW+ePgqGpCkfGIZzJV6JPq9Wq9iv/WHc=
+github.com/xujiajun/mmap-go v1.0.1/go.mod h1:CNN6Sw4SL69Sui00p0zEzcZKbt+5HtEnYUsc6BKKRMg=
+github.com/xujiajun/nutsdb v0.8.0 h1:BkXjifwlF3akHVoTQ8B3gdF183oq4QI0JQywazEZXkM=
+github.com/xujiajun/nutsdb v0.8.0/go.mod h1:KOdR/RLPELQ6611VTMsSOUBSO2s7kXPINOiA/+1dlgc=
+github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b h1:jKG9OiL4T4xQN3IUrhUpc1tG+HfDXppkgVcrAiiaI/0=
+github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b/go.mod h1:AZd87GYJlUzl82Yab2kTjx1EyXSQCAfZDhpTo1SQC4k=
 github.com/ysmood/goob v0.3.0 h1:XZ51cZJ4W3WCoCiUktixzMIQF86W7G5VFL4QQ/Q2uS0=
 github.com/ysmood/goob v0.3.0/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs=
 github.com/ysmood/got v0.15.1 h1:X5jAbMyBf5yeezuFMp9HaMGXZWMSqIQcUlAHI+kJmUs=
@@ -738,6 +748,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -776,6 +787,8 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
 golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM=
+golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 6 - 2
internal/backend/controllers/base/controller_base.go

@@ -4,14 +4,18 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/backend"
 	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
 	"net/http"
 )
 
 type ControllerBase struct {
+	log *logrus.Logger
 }
 
-func NewControllerBase() *ControllerBase {
-	return &ControllerBase{}
+func NewControllerBase(_logger *logrus.Logger) *ControllerBase {
+	return &ControllerBase{
+		log: _logger,
+	}
 }
 
 func (cb *ControllerBase) ErrorProcess(c *gin.Context, funcName string, err error) {

+ 7 - 7
internal/backend/controllers/base/proxy.go

@@ -9,11 +9,10 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/backend"
 	"github.com/gin-gonic/gin"
-	"github.com/huandu/go-clone"
 	"net/http"
 )
 
-func (cb ControllerBase) CheckProxyHandler(c *gin.Context) {
+func (cb *ControllerBase) CheckProxyHandler(c *gin.Context) {
 	var err error
 	defer func() {
 		// 统一的异常处理
@@ -26,17 +25,18 @@ func (cb ControllerBase) CheckProxyHandler(c *gin.Context) {
 		return
 	}
 
-	tmpSettings := clone.Clone(*settings.GetSettings()).(settings.Settings)
+	tmpSettings := settings.GetSettings()
 	tmpSettings.AdvancedSettings.ProxySettings.UseHttpProxy = true
 	tmpSettings.AdvancedSettings.ProxySettings.HttpProxyAddress = checkProxy.HttpProxyAddress
 
 	// 使用提交过来的这个代理地址,测试多个字幕网站的可用性
 	subSupplierHub := subSupplier.NewSubSupplierHub(
 		tmpSettings,
-		zimuku.NewSupplier(tmpSettings),
-		xunlei.NewSupplier(tmpSettings),
-		shooter.NewSupplier(tmpSettings),
-		subhd.NewSupplier(tmpSettings),
+		cb.log,
+		zimuku.NewSupplier(tmpSettings, cb.log),
+		xunlei.NewSupplier(tmpSettings, cb.log),
+		shooter.NewSupplier(tmpSettings, cb.log),
+		subhd.NewSupplier(tmpSettings, cb.log),
 	)
 
 	outStatus := subSupplierHub.CheckSubSiteStatus()

+ 2 - 1
internal/backend/routers/base_router.go

@@ -5,12 +5,13 @@ import (
 	v1 "github.com/allanpk716/ChineseSubFinder/internal/backend/controllers/v1"
 	"github.com/allanpk716/ChineseSubFinder/internal/backend/middle"
 	"github.com/allanpk716/ChineseSubFinder/internal/logic/cron_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/gin-gonic/gin"
 )
 
 func InitRouter(router *gin.Engine, cronHelper *cron_helper.CronHelper) {
 
-	cbBase := base.NewControllerBase()
+	cbBase := base.NewControllerBase(log_helper.GetLogger())
 	cbV1 := v1.NewControllerBase(cronHelper)
 	// 基础的路由
 	router.GET("/system-status", cbBase.SystemStatusHandler)

+ 6 - 6
internal/common/urls.go

@@ -1,12 +1,12 @@
 package common
 
 const (
-	SubXunLeiRootUrl  = "http://sub.xmp.sandai.net:8000/subxl/%s.json"
-	SubShooterRootUrl = "https://www.shooter.cn/api/subapi.php"
+	SubXunLeiRootUrlDef  = "http://sub.xmp.sandai.net:8000/subxl/%s.json"
+	SubShooterRootUrlDef = "https://www.shooter.cn/api/subapi.php"
 
-	SubZiMuKuRootUrl         = "https://zimuku.org"
-	SubZiMuKuSearchFormatUrl = SubZiMuKuRootUrl + "/search?q=%s"
+	SubZiMuKuRootUrlDef      = "https://zimuku.org"
+	SubZiMuKuSearchFormatUrl = "/search?q=%s"
 
-	SubSubHDRootUrl   = "https://subhd.tv"
-	SubSubHDSearchUrl = SubSubHDRootUrl + "/search/%s"
+	SubSubHDRootUrlDef = "https://subhd.tv"
+	SubSubHDSearchUrl  = "/search/%s"
 )

+ 2 - 0
internal/ifaces/iSupplier.go

@@ -12,6 +12,8 @@ type ISupplier interface {
 
 	GetSupplierName() string
 
+	OverDailyDownloadLimit() bool
+
 	GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error)
 
 	GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error)

+ 34 - 27
internal/logic/cron_helper/cron_helper.go

@@ -7,6 +7,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/robfig/cron/v3"
+	"github.com/sirupsen/logrus"
 	"sync"
 	"time"
 )
@@ -18,11 +19,17 @@ type CronHelper struct {
 	cronHelperRunningLock         sync.Mutex
 	c                             *cron.Cron
 	dh                            *downloader_helper.DownloaderHelper
+
+	sets *settings.Settings
+	log  *logrus.Logger
 }
 
-func NewCronHelper() *CronHelper {
+func NewCronHelper(_log *logrus.Logger, _sets *settings.Settings) *CronHelper {
 
-	ch := CronHelper{}
+	ch := CronHelper{
+		log:  _log,
+		sets: _sets,
+	}
 	return &ch
 }
 
@@ -30,24 +37,24 @@ func NewCronHelper() *CronHelper {
 // runImmediately == false 那么 ch.c.Start() 是不会阻塞的
 func (ch *CronHelper) Start(runImmediately bool) {
 
-	_, err := cron.ParseStandard(settings.GetSettings().CommonSettings.ScanInterval)
+	_, err := cron.ParseStandard(ch.sets.CommonSettings.ScanInterval)
 	if err != nil {
-		log_helper.GetLogger().Warningln("CommonSettings.ScanInterval format error, after v0.25.x , need reset this at WebUI")
+		ch.log.Warningln("CommonSettings.ScanInterval format error, after v0.25.x , need reset this at WebUI")
 		// 如果解析错误了,就需要重新赋值默认值过来,然后保存
-		nowSettings := settings.GetSettings()
+		nowSettings := ch.sets
 		nowSettings.CommonSettings.ScanInterval = settings.NewCommonSettings().ScanInterval
 		err = settings.SetFullNewSettings(nowSettings)
 		if err != nil {
-			log_helper.GetLogger().Panicln("CronHelper.SetFullNewSettings:", err)
+			ch.log.Panicln("CronHelper.SetFullNewSettings:", err)
 			return
 		}
 	}
 
 	ch.c = cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))
 	// 定时器
-	entryID, err := ch.c.AddFunc(settings.GetSettings().CommonSettings.ScanInterval, ch.coreSubDownloadProcess)
+	entryID, err := ch.c.AddFunc(ch.sets.CommonSettings.ScanInterval, ch.coreSubDownloadProcess)
 	if err != nil {
-		log_helper.GetLogger().Panicln("CronHelper Cron entryID:", entryID, "Error:", err)
+		ch.log.Panicln("CronHelper Cron entryID:", entryID, "Error:", err)
 	}
 
 	ch.cronHelperRunningLock.Lock()
@@ -56,17 +63,17 @@ func (ch *CronHelper) Start(runImmediately bool) {
 	// 是否在定时器开启前先执行一次任务
 	if runImmediately == true {
 
-		log_helper.GetLogger().Infoln("First Time coreSubDownloadProcess Start")
+		ch.log.Infoln("First Time coreSubDownloadProcess Start")
 
 		ch.coreSubDownloadProcess()
 
-		log_helper.GetLogger().Infoln("First Time coreSubDownloadProcess End")
+		ch.log.Infoln("First Time coreSubDownloadProcess End")
 
 	} else {
-		log_helper.GetLogger().Infoln("RunAtStartup: false, so will not Run At Startup")
+		ch.log.Infoln("RunAtStartup: false, so will not Run At Startup")
 	}
 
-	log_helper.GetLogger().Infoln("CronHelper Start...")
+	ch.log.Infoln("CronHelper Start...")
 	ch.c.Start()
 
 	// 只有定时任务 start 之后才能拿到信息
@@ -76,9 +83,9 @@ func (ch *CronHelper) Start(runImmediately bool) {
 		tttt := ch.c.Entries()[0].Next.Format("2006-01-02 15:04:05")
 		common.SetSubScanJobStatusWaiting(tttt)
 
-		log_helper.GetLogger().Infoln("Next Sub Scan Will Process At:", tttt)
+		ch.log.Infoln("Next Sub Scan Will Process At:", tttt)
 	} else {
-		log_helper.GetLogger().Errorln("Can't get cron jobs, will not send SubScanJobStatus")
+		ch.log.Errorln("Can't get cron jobs, will not send SubScanJobStatus")
 	}
 }
 
@@ -99,9 +106,9 @@ func (ch *CronHelper) Stop() {
 		nowContext := ch.c.Stop()
 		select {
 		case <-time.After(5 * time.Minute):
-			log_helper.GetLogger().Warningln("Wait over 5 min, CronHelper is timeout")
+			ch.log.Warningln("Wait over 5 min, CronHelper is timeout")
 		case <-nowContext.Done():
-			log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
+			ch.log.Infoln("CronHelper.Stop() Done.")
 		}
 	} else {
 		// Stop stops the cron scheduler if it is running; otherwise it does nothing.
@@ -109,9 +116,9 @@ func (ch *CronHelper) Stop() {
 		nowContext := ch.c.Stop()
 		select {
 		case <-time.After(5 * time.Second):
-			log_helper.GetLogger().Warningln("Wait over 5 s, CronHelper is timeout")
+			ch.log.Warningln("Wait over 5 s, CronHelper is timeout")
 		case <-nowContext.Done():
-			log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
+			ch.log.Infoln("CronHelper.Stop() Done.")
 		}
 	}
 
@@ -164,7 +171,7 @@ func (ch *CronHelper) coreSubDownloadProcess() {
 		ch.fullSubDownloadProcessing = false
 		ch.fullSubDownloadProcessingLock.Unlock()
 
-		log_helper.GetLogger().Infoln(log_helper.OnceSubsScanEnd)
+		ch.log.Infoln(log_helper.OnceSubsScanEnd)
 
 		// 下载完后,应该继续是等待
 		tttt := ch.c.Entries()[0].Next.Format("2006-01-02 15:04:05")
@@ -177,28 +184,28 @@ func (ch *CronHelper) coreSubDownloadProcess() {
 
 	// ------------------------------------------------------------------------
 	// 如果是 Debug 模式,那么就需要写入特殊文件
-	if settings.GetSettings().AdvancedSettings.DebugMode == true {
+	if ch.sets.AdvancedSettings.DebugMode == true {
 		err := log_helper.WriteDebugFile()
 		if err != nil {
-			log_helper.GetLogger().Errorln("log_helper.WriteDebugFile " + err.Error())
+			ch.log.Errorln("log_helper.WriteDebugFile " + err.Error())
 		}
 		log_helper.GetLogger(true).Infoln("Reload Log Settings, level = Debug")
 	} else {
 		err := log_helper.DeleteDebugFile()
 		if err != nil {
-			log_helper.GetLogger().Errorln("log_helper.DeleteDebugFile " + err.Error())
+			ch.log.Errorln("log_helper.DeleteDebugFile " + err.Error())
 		}
 		log_helper.GetLogger(true).Infoln("Reload Log Settings, level = Info")
 	}
 	// ------------------------------------------------------------------------
 	// 开始标记,这个是单次扫描的开始
-	log_helper.GetLogger().Infoln(log_helper.OnceSubsScanStart)
+	ch.log.Infoln(log_helper.OnceSubsScanStart)
 
 	// 扫描字幕任务开始,先是扫描阶段,那么是拿不到有多少视频需要扫描的数量的
 	common.SetSubScanJobStatusPreparing(time.Now().Format("2006-01-02 15:04:05"))
 
 	// 下载前的初始化
-	preDownloadProcess := pre_download_process.NewPreDownloadProcess()
+	preDownloadProcess := pre_download_process.NewPreDownloadProcess(ch.log, ch.sets)
 	err := preDownloadProcess.
 		Init().
 		Check().
@@ -207,8 +214,8 @@ func (ch *CronHelper) coreSubDownloadProcess() {
 		ReloadBrowser().
 		Wait()
 	if err != nil {
-		log_helper.GetLogger().Errorln("pre_download_process", "Error:", err)
-		log_helper.GetLogger().Errorln("Skip DownloaderHelper.Start()")
+		ch.log.Errorln("pre_download_process", "Error:", err)
+		ch.log.Errorln("Skip DownloaderHelper.Start()")
 		return
 	}
 	// 开始下载
@@ -216,7 +223,7 @@ func (ch *CronHelper) coreSubDownloadProcess() {
 		preDownloadProcess.SubSupplierHub)
 	err = ch.dh.Start()
 	if err != nil {
-		log_helper.GetLogger().Errorln("downloader_helper.Start()", "Error:", err)
+		ch.log.Errorln("downloader_helper.Start()", "Error:", err)
 		return
 	}
 }

+ 68 - 62
internal/logic/pre_download_process/pre_download_proces.go

@@ -10,7 +10,6 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/logic/sub_supplier/xunlei"
 	"github.com/allanpk716/ChineseSubFinder/internal/logic/sub_supplier/zimuku"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/hot_fix"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_folder"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
@@ -21,6 +20,7 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/url_connectedness_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"github.com/sirupsen/logrus"
 	"time"
 )
 
@@ -28,39 +28,44 @@ type PreDownloadProcess struct {
 	stageName string
 	gError    error
 
+	sets           *settings.Settings
+	log            *logrus.Logger
 	SubSupplierHub *subSupplier.SubSupplierHub
 }
 
-func NewPreDownloadProcess() *PreDownloadProcess {
-	return &PreDownloadProcess{}
+func NewPreDownloadProcess(_log *logrus.Logger, _sets *settings.Settings) *PreDownloadProcess {
+	return &PreDownloadProcess{
+		log:  _log,
+		sets: _sets,
+	}
 }
 
 func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 
 	if p.gError != nil {
-		log_helper.GetLogger().Infoln("Skip PreDownloadProcess.Init()")
+		p.log.Infoln("Skip PreDownloadProcess.Init()")
 		return p
 	}
 	p.stageName = stageNameInit
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.Init() End")
+		p.log.Infoln("PreDownloadProcess.Init() End")
 	}()
-	log_helper.GetLogger().Infoln("PreDownloadProcess.Init() Start...")
+	p.log.Infoln("PreDownloadProcess.Init() Start...")
 
 	// ------------------------------------------------------------------------
 	// 初始化通知缓存模块
-	notify_center.Notify = notify_center.NewNotifyCenter(settings.GetSettings().DeveloperSettings.BarkServerAddress)
+	notify_center.Notify = notify_center.NewNotifyCenter(p.sets.DeveloperSettings.BarkServerAddress)
 	// 清理通知中心
 	notify_center.Notify.Clear()
 	// ------------------------------------------------------------------------
 	// 获取验证码
 	nowTT := time.Now()
 	nowTimeFileNamePrix := fmt.Sprintf("%d%d%d", nowTT.Year(), nowTT.Month(), nowTT.Day())
-	updateTimeString, code, err := something_static.GetCodeFromWeb(log_helper.GetLogger(), nowTimeFileNamePrix)
+	updateTimeString, code, err := something_static.GetCodeFromWeb(p.log, nowTimeFileNamePrix)
 	if err != nil {
 		notify_center.Notify.Add("GetSubhdCode", "GetCodeFromWeb,"+err.Error())
-		log_helper.GetLogger().Errorln("something_static.GetCodeFromWeb", err)
-		log_helper.GetLogger().Errorln("Skip Subhd download")
+		p.log.Errorln("something_static.GetCodeFromWeb", err)
+		p.log.Errorln("Skip Subhd download")
 		// 没有则需要清空
 		commonValue.SubhdCode = ""
 	} else {
@@ -68,7 +73,7 @@ func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 		// 获取到的更新时间不是当前的日期,那么本次也跳过本次
 		codeTime, err := time.Parse("2006-01-02", updateTimeString)
 		if err != nil {
-			log_helper.GetLogger().Errorln("something_static.GetCodeFromWeb.time.Parse", err)
+			p.log.Errorln("something_static.GetCodeFromWeb.time.Parse", err)
 			// 没有则需要清空
 			commonValue.SubhdCode = ""
 		} else {
@@ -77,9 +82,9 @@ func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 			if codeTime.YearDay() != nowTime.YearDay() {
 				// 没有则需要清空
 				commonValue.SubhdCode = ""
-				log_helper.GetLogger().Warningln("something_static.GetCodeFromWeb, GetCodeTime:", updateTimeString, "NowTime:", time.Now().String(), "Skip")
+				p.log.Warningln("something_static.GetCodeFromWeb, GetCodeTime:", updateTimeString, "NowTime:", time.Now().String(), "Skip")
 			} else {
-				log_helper.GetLogger().Infoln("GetCode", updateTimeString, code)
+				p.log.Infoln("GetCode", updateTimeString, code)
 				commonValue.SubhdCode = code
 			}
 		}
@@ -87,14 +92,15 @@ func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 	// ------------------------------------------------------------------------
 	// 构建每个字幕站点下载者的实例
 	p.SubSupplierHub = subSupplier.NewSubSupplierHub(
-		*settings.GetSettings(),
-		zimuku.NewSupplier(*settings.GetSettings()),
-		xunlei.NewSupplier(*settings.GetSettings()),
-		shooter.NewSupplier(*settings.GetSettings()),
+		p.sets,
+		p.log,
+		zimuku.NewSupplier(p.sets, p.log),
+		xunlei.NewSupplier(p.sets, p.log),
+		shooter.NewSupplier(p.sets, p.log),
 	)
 	if commonValue.SubhdCode != "" {
 		// 如果找到 code 了,那么就可以继续用这个实例
-		p.SubSupplierHub.AddSubSupplier(subhd.NewSupplier(*settings.GetSettings()))
+		p.SubSupplierHub.AddSubSupplier(subhd.NewSupplier(p.sets, p.log))
 	}
 	// ------------------------------------------------------------------------
 	// 清理自定义的 rod 缓存目录
@@ -104,7 +110,7 @@ func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 		return p
 	}
 
-	log_helper.GetLogger().Infoln("ClearRodTmpRootFolder Done")
+	p.log.Infoln("ClearRodTmpRootFolder Done")
 
 	return p
 }
@@ -112,60 +118,60 @@ func (p *PreDownloadProcess) Init() *PreDownloadProcess {
 func (p *PreDownloadProcess) Check() *PreDownloadProcess {
 
 	if p.gError != nil {
-		log_helper.GetLogger().Infoln("Skip PreDownloadProcess.Check()")
+		p.log.Infoln("Skip PreDownloadProcess.Check()")
 		return p
 	}
 	p.stageName = stageNameCheck
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.Check() End")
+		p.log.Infoln("PreDownloadProcess.Check() End")
 	}()
-	log_helper.GetLogger().Infoln("PreDownloadProcess.Check() Start...")
+	p.log.Infoln("PreDownloadProcess.Check() Start...")
 	// ------------------------------------------------------------------------
 	// 是否启用代理
-	if settings.GetSettings().AdvancedSettings.ProxySettings.UseHttpProxy == false {
+	if p.sets.AdvancedSettings.ProxySettings.UseHttpProxy == false {
 
-		log_helper.GetLogger().Infoln("UseHttpProxy = false")
+		p.log.Infoln("UseHttpProxy = false")
 		// 如果不使用代理,那么默认需要检测 baidu 的连通性,不通过也继续
 		proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(url_connectedness_helper.BaiduUrl, "")
 		if err != nil {
-			log_helper.GetLogger().Errorln(errors.New("UrlConnectednessTest Target Site " + url_connectedness_helper.BaiduUrl + ", " + err.Error()))
+			p.log.Errorln(errors.New("UrlConnectednessTest Target Site " + url_connectedness_helper.BaiduUrl + ", " + err.Error()))
 		} else {
-			log_helper.GetLogger().Infoln("UrlConnectednessTest Target Site", url_connectedness_helper.BaiduUrl, "Speed:", proxySpeed, "ms,", "Status:", proxyStatus)
+			p.log.Infoln("UrlConnectednessTest Target Site", url_connectedness_helper.BaiduUrl, "Speed:", proxySpeed, "ms,", "Status:", proxyStatus)
 		}
 	} else {
 
-		log_helper.GetLogger().Infoln("UseHttpProxy:", settings.GetSettings().AdvancedSettings.ProxySettings.HttpProxyAddress)
+		p.log.Infoln("UseHttpProxy:", p.sets.AdvancedSettings.ProxySettings.HttpProxyAddress)
 		// 如果使用了代理,那么默认需要检测 google 的连通性,不通过也继续
-		proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(url_connectedness_helper.GoogleUrl, settings.GetSettings().AdvancedSettings.ProxySettings.HttpProxyAddress)
+		proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(url_connectedness_helper.GoogleUrl, p.sets.AdvancedSettings.ProxySettings.HttpProxyAddress)
 		if err != nil {
-			log_helper.GetLogger().Errorln(errors.New("UrlConnectednessTest Target Site " + url_connectedness_helper.GoogleUrl + ", " + err.Error()))
+			p.log.Errorln(errors.New("UrlConnectednessTest Target Site " + url_connectedness_helper.GoogleUrl + ", " + err.Error()))
 		} else {
-			log_helper.GetLogger().Infoln("UrlConnectednessTest Target Site", url_connectedness_helper.GoogleUrl, "Speed:", proxySpeed, "ms,", "Status:", proxyStatus)
+			p.log.Infoln("UrlConnectednessTest Target Site", url_connectedness_helper.GoogleUrl, "Speed:", proxySpeed, "ms,", "Status:", proxyStatus)
 		}
 	}
 	// ------------------------------------------------------------------------
-	// 测试提供字幕的网站是有效的
+	// 测试提供字幕的网站是有效的,是否下载次数超限
 	p.SubSupplierHub.CheckSubSiteStatus()
 	// ------------------------------------------------------------------------
 	// 判断文件夹是否存在
-	if len(settings.GetSettings().CommonSettings.MoviePaths) < 1 {
-		log_helper.GetLogger().Warningln("MoviePaths not set, len == 0")
+	if len(p.sets.CommonSettings.MoviePaths) < 1 {
+		p.log.Warningln("MoviePaths not set, len == 0")
 	}
-	if len(settings.GetSettings().CommonSettings.SeriesPaths) < 1 {
-		log_helper.GetLogger().Warningln("SeriesPaths not set, len == 0")
+	if len(p.sets.CommonSettings.SeriesPaths) < 1 {
+		p.log.Warningln("SeriesPaths not set, len == 0")
 	}
-	for i, path := range settings.GetSettings().CommonSettings.MoviePaths {
+	for i, path := range p.sets.CommonSettings.MoviePaths {
 		if my_util.IsDir(path) == false {
-			log_helper.GetLogger().Errorln("MovieFolder not found Index", i, "--", path)
+			p.log.Errorln("MovieFolder not found Index", i, "--", path)
 		} else {
-			log_helper.GetLogger().Infoln("MovieFolder Index", i, "--", path)
+			p.log.Infoln("MovieFolder Index", i, "--", path)
 		}
 	}
-	for i, path := range settings.GetSettings().CommonSettings.SeriesPaths {
+	for i, path := range p.sets.CommonSettings.SeriesPaths {
 		if my_util.IsDir(path) == false {
-			log_helper.GetLogger().Errorln("SeriesPaths not found Index", i, "--", path)
+			p.log.Errorln("SeriesPaths not found Index", i, "--", path)
 		} else {
-			log_helper.GetLogger().Infoln("SeriesPaths Index", i, "--", path)
+			p.log.Infoln("SeriesPaths Index", i, "--", path)
 		}
 	}
 	// ------------------------------------------------------------------------
@@ -177,24 +183,24 @@ func (p *PreDownloadProcess) Check() *PreDownloadProcess {
 func (p *PreDownloadProcess) HotFix() *PreDownloadProcess {
 
 	if p.gError != nil {
-		log_helper.GetLogger().Infoln("Skip PreDownloadProcess.Check()")
+		p.log.Infoln("Skip PreDownloadProcess.Check()")
 		return p
 	}
 	p.stageName = stageNameCHotFix
 
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.HotFix() End")
+		p.log.Infoln("PreDownloadProcess.HotFix() End")
 	}()
-	log_helper.GetLogger().Infoln("PreDownloadProcess.HotFix() Start...")
+	p.log.Infoln("PreDownloadProcess.HotFix() Start...")
 	// ------------------------------------------------------------------------
 	// 开始修复
-	log_helper.GetLogger().Infoln(commonValue.NotifyStringTellUserWait)
+	p.log.Infoln(commonValue.NotifyStringTellUserWait)
 	err := hot_fix.HotFixProcess(types.HotFixParam{
-		MovieRootDirs:  settings.GetSettings().CommonSettings.MoviePaths,
-		SeriesRootDirs: settings.GetSettings().CommonSettings.SeriesPaths,
+		MovieRootDirs:  p.sets.CommonSettings.MoviePaths,
+		SeriesRootDirs: p.sets.CommonSettings.SeriesPaths,
 	})
 	if err != nil {
-		log_helper.GetLogger().Errorln("hot_fix.HotFixProcess()", err)
+		p.log.Errorln("hot_fix.HotFixProcess()", err)
 		p.gError = err
 		return p
 	}
@@ -205,31 +211,31 @@ func (p *PreDownloadProcess) HotFix() *PreDownloadProcess {
 func (p *PreDownloadProcess) ChangeSubNameFormat() *PreDownloadProcess {
 
 	if p.gError != nil {
-		log_helper.GetLogger().Infoln("Skip PreDownloadProcess.ChangeSubNameFormat()")
+		p.log.Infoln("Skip PreDownloadProcess.ChangeSubNameFormat()")
 		return p
 	}
 	p.stageName = stageNameChangeSubNameFormat
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.ChangeSubNameFormat() End")
+		p.log.Infoln("PreDownloadProcess.ChangeSubNameFormat() End")
 	}()
-	log_helper.GetLogger().Infoln("PreDownloadProcess.ChangeSubNameFormat() Start...")
+	p.log.Infoln("PreDownloadProcess.ChangeSubNameFormat() Start...")
 	// ------------------------------------------------------------------------
 	/*
 		字幕命名格式转换,需要数据库支持
 		如果数据库没有记录经过转换,那么默认从 Emby 的格式作为检测的起点,转换到目标的格式
 		然后需要在数据库中记录本次的转换结果
 	*/
-	log_helper.GetLogger().Infoln(commonValue.NotifyStringTellUserWait)
+	p.log.Infoln(commonValue.NotifyStringTellUserWait)
 	renameResults, err := sub_formatter.SubFormatChangerProcess(
-		settings.GetSettings().CommonSettings.MoviePaths,
-		settings.GetSettings().CommonSettings.SeriesPaths,
-		common.FormatterName(settings.GetSettings().AdvancedSettings.SubNameFormatter))
+		p.sets.CommonSettings.MoviePaths,
+		p.sets.CommonSettings.SeriesPaths,
+		common.FormatterName(p.sets.AdvancedSettings.SubNameFormatter))
 	// 出错的文件有哪一些
 	for s, i := range renameResults.ErrFiles {
-		log_helper.GetLogger().Errorln("reformat ErrFile:"+s, i)
+		p.log.Errorln("reformat ErrFile:"+s, i)
 	}
 	if err != nil {
-		log_helper.GetLogger().Errorln("SubFormatChangerProcess() Error", err)
+		p.log.Errorln("SubFormatChangerProcess() Error", err)
 		p.gError = err
 		return p
 	}
@@ -240,14 +246,14 @@ func (p *PreDownloadProcess) ChangeSubNameFormat() *PreDownloadProcess {
 func (p *PreDownloadProcess) ReloadBrowser() *PreDownloadProcess {
 
 	if p.gError != nil {
-		log_helper.GetLogger().Infoln("Skip PreDownloadProcess.ReloadBrowser()")
+		p.log.Infoln("Skip PreDownloadProcess.ReloadBrowser()")
 		return p
 	}
 	p.stageName = stageNameReloadBrowser
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.ReloadBrowser() End")
+		p.log.Infoln("PreDownloadProcess.ReloadBrowser() End")
 	}()
-	log_helper.GetLogger().Infoln("PreDownloadProcess.ReloadBrowser() Start...")
+	p.log.Infoln("PreDownloadProcess.ReloadBrowser() Start...")
 	// ------------------------------------------------------------------------
 	// ReloadBrowser 提前把浏览器下载好
 	rod_helper.ReloadBrowser()
@@ -256,11 +262,11 @@ func (p *PreDownloadProcess) ReloadBrowser() *PreDownloadProcess {
 
 func (p *PreDownloadProcess) Wait() error {
 	defer func() {
-		log_helper.GetLogger().Infoln("PreDownloadProcess.Wait() Done.")
+		p.log.Infoln("PreDownloadProcess.Wait() Done.")
 	}()
 	if p.gError != nil {
 		outErrString := "PreDownloadProcess.Wait() Get Error, " + "stageName:" + p.stageName + " -- " + p.gError.Error()
-		log_helper.GetLogger().Errorln(outErrString)
+		p.log.Errorln(outErrString)
 		return errors.New(outErrString)
 	} else {
 		return nil

+ 23 - 14
internal/logic/sub_supplier/shooter/shooter.go

@@ -5,16 +5,15 @@ import (
 	"errors"
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/task_queue"
 	pkgcommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/decode"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/language"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
-	"github.com/huandu/go-clone"
 	"github.com/sirupsen/logrus"
 	"math"
 	"os"
@@ -24,20 +23,20 @@ import (
 )
 
 type Supplier struct {
-	settings settings.Settings
+	settings *settings.Settings
 	log      *logrus.Logger
 	topic    int
 	isAlive  bool
 }
 
-func NewSupplier(_settings settings.Settings) *Supplier {
+func NewSupplier(_settings *settings.Settings, _logger *logrus.Logger) *Supplier {
 
 	sup := Supplier{}
-	sup.log = log_helper.GetLogger()
+	sup.log = _logger
 	sup.topic = common.DownloadSubsPerSite
 	sup.isAlive = true // 默认是可以使用的,如果 check 后,再调整状态
 
-	sup.settings = clone.Clone(_settings).(settings.Settings)
+	sup.settings = _settings
 	if sup.settings.AdvancedSettings.Topic > 0 && sup.settings.AdvancedSettings.Topic != sup.topic {
 		sup.topic = sup.settings.AdvancedSettings.Topic
 	}
@@ -63,23 +62,28 @@ func (s *Supplier) IsAlive() bool {
 	return s.isAlive
 }
 
-func (s Supplier) GetSupplierName() string {
+func (s *Supplier) OverDailyDownloadLimit() bool {
+	// 对于这个接口暂时没有限制
+	return false
+}
+
+func (s *Supplier) GetSupplierName() string {
 	return common.SubSiteShooter
 }
 
-func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
 	return s.getSubListFromFile(filePath)
 }
 
-func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	return s.downloadSub4Series(seriesInfo)
 }
 
-func (s Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	return s.downloadSub4Series(seriesInfo)
 }
 
-func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error) {
 
 	defer func() {
 		s.log.Debugln(s.GetSupplierName(), filePath, "End...")
@@ -133,6 +137,11 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 				s.log.Error(err)
 				continue
 			}
+			// 下载成功需要统计到今天的次数中
+			_, err = task_queue.AddDailyDownloadCount(s.GetSupplierName())
+			if err != nil {
+				s.log.Warningln(s.GetSupplierName(), "getSubListFromFile.AddDailyDownloadCount", err)
+			}
 
 			onSub := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, language.ChineseSimple, file.Link, 0, shooter.Delay, subExt, data)
 			outSubInfoList = append(outSubInfoList, *onSub)
@@ -147,7 +156,7 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 	return outSubInfoList, nil
 }
 
-func (s Supplier) getSubInfos(fileHash, fileName, qLan string) ([]SublistShooter, error) {
+func (s *Supplier) getSubInfos(fileHash, fileName, qLan string) ([]SublistShooter, error) {
 
 	var jsonList []SublistShooter
 
@@ -160,7 +169,7 @@ func (s Supplier) getSubInfos(fileHash, fileName, qLan string) ([]SublistShooter
 			"lang":     qLan,
 		}).
 		SetResult(&jsonList).
-		Post(common.SubShooterRootUrl)
+		Post(s.settings.SuppliersSettings.Shooter.RootUrl)
 	if err != nil {
 		if resp != nil {
 			s.log.Errorln(s.GetSupplierName(), "NewHttpClient:", fileName, err.Error())
@@ -212,7 +221,7 @@ func ComputeFileHash(filePath string) (string, error) {
 	return hash, nil
 }
 
-func (s Supplier) downloadSub4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) downloadSub4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	var allSupplierSubInfo = make([]supplier.SubInfo, 0)
 
 	index := 0

+ 11 - 10
internal/logic/sub_supplier/subSupplierHub.go

@@ -5,7 +5,6 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/ifaces"
 	movieHelper "github.com/allanpk716/ChineseSubFinder/internal/logic/movie_helper"
 	seriesHelper "github.com/allanpk716/ChineseSubFinder/internal/logic/series_helper"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_helper"
@@ -18,17 +17,17 @@ import (
 )
 
 type SubSupplierHub struct {
-	settings settings.Settings
+	settings *settings.Settings
 
 	Suppliers []ifaces.ISupplier
 
 	log *logrus.Logger
 }
 
-func NewSubSupplierHub(_settings settings.Settings, one ifaces.ISupplier, _inSupplier ...ifaces.ISupplier) *SubSupplierHub {
+func NewSubSupplierHub(_settings *settings.Settings, _logger *logrus.Logger, one ifaces.ISupplier, _inSupplier ...ifaces.ISupplier) *SubSupplierHub {
 	s := SubSupplierHub{}
 	s.settings = _settings
-	s.log = log_helper.GetLogger()
+	s.log = _logger
 	s.Suppliers = make([]ifaces.ISupplier, 0)
 	s.Suppliers = append(s.Suppliers, one)
 	if len(_inSupplier) > 0 {
@@ -56,7 +55,7 @@ func (d *SubSupplierHub) DelSubSupplier(one ifaces.ISupplier) {
 }
 
 // DownloadSub4Movie 某一个电影字幕下载,下载完毕后,返回下载缓存每个字幕的位置
-func (d SubSupplierHub) DownloadSub4Movie(videoFullPath string, index int, forcedScanAndDownloadSub bool) ([]string, error) {
+func (d *SubSupplierHub) DownloadSub4Movie(videoFullPath string, index int, forcedScanAndDownloadSub bool) ([]string, error) {
 
 	if forcedScanAndDownloadSub == false {
 		// 非强制扫描的时候,需要判断这个视频根目录是否有 .ignore 文件,有也跳过
@@ -112,7 +111,7 @@ func (d SubSupplierHub) DownloadSub4Movie(videoFullPath string, index int, force
 }
 
 // DownloadSub4Series 某一部连续剧的字幕下载,下载完毕后,返回下载缓存每个字幕的位置
-func (d SubSupplierHub) DownloadSub4Series(seriesDirPath string, index int, forcedScanAndDownloadSub bool) (*series.SeriesInfo, map[string][]string, error) {
+func (d *SubSupplierHub) DownloadSub4Series(seriesDirPath string, index int, forcedScanAndDownloadSub bool) (*series.SeriesInfo, map[string][]string, error) {
 
 	if forcedScanAndDownloadSub == false {
 		// 非强制扫描的时候,需要判断这个视频根目录是否有 .ignore 文件,有也跳过
@@ -144,7 +143,7 @@ func (d SubSupplierHub) DownloadSub4Series(seriesDirPath string, index int, forc
 }
 
 // DownloadSub4SeriesFromEmby 通过 Emby 查询到的信息进行字幕下载,下载完毕后,返回下载缓存每个字幕的位置
-func (d SubSupplierHub) DownloadSub4SeriesFromEmby(seriesDirPath string, seriesList []emby.EmbyMixInfo, index int) (*series.SeriesInfo, map[string][]string, error) {
+func (d *SubSupplierHub) DownloadSub4SeriesFromEmby(seriesDirPath string, seriesList []emby.EmbyMixInfo, index int) (*series.SeriesInfo, map[string][]string, error) {
 
 	// 跳过中文的连续剧,不是一定要跳过的
 	skip, imdbInfo, err := seriesHelper.SkipChineseSeries(seriesDirPath, *d.settings.AdvancedSettings.ProxySettings)
@@ -166,7 +165,7 @@ func (d SubSupplierHub) DownloadSub4SeriesFromEmby(seriesDirPath string, seriesL
 	return seriesInfo, organizeSubFiles, nil
 }
 
-// CheckSubSiteStatus 检测多个字幕提供的网站是否是有效的
+// CheckSubSiteStatus 检测多个字幕提供的网站是否是有效的,是否下载次数超限
 func (d *SubSupplierHub) CheckSubSiteStatus() backend.ReplyCheckStatus {
 
 	outStatus := backend.ReplyCheckStatus{
@@ -192,7 +191,9 @@ func (d *SubSupplierHub) CheckSubSiteStatus() backend.ReplyCheckStatus {
 
 	suppliersLen := len(d.Suppliers)
 	for i := 0; i < suppliersLen; {
-		if d.Suppliers[i].IsAlive() == false {
+
+		// 网络检测是否有效,以及每次的下载次数限制检测
+		if d.Suppliers[i].IsAlive() == false || d.Suppliers[i].OverDailyDownloadLimit() == true {
 
 			d.DelSubSupplier(d.Suppliers[i])
 			// 删除后,从头再来
@@ -208,7 +209,7 @@ func (d *SubSupplierHub) CheckSubSiteStatus() backend.ReplyCheckStatus {
 	return outStatus
 }
 
-func (d SubSupplierHub) dlSubFromSeriesInfo(seriesDirPath string, index int, seriesInfo *series.SeriesInfo, err error) (map[string][]string, error) {
+func (d *SubSupplierHub) dlSubFromSeriesInfo(seriesDirPath string, index int, seriesInfo *series.SeriesInfo, err error) (map[string][]string, error) {
 	// 下载好的字幕
 	subInfos := seriesHelper.DownloadSubtitleInAllSiteByOneSeries(d.Suppliers, seriesInfo, index)
 	// 整理字幕,比如解压什么的

+ 59 - 28
internal/logic/sub_supplier/subhd/subhd.go

@@ -6,10 +6,10 @@ import (
 	"github.com/PuerkitoBio/goquery"
 	"github.com/Tnze/go.num/v2/zh"
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/task_queue"
 	pkgcommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/decode"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
@@ -20,7 +20,6 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/go-rod/rod"
-	"github.com/huandu/go-clone"
 	"github.com/nfnt/resize"
 	"github.com/sirupsen/logrus"
 	"image/jpeg"
@@ -34,7 +33,7 @@ import (
 )
 
 type Supplier struct {
-	settings  settings.Settings
+	settings  *settings.Settings
 	log       *logrus.Logger
 	topic     int
 	tt        time.Duration
@@ -42,13 +41,13 @@ type Supplier struct {
 	isAlive   bool
 }
 
-func NewSupplier(_settings settings.Settings) *Supplier {
+func NewSupplier(_settings *settings.Settings, _logger *logrus.Logger) *Supplier {
 
 	sup := Supplier{}
-	sup.log = log_helper.GetLogger()
+	sup.log = _logger
 	sup.topic = common.DownloadSubsPerSite
 
-	sup.settings = clone.Clone(_settings).(settings.Settings)
+	sup.settings = _settings
 	if sup.settings.AdvancedSettings.Topic > 0 && sup.settings.AdvancedSettings.Topic != sup.topic {
 		sup.topic = sup.settings.AdvancedSettings.Topic
 	}
@@ -66,7 +65,7 @@ func NewSupplier(_settings settings.Settings) *Supplier {
 
 func (s *Supplier) CheckAlive() (bool, int64) {
 
-	proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(common.SubSubHDRootUrl, s.settings.AdvancedSettings.ProxySettings.HttpProxyAddress)
+	proxyStatus, proxySpeed, err := url_connectedness_helper.UrlConnectednessTest(s.settings.SuppliersSettings.SubHD.RootUrl, s.settings.AdvancedSettings.ProxySettings.HttpProxyAddress)
 	if err != nil {
 		s.log.Errorln(s.GetSupplierName(), "CheckAlive", "Error", err)
 		s.isAlive = false
@@ -86,15 +85,31 @@ func (s *Supplier) IsAlive() bool {
 	return s.isAlive
 }
 
-func (s Supplier) GetSupplierName() string {
+func (s *Supplier) OverDailyDownloadLimit() bool {
+
+	// 需要查询今天的限额
+	count, err := task_queue.GetDailyDownloadCount(s.GetSupplierName())
+	if err != nil {
+		s.log.Errorln(s.GetSupplierName(), "GetDailyDownloadCount", err)
+		return true
+	}
+	if count > s.settings.SuppliersSettings.Zimuku.DailyDownloadLimit {
+		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit:", s.settings.SuppliersSettings.SubHD.DailyDownloadLimit, "Now Is:", count)
+		return true
+	}
+	// 没有超限
+	return false
+}
+
+func (s *Supplier) GetSupplierName() string {
 	return common.SubSiteSubHd
 }
 
-func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
 	return s.getSubListFromFile4Movie(filePath)
 }
 
-func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 
 	var browser *rod.Browser
 	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
@@ -157,7 +172,12 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 			s.log.Errorln("subhd step2Ex return false")
 			continue
 		}
-		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, language.ChineseSimple, my_util.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0,
+		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(),
+			int64(i),
+			hdContent.Filename,
+			language.ChineseSimple,
+			my_util.AddBaseUrl(s.settings.SuppliersSettings.SubHD.RootUrl, item.Url),
+			0,
 			0, hdContent.Ext, hdContent.Data)
 		oneSubInfo.Season = item.Season
 		oneSubInfo.Episode = item.Episode
@@ -167,11 +187,11 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 	return subInfos, nil
 }
 
-func (s Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	panic("not implemented")
 }
 
-func (s Supplier) getSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) getSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
 	/*
 		虽然是传入视频文件路径,但是其实需要读取对应的视频文件目录下的
 		movie.xml 以及 *.nfo,找到 IMDB id
@@ -217,7 +237,7 @@ func (s Supplier) getSubListFromFile4Movie(filePath string) ([]supplier.SubInfo,
 	return subInfoList, nil
 }
 
-func (s Supplier) getSubListFromKeyword4Movie(keyword string) ([]supplier.SubInfo, error) {
+func (s *Supplier) getSubListFromKeyword4Movie(keyword string) ([]supplier.SubInfo, error) {
 
 	var browser *rod.Browser
 	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
@@ -253,13 +273,18 @@ func (s Supplier) getSubListFromKeyword4Movie(keyword string) ([]supplier.SubInf
 			s.log.Errorln("subhd step2Ex return false")
 			continue
 		}
-		subInfos = append(subInfos, *supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, language.ChineseSimple, my_util.AddBaseUrl(common.SubSubHDRootUrl, item.Url), 0, 0, hdContent.Ext, hdContent.Data))
+		subInfos = append(subInfos, *supplier.NewSubInfo(s.GetSupplierName(), int64(i), hdContent.Filename, language.ChineseSimple,
+			my_util.AddBaseUrl(s.settings.SuppliersSettings.SubHD.RootUrl, item.Url),
+			0,
+			0,
+			hdContent.Ext,
+			hdContent.Data))
 	}
 
 	return subInfos, nil
 }
 
-func (s Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, allSubList []HdListItem) []HdListItem {
+func (s *Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, allSubList []HdListItem) []HdListItem {
 	// 字幕很多,考虑效率,需要做成字典
 	// key SxEx - SubInfos
 	var allSubDict = make(map[string][]HdListItem)
@@ -314,7 +339,7 @@ func (s Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, all
 }
 
 // step0 找到这个影片的详情列表
-func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
+func (s *Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 	var err error
 	defer func() {
 		if err != nil {
@@ -322,7 +347,7 @@ func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 		}
 	}()
 
-	result, page, err := rod_helper.HttpGetFromBrowser(browser, fmt.Sprintf(common.SubSubHDSearchUrl, url.QueryEscape(keyword)), s.tt)
+	result, page, err := rod_helper.HttpGetFromBrowser(browser, fmt.Sprintf(s.settings.SuppliersSettings.SubHD.RootUrl+common.SubSubHDSearchUrl, url.QueryEscape(keyword)), s.tt)
 	if err != nil {
 		return "", err
 	}
@@ -383,14 +408,14 @@ func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 }
 
 // step1 获取影片的详情字幕列表
-func (s Supplier) step1(browser *rod.Browser, detailPageUrl string, isMovieOrSeries bool) ([]HdListItem, error) {
+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 = my_util.AddBaseUrl(common.SubSubHDRootUrl, detailPageUrl)
+	detailPageUrl = my_util.AddBaseUrl(s.settings.SuppliersSettings.SubHD.RootUrl, detailPageUrl)
 	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailPageUrl, s.tt)
 	if err != nil {
 		return nil, err
@@ -433,7 +458,7 @@ func (s Supplier) step1(browser *rod.Browser, detailPageUrl string, isMovieOrSer
 
 		listItem := HdListItem{}
 		listItem.Url = downUrl
-		listItem.BaseUrl = common.SubSubHDRootUrl
+		listItem.BaseUrl = s.settings.SuppliersSettings.SubHD.RootUrl
 		listItem.Title = title
 		listItem.DownCount = downCount
 
@@ -453,14 +478,14 @@ func (s Supplier) step1(browser *rod.Browser, detailPageUrl string, isMovieOrSer
 }
 
 // step2Ex 下载字幕 过防水墙
-func (s Supplier) step2Ex(browser *rod.Browser, subDownloadPageUrl string) (bool, *HdContent, error) {
+func (s *Supplier) step2Ex(browser *rod.Browser, subDownloadPageUrl string) (bool, *HdContent, error) {
 	var err error
 	defer func() {
 		if err != nil {
 			notify_center.Notify.Add("subhd_step2Ex", err.Error())
 		}
 	}()
-	subDownloadPageUrl = my_util.AddBaseUrl(common.SubSubHDRootUrl, subDownloadPageUrl)
+	subDownloadPageUrl = my_util.AddBaseUrl(s.settings.SuppliersSettings.SubHD.RootUrl, subDownloadPageUrl)
 
 	_, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageUrl, s.tt)
 	if err != nil {
@@ -483,7 +508,7 @@ func (s Supplier) step2Ex(browser *rod.Browser, subDownloadPageUrl string) (bool
 	return true, content, nil
 }
 
-func (s Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *HdContent, error) {
+func (s *Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *HdContent, error) {
 
 	var err error
 	var doc *goquery.Document
@@ -533,7 +558,7 @@ func (s Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *
 			element = page.MustElement(btnCommitCode)
 			benCommit := element.MustText()
 			if strings.Contains(benCommit, "验证") == false {
-				log_helper.GetLogger().Errorln("btn not found 完整验证")
+				s.log.Errorln("btn not found 完整验证")
 				return
 			}
 			element.MustClick()
@@ -548,7 +573,7 @@ func (s Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *
 			time.Sleep(time.Second * 2)
 		} else {
 
-			log_helper.GetLogger().Errorln("btn not found 下载验证 or 下载")
+			s.log.Errorln("btn not found 下载验证 or 下载")
 			return
 		}
 		// 更新 page 的实例对应的 doc Content
@@ -563,7 +588,7 @@ func (s Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *
 		if len(waterWall.Nodes) >= 1 {
 			hasWaterWall = true
 		}
-		log_helper.GetLogger().Debugln("Need pass WaterWall", hasWaterWall)
+		s.log.Debugln("Need pass WaterWall", hasWaterWall)
 		// 过墙
 		if hasWaterWall == true {
 			s.passWaterWall(page)
@@ -587,10 +612,16 @@ func (s Supplier) downloadSubFile(browser *rod.Browser, page *rod.Page) (bool, *
 		return false, &hdContent, common.SubHDStep2ExCannotFindDownloadBtn
 	}
 
+	// 下载成功需要统计到今天的次数中
+	_, err = task_queue.AddDailyDownloadCount(s.GetSupplierName())
+	if err != nil {
+		s.log.Warningln(s.GetSupplierName(), "getSubListFromFile.AddDailyDownloadCount", err)
+	}
+
 	return downloadSuccess, &hdContent, nil
 }
 
-func (s Supplier) passWaterWall(page *rod.Page) {
+func (s *Supplier) passWaterWall(page *rod.Page) {
 	//等待驗證碼窗體載入
 	page.MustElement("#tcaptcha_iframe").MustWaitLoad()
 	//進入到iframe

+ 24 - 15
internal/logic/sub_supplier/xunlei/xunlei.go

@@ -5,17 +5,16 @@ import (
 	"errors"
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/task_queue"
 	pkgcommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/decode"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
-	"github.com/huandu/go-clone"
 	"github.com/sirupsen/logrus"
 	"math"
 	"os"
@@ -24,20 +23,20 @@ import (
 )
 
 type Supplier struct {
-	settings settings.Settings
+	settings *settings.Settings
 	log      *logrus.Logger
 	topic    int
 	isAlive  bool
 }
 
-func NewSupplier(_settings settings.Settings) *Supplier {
+func NewSupplier(_settings *settings.Settings, _logger *logrus.Logger) *Supplier {
 
 	sup := Supplier{}
-	sup.log = log_helper.GetLogger()
+	sup.log = _logger
 	sup.topic = common.DownloadSubsPerSite
 	sup.isAlive = true // 默认是可以使用的,如果 check 后,再调整状态
 
-	sup.settings = clone.Clone(_settings).(settings.Settings)
+	sup.settings = _settings
 	if sup.settings.AdvancedSettings.Topic > 0 && sup.settings.AdvancedSettings.Topic != sup.topic {
 		sup.topic = sup.settings.AdvancedSettings.Topic
 	}
@@ -70,23 +69,28 @@ func (s *Supplier) IsAlive() bool {
 	return s.isAlive
 }
 
-func (s Supplier) GetSupplierName() string {
+func (s *Supplier) OverDailyDownloadLimit() bool {
+	// 对于这个接口暂时没有限制
+	return false
+}
+
+func (s *Supplier) GetSupplierName() string {
 	return common.SubSiteXunLei
 }
 
-func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
 	return s.getSubListFromFile(filePath)
 }
 
-func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	return s.downloadSub4Series(seriesInfo)
 }
 
-func (s Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	return s.downloadSub4Series(seriesInfo)
 }
 
-func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error) {
 
 	defer func() {
 		s.log.Debugln(s.GetSupplierName(), filePath, "End...")
@@ -156,6 +160,11 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 			s.log.Errorln("xunlei pkg.DownFile:", err)
 			continue
 		}
+		// 下载成功需要统计到今天的次数中
+		_, err = task_queue.AddDailyDownloadCount(s.GetSupplierName())
+		if err != nil {
+			s.log.Warningln(s.GetSupplierName(), "getSubListFromFile.AddDailyDownloadCount", err)
+		}
 		ext := ""
 		if filename == "" {
 			ext = filepath.Ext(v.Surl)
@@ -169,13 +178,13 @@ func (s Supplier) getSubListFromFile(filePath string) ([]supplier.SubInfo, error
 	return outSubList, nil
 }
 
-func (s Supplier) getSubInfos(filePath, cid string) (SublistSliceXunLei, error) {
+func (s *Supplier) getSubInfos(filePath, cid string) (SublistSliceXunLei, error) {
 	var jsonList SublistSliceXunLei
 
 	httpClient := my_util.NewHttpClient(*s.settings.AdvancedSettings.ProxySettings)
 	resp, err := httpClient.R().
 		SetResult(&jsonList).
-		Get(fmt.Sprintf(common.SubXunLeiRootUrl, cid))
+		Get(fmt.Sprintf(s.settings.SuppliersSettings.Xunlei.RootUrl, cid))
 	if err != nil {
 		if resp != nil {
 			s.log.Errorln(s.GetSupplierName(), "NewHttpClient:", filePath, err.Error())
@@ -188,7 +197,7 @@ func (s Supplier) getSubInfos(filePath, cid string) (SublistSliceXunLei, error)
 }
 
 //getCid 获取指定文件的唯一 cid
-func (s Supplier) getCid(filePath string) (string, error) {
+func (s *Supplier) getCid(filePath string) (string, error) {
 	hash := ""
 	sha1Ctx := sha1.New()
 
@@ -226,7 +235,7 @@ func (s Supplier) getCid(filePath string) (string, error) {
 	return hash, nil
 }
 
-func (s Supplier) downloadSub4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) downloadSub4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 	var allSupplierSubInfo = make([]supplier.SubInfo, 0)
 	index := 0
 	// 这里拿到的 seriesInfo ,里面包含了,需要下载字幕的 Eps 信息

+ 51 - 29
internal/logic/sub_supplier/zimuku/zimuku.go

@@ -5,11 +5,11 @@ import (
 	"github.com/PuerkitoBio/goquery"
 	"github.com/Tnze/go.num/v2/zh"
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/task_queue"
 	pkgcommon "github.com/allanpk716/ChineseSubFinder/internal/pkg/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/decode"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
-	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/notify_center"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
@@ -19,7 +19,6 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/types/series"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/supplier"
 	"github.com/go-rod/rod"
-	"github.com/huandu/go-clone"
 	"github.com/sirupsen/logrus"
 	"net/url"
 	"os"
@@ -31,7 +30,7 @@ import (
 )
 
 type Supplier struct {
-	settings         settings.Settings
+	settings         *settings.Settings
 	log              *logrus.Logger
 	tt               time.Duration
 	debugMode        bool
@@ -40,14 +39,14 @@ type Supplier struct {
 	isAlive          bool
 }
 
-func NewSupplier(_settings settings.Settings) *Supplier {
+func NewSupplier(_settings *settings.Settings, _logger *logrus.Logger) *Supplier {
 
 	sup := Supplier{}
-	sup.log = log_helper.GetLogger()
+	sup.log = _logger
 	sup.topic = common.DownloadSubsPerSite
 	sup.isAlive = true // 默认是可以使用的,如果 check 后,再调整状态
 
-	sup.settings = clone.Clone(_settings).(settings.Settings)
+	sup.settings = _settings
 	if sup.settings.AdvancedSettings.Topic > 0 && sup.settings.AdvancedSettings.Topic != sup.topic {
 		sup.topic = sup.settings.AdvancedSettings.Topic
 	}
@@ -71,7 +70,7 @@ func NewSupplier(_settings settings.Settings) *Supplier {
 func (s *Supplier) CheckAlive() (bool, int64) {
 
 	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	browser, err := rod_helper.NewBrowserEx(true, s.settings, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowserEx(true, s.settings, s.settings.SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		return false, 0
 	}
@@ -80,7 +79,7 @@ func (s *Supplier) CheckAlive() (bool, int64) {
 	}()
 
 	begin := time.Now() //判断代理访问时间
-	_, page, err := rod_helper.HttpGetFromBrowser(browser, common.SubZiMuKuRootUrl, 15*time.Second)
+	_, page, err := rod_helper.HttpGetFromBrowser(browser, s.settings.SuppliersSettings.Zimuku.RootUrl, 15*time.Second)
 	if err != nil {
 		return false, 0
 	}
@@ -94,14 +93,30 @@ func (s *Supplier) IsAlive() bool {
 	return s.isAlive
 }
 
-func (s Supplier) GetSupplierName() string {
+func (s *Supplier) OverDailyDownloadLimit() bool {
+
+	// 需要查询今天的限额
+	count, err := task_queue.GetDailyDownloadCount(s.GetSupplierName())
+	if err != nil {
+		s.log.Errorln(s.GetSupplierName(), "GetDailyDownloadCount", err)
+		return true
+	}
+	if count > s.settings.SuppliersSettings.Zimuku.DailyDownloadLimit {
+		s.log.Warningln(s.GetSupplierName(), "DailyDownloadLimit:", s.settings.SuppliersSettings.Zimuku.DailyDownloadLimit, "Now Is:", count)
+		return true
+	}
+	// 没有超限
+	return false
+}
+
+func (s *Supplier) GetSupplierName() string {
 	return common.SubSiteZiMuKu
 }
 
-func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo, error) {
 
 	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	browser, err := rod_helper.NewBrowserEx(true, s.settings, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowserEx(true, s.settings, s.settings.SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		return nil, err
 	}
@@ -112,7 +127,7 @@ func (s Supplier) GetSubListFromFile4Movie(filePath string) ([]supplier.SubInfo,
 	return s.getSubListFromMovie(browser, filePath)
 }
 
-func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
 
 	defer func() {
 		s.log.Debugln(s.GetSupplierName(), seriesInfo.Name, "End...")
@@ -122,7 +137,7 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 
 	var err error
 	// TODO 是用本地的 Browser 还是远程的,推荐是远程的
-	browser, err := rod_helper.NewBrowserEx(true, s.settings, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowserEx(true, s.settings, s.settings.SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		return nil, err
 	}
@@ -183,11 +198,11 @@ func (s Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]su
 	return outSubInfoList, nil
 }
 
-func (s Supplier) GetSubListFromFile4Anime(seriesInfo *series.SeriesInfo) ([]supplier.SubInfo, error) {
+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) {
+func (s *Supplier) getSubListFromMovie(browser *rod.Browser, fileFPath string) ([]supplier.SubInfo, error) {
 
 	defer func() {
 		s.log.Debugln(s.GetSupplierName(), fileFPath, "End...")
@@ -253,7 +268,7 @@ func (s Supplier) getSubListFromMovie(browser *rod.Browser, fileFPath string) ([
 	return subInfoList, nil
 }
 
-func (s Supplier) getSubListFromKeyword(browser *rod.Browser, keyword string) ([]supplier.SubInfo, error) {
+func (s *Supplier) getSubListFromKeyword(browser *rod.Browser, keyword string) ([]supplier.SubInfo, error) {
 
 	var outSubInfoList []supplier.SubInfo
 	// 第一级界面,找到影片的详情界面
@@ -285,7 +300,7 @@ func (s Supplier) getSubListFromKeyword(browser *rod.Browser, keyword string) ([
 	return outSubInfoList, nil
 }
 
-func (s Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, AllSeasonSubResult SubResult) []SubInfo {
+func (s *Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, AllSeasonSubResult SubResult) []SubInfo {
 	// 字幕很多,考虑效率,需要做成字典
 	// key SxEx - SubInfos
 	var allSubDict = make(map[string]SubInfos)
@@ -340,7 +355,7 @@ func (s Supplier) whichEpisodeNeedDownloadSub(seriesInfo *series.SeriesInfo, All
 	return subInfoNeedDownload
 }
 
-func (s Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInfos, err error) []supplier.SubInfo {
+func (s *Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInfos, err error) []supplier.SubInfo {
 
 	var outSubInfoList = make([]supplier.SubInfo, 0)
 	for i := range subInfos {
@@ -398,7 +413,8 @@ func (s Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInf
 		}
 		// 默认都是包含中文字幕的,然后具体使用的时候再进行区分
 
-		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, language2.ChineseSimple, my_util.AddBaseUrl(common.SubZiMuKuRootUrl, subInfo.SubDownloadPageUrl), 0,
+		oneSubInfo := supplier.NewSubInfo(s.GetSupplierName(), int64(i), fileName, language2.ChineseSimple,
+			my_util.AddBaseUrl(s.settings.SuppliersSettings.Zimuku.RootUrl, subInfo.SubDownloadPageUrl), 0,
 			0, filepath.Ext(fileName), data)
 
 		oneSubInfo.Season = subInfo.Season
@@ -415,7 +431,7 @@ func (s Supplier) whichSubInfoNeedDownload(browser *rod.Browser, subInfos SubInf
 }
 
 // step0 先在查询界面找到字幕对应第一个影片的详情界面,需要解决自定义错误 ZiMuKuSearchKeyWordStep0DetailPageUrlNotFound
-func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
+func (s *Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 	var err error
 	defer func() {
 		if err != nil {
@@ -423,7 +439,7 @@ func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 		}
 	}()
 
-	desUrl := fmt.Sprintf(common.SubZiMuKuSearchFormatUrl, url.QueryEscape(keyword))
+	desUrl := fmt.Sprintf(s.settings.SuppliersSettings.Zimuku.RootUrl+common.SubZiMuKuSearchFormatUrl, url.QueryEscape(keyword))
 	result, page, err := rod_helper.HttpGetFromBrowser(browser, desUrl, s.tt)
 	if err != nil {
 		return "", err
@@ -443,7 +459,7 @@ func (s Supplier) step0(browser *rod.Browser, keyword string) (string, error) {
 }
 
 // step1 分析详情界面,找到有多少个字幕
-func (s Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResult, error) {
+func (s *Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResult, error) {
 	var err error
 	defer func() {
 		if err != nil {
@@ -454,7 +470,7 @@ func (s Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResu
 	var subResult SubResult
 	subResult.SubInfos = SubInfos{}
 
-	filmDetailPageUrl = my_util.AddBaseUrl(common.SubZiMuKuRootUrl, filmDetailPageUrl)
+	filmDetailPageUrl = my_util.AddBaseUrl(s.settings.SuppliersSettings.Zimuku.RootUrl, filmDetailPageUrl)
 
 	result, page, err := rod_helper.HttpGetFromBrowser(browser, filmDetailPageUrl, s.tt)
 	if err != nil {
@@ -548,14 +564,14 @@ func (s Supplier) step1(browser *rod.Browser, filmDetailPageUrl string) (SubResu
 }
 
 // step2 第二级界面,单个字幕详情,需要判断 ZiMuKuDownloadUrlStep2NotFound 这个自定义错误
-func (s Supplier) step2(browser *rod.Browser, subInfo *SubInfo) error {
+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 := my_util.AddBaseUrl(common.SubZiMuKuRootUrl, subInfo.DetailUrl)
+	detailUrl := my_util.AddBaseUrl(s.settings.SuppliersSettings.Zimuku.RootUrl, subInfo.DetailUrl)
 	result, page, err := rod_helper.HttpGetFromBrowser(browser, detailUrl, s.tt)
 	if err != nil {
 		return err
@@ -573,20 +589,20 @@ func (s Supplier) step2(browser *rod.Browser, subInfo *SubInfo) error {
 	if strings.Contains(matched[0][1], "://") {
 		subInfo.SubDownloadPageUrl = matched[0][1]
 	} else {
-		subInfo.SubDownloadPageUrl = fmt.Sprintf("%s%s", common.SubZiMuKuRootUrl, matched[0][1])
+		subInfo.SubDownloadPageUrl = fmt.Sprintf("%s%s", s.settings.SuppliersSettings.Zimuku.RootUrl, matched[0][1])
 	}
 	return nil
 }
 
 // step3 第三级界面,具体字幕下载 ZiMuKuDownloadUrlStep3NotFound ZiMuKuDownloadUrlStep3AllFailed
-func (s Supplier) step3(browser *rod.Browser, subDownloadPageUrl string) (string, []byte, error) {
+func (s *Supplier) step3(browser *rod.Browser, subDownloadPageUrl string) (string, []byte, error) {
 	var err error
 	defer func() {
 		if err != nil {
 			notify_center.Notify.Add("zimuku_step3", err.Error())
 		}
 	}()
-	subDownloadPageUrl = my_util.AddBaseUrl(common.SubZiMuKuRootUrl, subDownloadPageUrl)
+	subDownloadPageUrl = my_util.AddBaseUrl(s.settings.SuppliersSettings.Zimuku.RootUrl, subDownloadPageUrl)
 	result, page, err := rod_helper.HttpGetFromBrowser(browser, subDownloadPageUrl, s.tt)
 	if err != nil {
 		return "", nil, err
@@ -633,9 +649,15 @@ func (s Supplier) step3(browser *rod.Browser, subDownloadPageUrl string) (string
 		s.log.Errorln("ZiMuKu step3 DownloadFile", err)
 		return "", nil, err
 	}
-
 	if downloadSuccess == true {
 		s.log.Debugln("Step3,DownFile, FileName:", fileName, "DataLen:", len(fileByte))
+
+		// 下载成功需要统计到今天的次数中
+		_, err = task_queue.AddDailyDownloadCount(s.GetSupplierName())
+		if err != nil {
+			s.log.Warningln(s.GetSupplierName(), "getSubListFromFile.AddDailyDownloadCount", err)
+		}
+
 		return fileName, fileByte, nil
 	} else {
 		s.log.Debugln("Step3,sub download url not found", subDownloadPageUrl)

+ 9 - 9
internal/logic/sub_supplier/zimuku/zimuku_test.go

@@ -1,8 +1,8 @@
 package zimuku
 
 import (
-	"github.com/allanpk716/ChineseSubFinder/internal/common"
 	"github.com/allanpk716/ChineseSubFinder/internal/logic/series_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/rod_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/unit_test_helper"
@@ -12,7 +12,7 @@ import (
 
 func TestSupplier_GetSubListFromKeyword(t *testing.T) {
 
-	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowser("", true, settings.NewSettings().SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -22,7 +22,7 @@ func TestSupplier_GetSubListFromKeyword(t *testing.T) {
 
 	//imdbId1 := "tt3228774"
 	videoName := "黑白魔女库伊拉"
-	s := NewSupplier(*settings.NewSettings())
+	s := NewSupplier(settings.NewSettings(), log_helper.GetLogger())
 	outList, err := s.getSubListFromKeyword(browser, videoName)
 	if err != nil {
 		t.Error(err)
@@ -35,7 +35,7 @@ func TestSupplier_GetSubListFromKeyword(t *testing.T) {
 
 func TestSupplier_GetSubListFromFile(t *testing.T) {
 
-	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowser("", true, settings.NewSettings().SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -52,7 +52,7 @@ func TestSupplier_GetSubListFromFile(t *testing.T) {
 
 	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")
-	s := NewSupplier(*settings.NewSettings())
+	s := NewSupplier(settings.NewSettings(), log_helper.GetLogger())
 	outList, err := s.getSubListFromMovie(browser, movie1)
 	if err != nil {
 		t.Error(err)
@@ -84,7 +84,7 @@ func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
 	//epsMap[1] = 4
 	//series_helper2.SetTheSpecifiedEps2Download(seriesInfo, epsMap)
 
-	s := NewSupplier(*settings.NewSettings())
+	s := NewSupplier(settings.NewSettings(), log_helper.GetLogger())
 	outList, err := s.GetSubListFromFile4Series(seriesInfo)
 	if err != nil {
 		t.Fatal(err)
@@ -97,7 +97,7 @@ func TestSupplier_GetSubListFromFile4Series(t *testing.T) {
 
 func TestSupplier_getSubListFromKeyword(t *testing.T) {
 
-	browser, err := rod_helper.NewBrowser("", true, common.SubZiMuKuRootUrl)
+	browser, err := rod_helper.NewBrowser("", true, settings.NewSettings().SuppliersSettings.Zimuku.RootUrl)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -113,7 +113,7 @@ func TestSupplier_getSubListFromKeyword(t *testing.T) {
 	//imdbID := "tt15299712" // 云南虫谷
 	//imdbID := "tt3626476"  // Vacation Friends (2021)
 	imdbID := "tt11192306" // Superman.and.Lois
-	zimuku := NewSupplier(*settings.NewSettings())
+	zimuku := NewSupplier(settings.NewSettings(), log_helper.GetLogger())
 	subInfos, err := zimuku.getSubListFromKeyword(browser, imdbID)
 	if err != nil {
 		t.Fatal(err)
@@ -138,7 +138,7 @@ func TestSupplier_step3(t *testing.T) {
 
 func TestSupplier_CheckAlive(t *testing.T) {
 
-	s := NewSupplier(*settings.NewSettings())
+	s := NewSupplier(settings.NewSettings(), log_helper.GetLogger())
 	alive, _ := s.CheckAlive()
 	if alive == false {
 		t.Fatal("CheckAlive == false")

+ 6 - 0
internal/logic/task_queue/buckt_name.go

@@ -0,0 +1,6 @@
+package task_queue
+
+const (
+	// 每日字幕提供者的下载字幕次数
+	BucketNamePrefixSupplierDailyDownloadCounter = "SupplierDailyDownloadCounter"
+)

+ 102 - 0
internal/logic/task_queue/daily_download_limit.go

@@ -0,0 +1,102 @@
+package task_queue
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
+	"github.com/xujiajun/nutsdb"
+	"time"
+)
+
+// GetDailyDownloadCount 根据字幕提供者的名称,获取今日下载计数的次数
+func GetDailyDownloadCount(supplierName string) (int, error) {
+
+	nowTime := time.Now()
+	// 今天剩余的时间(s)
+	KeyName := supplierName + "_" + nowTime.Format("2006-01-02")
+
+	outCount := 0
+	err := GetDb().Update(
+		func(tx *nutsdb.Tx) error {
+			var err error
+			outCount, err = getDailyDownloadCount(tx, KeyName)
+			if err != nil {
+				return err
+			}
+			return nil
+		})
+	if err != nil {
+		return 0, err
+	}
+
+	return outCount, nil
+}
+
+func getDailyDownloadCount(tx *nutsdb.Tx, KeyName string) (int, error) {
+	outCount := 0
+	key := []byte(KeyName)
+	// 先判断 key 是否存在
+	ok, err := tx.SHasKey(BucketNamePrefixSupplierDailyDownloadCounter, key)
+	if err != nil {
+		return 0, err
+	}
+	if ok == true {
+		// 存在
+		// 不存在,说明今天的还没有使用,那么就需要新建赋值
+		if e, err := tx.Get(BucketNamePrefixSupplierDailyDownloadCounter, key); err != nil {
+			return 0, err
+		} else {
+			outCount, err = my_util.BytesToInt(e.Value)
+			if err != nil {
+				return 0, err
+			}
+		}
+	} else {
+		// 每日的计数器从 0 开始
+		value, err := my_util.IntToBytes(0)
+		if err != nil {
+			return 0, err
+		}
+		restOfDaySecond := my_util.GetRestOfDaySec()
+		// 不存在,说明今天的还没有使用,那么就需要新建赋值
+		if err = tx.Put(BucketNamePrefixSupplierDailyDownloadCounter, key, value, uint32(restOfDaySecond.Seconds())); err != nil {
+			return 0, err
+		}
+
+		return outCount, nil
+	}
+
+	return outCount, nil
+}
+
+// AddDailyDownloadCount 根据字幕提供者的名称,今日下载计数的次数+1,TTL 多加 5s 确保今天过去
+func AddDailyDownloadCount(supplierName string) (int, error) {
+
+	nowTime := time.Now()
+	// 今天剩余的时间(s)
+	restOfDaySecond := my_util.GetRestOfDaySec()
+	KeyName := supplierName + "_" + nowTime.Format("2006-01-02")
+	dailyDownloadCount := 0
+	err := GetDb().Update(
+		func(tx *nutsdb.Tx) error {
+
+			var err error
+			key := []byte(KeyName)
+			dailyDownloadCount, err = getDailyDownloadCount(tx, KeyName)
+			if err != nil {
+				return err
+			}
+			value, err := my_util.IntToBytes(dailyDownloadCount + 1)
+			if err != nil {
+				return err
+			}
+			// 因为已经查询了一次,确保一定存在,所以直接更新+1,TTL 多加 5s 确保今天过去
+			if err = tx.Put(BucketNamePrefixSupplierDailyDownloadCounter, key, value, uint32(restOfDaySecond.Seconds())+5); err != nil {
+				return err
+			}
+			return nil
+		})
+	if err != nil {
+		return 0, err
+	}
+
+	return dailyDownloadCount, nil
+}

+ 32 - 0
internal/logic/task_queue/init.go

@@ -0,0 +1,32 @@
+package task_queue
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_folder"
+	"github.com/xujiajun/nutsdb"
+	"path/filepath"
+)
+
+func GetDb() *nutsdb.DB {
+
+	if dbBase == nil {
+		var err error
+		opt := nutsdb.DefaultOptions
+		opt.Dir = getDbName() //这边数据库会自动创建这个目录文件
+		dbBase, err = nutsdb.Open(opt)
+		if err != nil {
+			log_helper.GetLogger().Panicln("task_queue.GetDb()", err)
+		}
+	}
+	return dbBase
+}
+
+func getDbName() string {
+	return filepath.Join(my_folder.GetConfigRootDirFPath(), dbFileName)
+}
+
+const (
+	dbFileName = "task_queue"
+)
+
+var dbBase *nutsdb.DB

+ 38 - 0
internal/pkg/my_util/util.go

@@ -1,8 +1,10 @@
 package my_util
 
 import (
+	"bytes"
 	"crypto/md5"
 	"crypto/sha1"
+	"encoding/binary"
 	"encoding/hex"
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/common"
@@ -680,6 +682,42 @@ func GetFileSHA1String(fileFPath string) (string, error) {
 	return fmt.Sprintf("%x", md5.Sum(hashBytes)), nil
 }
 
+func GetRestOfDaySec() time.Duration {
+
+	nowTime := time.Now()
+	todayLast := nowTime.Format("2006-01-02") + " 23:59:59"
+	todayLastTime, _ := time.ParseInLocation("2006-01-02 15:04:05", todayLast, time.Local)
+	// 今天剩余的时间(s)
+	restOfDaySec := time.Duration(todayLastTime.Unix()-time.Now().Local().Unix()) * time.Second
+
+	return restOfDaySec
+}
+
+// IntToBytes 整形转换成字节
+func IntToBytes(n int) ([]byte, error) {
+	x := int32(n)
+
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	err := binary.Write(bytesBuffer, binary.BigEndian, x)
+	if err != nil {
+		return nil, err
+	}
+	return bytesBuffer.Bytes(), nil
+}
+
+// BytesToInt 字节转换成整形
+func BytesToInt(b []byte) (int, error) {
+	bytesBuffer := bytes.NewBuffer(b)
+
+	var x int32
+	err := binary.Read(bytesBuffer, binary.BigEndian, &x)
+	if err != nil {
+		return 0, err
+	}
+
+	return int(x), nil
+}
+
 var (
 	_wantedExtMap    = make(map[string]string) // 人工确认的需要监控的视频后缀名
 	_defExtMap       = make(map[string]string) // 内置支持的视频后缀名列表

+ 8 - 1
internal/pkg/my_util/util_test.go

@@ -1,6 +1,7 @@
 package my_util
 
 import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/unit_test_helper"
 	"path/filepath"
 	"testing"
@@ -9,7 +10,7 @@ import (
 func TestCloseChrome(t *testing.T) {
 
 	// BUG: will produce Logs under this dir
-	CloseChrome()
+	CloseChrome(log_helper.GetLogger())
 }
 
 func TestFileNameIsBDMV(t *testing.T) {
@@ -22,3 +23,9 @@ func TestFileNameIsBDMV(t *testing.T) {
 	}
 	println(fakeVideoFPath)
 }
+
+func TestGetRestOfDaySec(t *testing.T) {
+
+	rest := GetRestOfDaySec()
+	println(rest)
+}

+ 2 - 2
internal/pkg/rod_helper/rodHelper.go

@@ -20,7 +20,7 @@ import (
 	"time"
 )
 
-func NewBrowserEx(loadAdblock bool, _settings settings.Settings, preLoadUrl ...string) (*rod.Browser, error) {
+func NewBrowserEx(loadAdblock bool, _settings *settings.Settings, preLoadUrl ...string) (*rod.Browser, error) {
 
 	httpProxyURL := ""
 
@@ -237,7 +237,7 @@ func HttpGetFromBrowser(browser *rod.Browser, inputUrl string, tt time.Duration,
 
 // ReloadBrowser 提前把浏览器下载好
 func ReloadBrowser() {
-	newBrowser, err := NewBrowserEx(true, *settings.GetSettings())
+	newBrowser, err := NewBrowserEx(true, settings.GetSettings())
 	if err != nil {
 		return
 	}

+ 2 - 0
internal/pkg/settings/settings.go

@@ -19,6 +19,7 @@ type Settings struct {
 	EmbySettings          *EmbySettings          `json:"emby_settings"`
 	DeveloperSettings     *DeveloperSettings     `json:"developer_settings"`
 	TimelineFixerSettings *TimelineFixerSettings `json:"timeline_fixer_settings"`
+	SuppliersSettings     *SuppliersSettings     `json:"suppliers_settings"`
 	ExperimentalFunction  *ExperimentalFunction  `json:"experimental_function"`
 }
 
@@ -78,6 +79,7 @@ func NewSettings() *Settings {
 		EmbySettings:          NewEmbySettings(),
 		DeveloperSettings:     NewDeveloperSettings(),
 		TimelineFixerSettings: NewTimelineFixerSettings(),
+		SuppliersSettings:     NewSuppliersSettings(),
 		ExperimentalFunction:  NewExperimentalFunction(),
 	}
 }

+ 29 - 0
internal/pkg/settings/supplier_settings.go

@@ -0,0 +1,29 @@
+package settings
+
+import "github.com/allanpk716/ChineseSubFinder/internal/common"
+
+type SuppliersSettings struct {
+	Xunlei  *OneSupplierSettings `json:"xunlei"`
+	Shooter *OneSupplierSettings `json:"shooter"`
+	SubHD   *OneSupplierSettings `json:"subhd"`
+	Zimuku  *OneSupplierSettings `json:"zimuku"`
+}
+
+func NewSuppliersSettings() *SuppliersSettings {
+	return &SuppliersSettings{
+		Xunlei:  NewOneSupplierSettings(common.SubSiteXunLei, common.SubXunLeiRootUrlDef, -1),
+		Shooter: NewOneSupplierSettings(common.SubSiteShooter, common.SubShooterRootUrlDef, -1),
+		SubHD:   NewOneSupplierSettings(common.SubSiteSubHd, common.SubSubHDRootUrlDef, 50),
+		Zimuku:  NewOneSupplierSettings(common.SubSiteZiMuKu, common.SubZiMuKuRootUrlDef, 50),
+	}
+}
+
+type OneSupplierSettings struct {
+	Name               string `json:"name"`
+	RootUrl            string `json:"root_url"`
+	DailyDownloadLimit int    `json:"daily_download_limit" default:"-1"` // -1 是无限制
+}
+
+func NewOneSupplierSettings(name string, rootUrl string, dailyDownloadLimit int) *OneSupplierSettings {
+	return &OneSupplierSettings{Name: name, RootUrl: rootUrl, DailyDownloadLimit: dailyDownloadLimit}
+}