sub_format_changer.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package sub_formatter
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/allanpk716/ChineseSubFinder/internal/dao"
  6. "github.com/allanpk716/ChineseSubFinder/internal/ifaces"
  7. movieHelper "github.com/allanpk716/ChineseSubFinder/internal/logic/movie_helper"
  8. seriesHelper "github.com/allanpk716/ChineseSubFinder/internal/logic/series_helper"
  9. "github.com/allanpk716/ChineseSubFinder/internal/models"
  10. "github.com/allanpk716/ChineseSubFinder/internal/pkg"
  11. "github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
  12. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/common"
  13. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/emby"
  14. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_formatter/normal"
  15. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_helper"
  16. "github.com/allanpk716/ChineseSubFinder/internal/types/language"
  17. "os"
  18. "strings"
  19. )
  20. type SubFormatChanger struct {
  21. movieRootDir string
  22. seriesRootDir string
  23. formatter map[string]ifaces.ISubFormatter
  24. }
  25. func NewSubFormatChanger(movieRootDir string, seriesRootDir string) *SubFormatChanger {
  26. formatter := SubFormatChanger{movieRootDir: movieRootDir, seriesRootDir: seriesRootDir}
  27. // TODO 如果字幕格式新增了实现,这里也需要添加对应的实例
  28. // 初始化支持的 formatter
  29. // normal
  30. formatter.formatter = make(map[string]ifaces.ISubFormatter)
  31. normalM := normal.NewFormatter()
  32. formatter.formatter[normalM.GetFormatterName()] = normalM
  33. // emby
  34. embyM := emby.NewFormatter()
  35. formatter.formatter[embyM.GetFormatterName()] = embyM
  36. return &formatter
  37. }
  38. // AutoDetectThenChangeTo 自动检测字幕的命名格式,然后转换到目标的 formatter 上
  39. func (s SubFormatChanger) AutoDetectThenChangeTo(desFormatter common.FormatterName) (RenameResults, error) {
  40. var err error
  41. outStruct := RenameResults{}
  42. outStruct.RenamedFiles = make(map[string]int)
  43. outStruct.ErrFiles = make(map[string]int)
  44. if pkg.IsDir(s.movieRootDir) == false {
  45. return outStruct, errors.New("movieRootDir path not exist: " + s.movieRootDir)
  46. }
  47. if pkg.IsDir(s.seriesRootDir) == false {
  48. return outStruct, errors.New("seriesRootDir path not exist: " + s.seriesRootDir)
  49. }
  50. // 先找出有那些电影文件夹和连续剧文件夹
  51. var movieFullPathList = make([]string, 0)
  52. movieFullPathList, err = pkg.SearchMatchedVideoFile(s.movieRootDir)
  53. if err != nil {
  54. return outStruct, err
  55. }
  56. seriesDirList, err := seriesHelper.GetSeriesList(s.seriesRootDir)
  57. if err != nil {
  58. return outStruct, err
  59. }
  60. // 搜索所有的字幕,找到相关的字幕进行修改
  61. for _, one := range movieFullPathList {
  62. found := false
  63. var fitMovieNameSubList = make([]string, 0)
  64. found, _, fitMovieNameSubList, err = movieHelper.MovieHasChineseSub(one)
  65. if err != nil || found == false {
  66. continue
  67. }
  68. // 判断是否是符合要求
  69. for _, fitSubName := range fitMovieNameSubList {
  70. s.autoDetectAndChange(&outStruct, fitSubName, desFormatter)
  71. }
  72. }
  73. // 连续剧
  74. var seriesSubFiles = make([]string, 0)
  75. for _, oneSeriesDir := range seriesDirList {
  76. seriesSubFiles, err = sub_helper.SearchMatchedSubFileByDir(oneSeriesDir)
  77. if err != nil {
  78. return outStruct, err
  79. }
  80. // 判断是否是符合要求
  81. for _, fitSubName := range seriesSubFiles {
  82. s.autoDetectAndChange(&outStruct, fitSubName, desFormatter)
  83. }
  84. }
  85. return outStruct, nil
  86. }
  87. // autoDetectAndChange 自动检测命名格式,然后修改至目标的命名格式
  88. func (s SubFormatChanger) autoDetectAndChange(outStruct *RenameResults, fitSubName string, desFormatter common.FormatterName) {
  89. for _, formatter := range s.formatter {
  90. bok, fileNameWithOutExt, subExt, subLang, extraSubPreName := formatter.IsMatchThisFormat(fitSubName)
  91. if bok == false {
  92. continue
  93. }
  94. // 如果检测到的格式和目标要转换到的格式是一个,那么就跳过
  95. if common.FormatterName(formatter.GetFormatterFormatterName()) == desFormatter {
  96. return
  97. }
  98. // 这里得到的 subExt 可能是 .ass or .default.ass or .forced.ass
  99. // 需要进行剔除,因为后续的 GenerateMixSubName 会自动生成对应的附加后缀名
  100. // 转换格式后,需要保留之前的 default 或者 forced
  101. findDefault := false
  102. findForce := false
  103. if strings.Contains(subExt, language.Sub_Ext_Mark_Default) == true {
  104. subExt = strings.Replace(subExt, language.Sub_Ext_Mark_Default, "", -1)
  105. findDefault = true
  106. }
  107. if strings.Contains(subExt, language.Sub_Ext_Mark_Forced) == true {
  108. subExt = strings.Replace(subExt, language.Sub_Ext_Mark_Forced, "", -1)
  109. findForce = true
  110. }
  111. // 通过传入的目标格式化 formatter 的名称去调用
  112. newSubFileName := ""
  113. newName, newDefaultName, newForcedName := s.formatter[fmt.Sprintf("%s", desFormatter)].
  114. GenerateMixSubNameBase(fileNameWithOutExt, subExt, subLang, extraSubPreName)
  115. if findDefault == false && findForce == false {
  116. // 使用没得额外 Default 或者 Forced 的名称即可
  117. newSubFileName = newName
  118. } else if findDefault == true {
  119. newSubFileName = newDefaultName
  120. } else if findForce == true {
  121. newSubFileName = newForcedName
  122. }
  123. if newSubFileName == "" {
  124. continue
  125. }
  126. // 确认改格式
  127. err := os.Rename(fitSubName, newSubFileName)
  128. if err != nil {
  129. tmpName := pkg.FixWindowPathBackSlash(fitSubName)
  130. outStruct.ErrFiles[tmpName] += 1
  131. continue
  132. } else {
  133. tmpName := pkg.FixWindowPathBackSlash(newSubFileName)
  134. outStruct.RenamedFiles[tmpName] += 1
  135. }
  136. }
  137. }
  138. type RenameResults struct {
  139. RenamedFiles map[string]int
  140. ErrFiles map[string]int
  141. }
  142. // GetSubFormatter 选择字幕命名格式化的实例
  143. func GetSubFormatter(subNameFormatter int) ifaces.ISubFormatter {
  144. var subFormatter ifaces.ISubFormatter
  145. switch subNameFormatter {
  146. case int(common.Emby):
  147. {
  148. subFormatter = emby.NewFormatter()
  149. break
  150. }
  151. case int(common.Normal):
  152. {
  153. subFormatter = normal.NewFormatter()
  154. break
  155. }
  156. default:
  157. {
  158. subFormatter = emby.NewFormatter()
  159. break
  160. }
  161. }
  162. return subFormatter
  163. }
  164. // SubFormatChangerProcess 执行 SubFormatChanger 逻辑,并且更新数据库缓存
  165. func SubFormatChangerProcess(movieRootDir string, seriesRootDir string, nowDesFormatter common.FormatterName) (RenameResults, error) {
  166. var subFormatRec models.SubFormatRec
  167. dao.GetDb().First(&subFormatRec)
  168. subFormatChanger := NewSubFormatChanger(movieRootDir, seriesRootDir)
  169. // 理论上有且仅有一条记录
  170. if subFormatRec.Done == false {
  171. // 没有找到,认为是第一次执行
  172. renameResults, err := subFormatChanger.AutoDetectThenChangeTo(nowDesFormatter)
  173. if err != nil {
  174. return renameResults, err
  175. }
  176. // 需要记录到数据库中
  177. oneSubFormatter := models.SubFormatRec{FormatName: int(nowDesFormatter), Done: true}
  178. dao.GetDb().Create(&oneSubFormatter)
  179. return renameResults, nil
  180. } else {
  181. // 找到了,需要判断上一次执行的目标 formatter 是啥,如果这次的目标 formatter 不一样则执行
  182. // 如果是一样的则跳过
  183. if common.FormatterName(subFormatRec.FormatName) == nowDesFormatter {
  184. log_helper.GetLogger().Infoln("DesSubFormatter == LateTimeSubFormatter then skip process")
  185. return RenameResults{}, nil
  186. }
  187. // 执行更改
  188. renameResults, err := subFormatChanger.AutoDetectThenChangeTo(nowDesFormatter)
  189. if err != nil {
  190. return renameResults, err
  191. }
  192. // 更新数据库
  193. subFormatRec.FormatName = int(nowDesFormatter)
  194. subFormatRec.Done = true
  195. dao.GetDb().Save(subFormatRec)
  196. return renameResults, nil
  197. }
  198. }