123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- package manual_upload_sub_2_local
- import (
- "sync"
- "github.com/ChineseSubFinder/ChineseSubFinder/internal/models"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/scan_logic"
- "github.com/pkg/errors"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/save_sub_helper"
- subCommon "github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_formatter/common"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/sub_parser/ass"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/sub_parser/srt"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_parser_hub"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/sub_helper"
- "github.com/sirupsen/logrus"
- llq "github.com/emirpasic/gods/queues/linkedlistqueue"
- "github.com/emirpasic/gods/sets/hashset"
- )
- type ManualUploadSub2Local struct {
- log *logrus.Logger
- saveSubHelper *save_sub_helper.SaveSubHelper // 保存字幕的逻辑
- scanLogic *scan_logic.ScanLogic // 是否扫描逻辑
- subNameFormatter subCommon.FormatterName // 从 inSubFormatter 推断出来
- processQueue *llq.Queue
- jobSet *hashset.Set
- jobResultMap sync.Map
- addOneSignal chan interface{}
- addLocker sync.Mutex
- subParserHub *sub_parser_hub.SubParserHub
- workingJob *Job // 正在操作的任务的路径
- }
- func NewManualUploadSub2Local(log *logrus.Logger, saveSubHelper *save_sub_helper.SaveSubHelper, scanLogic *scan_logic.ScanLogic) *ManualUploadSub2Local {
- m := &ManualUploadSub2Local{
- log: log,
- saveSubHelper: saveSubHelper,
- scanLogic: scanLogic,
- processQueue: llq.New(),
- jobSet: hashset.New(),
- jobResultMap: sync.Map{},
- addOneSignal: make(chan interface{}, 1),
- subParserHub: sub_parser_hub.NewSubParserHub(log, ass.NewParser(log), srt.NewParser(log)),
- workingJob: nil,
- }
- // 这里就不单独弄一个 settings.SubNameFormatter 字段来传递值了,因为 inSubFormatter 就已经知道是什么 formatter 了
- m.subNameFormatter = subCommon.FormatterName(saveSubHelper.SubFormatter.GetFormatterFormatterName())
- go func(mu *ManualUploadSub2Local) {
- for {
- select {
- case _ = <-mu.addOneSignal:
- // 有新任务了
- m.dealers()
- }
- }
- }(m)
- return m
- }
- // IsJobInQueue 是否正在队列中排队,或者正在被处理
- func (m *ManualUploadSub2Local) IsJobInQueue(job *Job) bool {
- m.addLocker.Lock()
- defer func() {
- m.addLocker.Unlock()
- }()
- if job == nil || job.VideoFPath == "" {
- return false
- }
- if m.jobSet.Contains(job.VideoFPath) == true {
- // 已经在队列中了
- return true
- } else {
- if m.workingJob == nil {
- return false
- }
- // 还有一种可能,任务从队列拿出来了,正在处理,那么在外部开来也还是在队列中的
- if m.workingJob.VideoFPath == job.VideoFPath {
- return true
- }
- }
- return false
- }
- // Add 添加任务
- func (m *ManualUploadSub2Local) Add(job *Job) {
- m.addLocker.Lock()
- defer func() {
- m.addLocker.Unlock()
- }()
- if m.jobSet.Contains(job.VideoFPath) == true {
- // 已经在队列中了
- return
- }
- m.processQueue.Enqueue(job)
- m.jobSet.Add(job.VideoFPath)
- // 通知有新任务了
- m.addOneSignal <- struct{}{}
- return
- }
- // JobResult 任务结果,如果成功 ok,如果没有就是空,其他就是错误信息
- func (m *ManualUploadSub2Local) JobResult(job *Job) string {
- value, found := m.jobResultMap.LoadAndDelete(job.VideoFPath)
- if found == false {
- return ""
- }
- return value.(string)
- }
- // ListJob 任务列表
- func (m *ManualUploadSub2Local) ListJob() []*Job {
- m.addLocker.Lock()
- defer func() {
- m.addLocker.Unlock()
- }()
- ret := make([]*Job, 0)
- for _, v := range m.processQueue.Values() {
- ret = append(ret, v.(*Job))
- }
- if m.workingJob != nil {
- ret = append(ret, m.workingJob)
- }
- return ret
- }
- func (m *ManualUploadSub2Local) dealers() {
- m.addLocker.Lock()
- if m.processQueue.Empty() == true {
- // 没有任务了
- m.addLocker.Unlock()
- return
- }
- job, ok := m.processQueue.Dequeue()
- if ok == false {
- // 没有任务了
- m.addLocker.Unlock()
- return
- }
- // 移除这个任务
- m.jobSet.Remove(job.(*Job).VideoFPath)
- // 标记这个正在处理
- m.workingJob = job.(*Job)
- m.addLocker.Unlock()
- // 具体处理这个任务
- err := m.processSub(job.(*Job))
- if err != nil {
- m.log.Error(err)
- }
- }
- func (m *ManualUploadSub2Local) processSub(job *Job) error {
- var err error
- defer func() {
- // 任务处理完了
- m.addLocker.Lock()
- m.workingJob = nil
- m.addLocker.Unlock()
- if err != nil {
- m.jobResultMap.Store(job.VideoFPath, err.Error())
- } else {
- m.jobResultMap.Store(job.VideoFPath, "ok")
- }
- }()
- // 不管是不是保存多个字幕,都要先扫描本地的字幕,进行 .Default .Forced 去除
- // 这个视频的所有字幕,去除 .default .Forced 标记
- err = sub_helper.SearchVideoMatchSubFileAndRemoveExtMark(m.log, job.VideoFPath)
- if err != nil {
- // 找个错误可以忍
- m.log.Errorln("SearchVideoMatchSubFileAndRemoveExtMark,", job.VideoFPath, err)
- }
- bFind, subFileInfo, err := m.subParserHub.DetermineFileTypeFromFile(job.SubFPath)
- if err != nil {
- err = errors.New("DetermineFileTypeFromFile," + job.SubFPath + "," + err.Error())
- return err
- }
- if bFind == false {
- err = errors.New("DetermineFileTypeFromFile," + job.SubFPath + ",not support SubType")
- return err
- }
- var skipInfo *models.SkipScanInfo
- if m.subNameFormatter == subCommon.Emby {
- err = m.saveSubHelper.WriteSubFile2VideoPath(job.VideoFPath, *subFileInfo, "manual", true, false)
- if err != nil {
- err = errors.New("WriteSubFile2VideoPath," + job.VideoFPath + "," + err.Error())
- return err
- }
- // 默认设置这个视频“跳过”(跳过扫描和下载字幕)属性
- skipInfo = models.NewSkipScanInfoByMovie(job.VideoFPath, true)
- } else {
- err = m.saveSubHelper.WriteSubFile2VideoPath(job.VideoFPath, *subFileInfo, "manual", false, false)
- if err != nil {
- err = errors.New("WriteSubFile2VideoPath," + job.VideoFPath + "," + err.Error())
- return err
- }
- // 默认设置这个视频“跳过”(跳过扫描和下载字幕)属性
- skipInfo = models.NewSkipScanInfoBySeriesEx(job.VideoFPath, true)
- }
- m.scanLogic.Set(skipInfo)
- return nil
- }
- type Job struct {
- VideoFPath string `json:"video_f_path"`
- SubFPath string `json:"sub_f_path"`
- }
- type Reply struct {
- Jobs []*Job `json:"jobs"`
- }
|