downloader_things.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package downloader
  2. import (
  3. "errors"
  4. "fmt"
  5. "path/filepath"
  6. "github.com/allanpk716/ChineseSubFinder/pkg"
  7. "github.com/allanpk716/ChineseSubFinder/pkg/settings"
  8. "github.com/allanpk716/ChineseSubFinder/pkg/types/common"
  9. "github.com/allanpk716/ChineseSubFinder/pkg/types/series"
  10. "github.com/allanpk716/ChineseSubFinder/pkg/types/subparser"
  11. "github.com/allanpk716/ChineseSubFinder/pkg/decode"
  12. subcommon "github.com/allanpk716/ChineseSubFinder/pkg/sub_formatter/common"
  13. "github.com/allanpk716/ChineseSubFinder/pkg/sub_helper"
  14. )
  15. // oneVideoSelectBestSub 一个视频,选择最佳的一个字幕(也可以保存所有网站第一个最佳字幕)
  16. func (d *Downloader) oneVideoSelectBestSub(oneVideoFullPath string, organizeSubFiles []string) error {
  17. // 如果没有则直接跳过
  18. if organizeSubFiles == nil || len(organizeSubFiles) < 1 {
  19. return common.AllSiteDownloadSubNotFound
  20. }
  21. var err error
  22. // 得到目标视频文件的文件名
  23. videoFileName := filepath.Base(oneVideoFullPath)
  24. // -------------------------------------------------
  25. // 调试缓存,把下载好的字幕写到对应的视频目录下,方便调试
  26. if settings.Get().AdvancedSettings.DebugMode == true {
  27. err = pkg.CopyFiles2DebugFolder([]string{videoFileName}, organizeSubFiles)
  28. if err != nil {
  29. // 这个错误可以忍
  30. d.log.Errorln("copySubFile2DesFolder", err)
  31. }
  32. }
  33. // -------------------------------------------------
  34. /*
  35. 这里需要额外考虑一点,有可能当前目录已经有一个 .Default .Forced 标记的字幕了
  36. 那么下载字幕丢进来的时候就需要提前把这个字幕找出来,去除整个 .Default .Forced 标记
  37. 然后进行正常的下载,存储和替换字幕,最后将本次操作的第一次标记为 .Default
  38. */
  39. // 不管是不是保存多个字幕,都要先扫描本地的字幕,进行 .Default .Forced 去除
  40. // 这个视频的所有字幕,去除 .default .Forced 标记
  41. err = sub_helper.SearchVideoMatchSubFileAndRemoveExtMark(d.log, oneVideoFullPath)
  42. if err != nil {
  43. // 找个错误可以忍
  44. d.log.Errorln("SearchVideoMatchSubFileAndRemoveExtMark,", oneVideoFullPath, err)
  45. }
  46. if settings.Get().AdvancedSettings.SaveMultiSub == false {
  47. // 选择最优的一个字幕
  48. var finalSubFile *subparser.FileInfo
  49. finalSubFile = d.mk.SelectOneSubFile(organizeSubFiles)
  50. if finalSubFile == nil {
  51. outString := fmt.Sprintln("Found", len(organizeSubFiles), " subtitles but not one fit:", oneVideoFullPath)
  52. d.log.Warnln(outString)
  53. return errors.New(outString)
  54. }
  55. /*
  56. 这里还有一个梗,Emby、jellyfin 支持 default 和 forced 扩展字段
  57. 但是,plex 只支持 forced
  58. 那么就比较麻烦,干脆,normal 的命名格式化实例,就不设置 default 了,forced 不想用,因为可能会跟你手动选择的字幕冲突(下次观看的时候,理论上也可能不会)
  59. */
  60. // 判断配置文件中的字幕命名格式化的选择
  61. bSetDefault := true
  62. if d.subNameFormatter == subcommon.Normal {
  63. bSetDefault = false
  64. }
  65. // 找到了,写入文件
  66. err = d.SaveSubHelper.WriteSubFile2VideoPath(oneVideoFullPath, *finalSubFile, "", bSetDefault, false)
  67. if err != nil {
  68. return errors.New(fmt.Sprintf("SaveMultiSub: %v, writeSubFile2VideoPath, Error: %v ", settings.Get().AdvancedSettings.SaveMultiSub, err))
  69. }
  70. } else {
  71. // 每个网站 Top1 的字幕
  72. siteNames, finalSubFiles := d.mk.SelectEachSiteTop1SubFile(organizeSubFiles)
  73. if len(siteNames) < 0 {
  74. outString := fmt.Sprintln("SelectEachSiteTop1SubFile found none sub file")
  75. d.log.Warnln(outString)
  76. return errors.New(outString)
  77. }
  78. // 多网站 Top 1 字幕保存的时候,第一个设置为 Default 即可
  79. /*
  80. 由于新功能支持了字幕命名格式的选择,那么如果触发了多个字幕保存的逻辑,如果不调整
  81. 则会遇到,top1 先写入,然后 top2 覆盖 top1 ,以此类推的情况出现
  82. 所以如果开启了 Normal SubNameFormatter 的功能,则要反序写入文件
  83. 如果是 Emby 的字幕命名格式则无需考虑此问题,因为每个网站只会有一个字幕,且字幕命名格式决定了不会重复写入覆盖
  84. */
  85. if d.subNameFormatter == subcommon.Emby {
  86. for i, file := range finalSubFiles {
  87. setDefault := false
  88. if i == 0 {
  89. setDefault = true
  90. }
  91. err = d.SaveSubHelper.WriteSubFile2VideoPath(oneVideoFullPath, file, siteNames[i], setDefault, false)
  92. if err != nil {
  93. return errors.New(fmt.Sprintf("SaveMultiSub: %v, writeSubFile2VideoPath, Error: %v ", settings.Get().AdvancedSettings.SaveMultiSub, err))
  94. }
  95. }
  96. } else {
  97. // 默认这里就是 normal 模式
  98. // 逆序写入
  99. /*
  100. 这里还有一个梗,Emby、jellyfin 支持 default 和 forced 扩展字段
  101. 但是,plex 只支持 forced
  102. 那么就比较麻烦,干脆,normal 的命名格式化实例,就不设置 default 了,forced 不想用,因为可能会跟你手动选择的字幕冲突(下次观看的时候,理论上也可能不会)
  103. */
  104. for i := len(finalSubFiles) - 1; i > -1; i-- {
  105. err = d.SaveSubHelper.WriteSubFile2VideoPath(oneVideoFullPath, finalSubFiles[i], siteNames[i], false, false)
  106. if err != nil {
  107. return errors.New(fmt.Sprintf("SaveMultiSub: %v, writeSubFile2VideoPath, Error: %v ", settings.Get().AdvancedSettings.SaveMultiSub, err))
  108. }
  109. }
  110. }
  111. }
  112. // -------------------------------------------------
  113. return nil
  114. }
  115. // saveFullSeasonSub 这里就需要单独存储到连续剧每一季的文件夹的特殊文件夹中。需要跟 DeleteOneSeasonSubCacheFolder 关联起来
  116. func (d *Downloader) saveFullSeasonSub(seriesInfo *series.SeriesInfo, organizeSubFiles map[string][]string) map[string][]string {
  117. var fullSeasonSubDict = make(map[string][]string)
  118. for _, season := range seriesInfo.SeasonDict {
  119. seasonKey := pkg.GetEpisodeKeyName(season, 0)
  120. subs, ok := organizeSubFiles[seasonKey]
  121. if ok == false {
  122. continue
  123. }
  124. for _, sub := range subs {
  125. subFileName := filepath.Base(sub)
  126. newSeasonSubRootPath, err := pkg.GetDebugFolderByName([]string{
  127. filepath.Base(seriesInfo.DirPath),
  128. "Sub_" + seasonKey})
  129. if err != nil {
  130. d.log.Errorln("saveFullSeasonSub.GetDebugFolderByName", subFileName, err)
  131. continue
  132. }
  133. newSubFullPath := filepath.Join(newSeasonSubRootPath, subFileName)
  134. err = pkg.CopyFile(sub, newSubFullPath)
  135. if err != nil {
  136. d.log.Errorln("saveFullSeasonSub.CopyFile", subFileName, err)
  137. continue
  138. }
  139. // 从字幕的文件名推断是 哪一季 的 那一集
  140. _, gusSeason, gusEpisode, err := decode.GetSeasonAndEpisodeFromSubFileName(subFileName)
  141. if err != nil {
  142. return nil
  143. }
  144. // 把整季的字幕缓存位置也提供出去,如果之前没有下载到的,这里返回出来的可以补上
  145. seasonEpsKey := pkg.GetEpisodeKeyName(gusSeason, gusEpisode)
  146. _, ok := fullSeasonSubDict[seasonEpsKey]
  147. if ok == false {
  148. // 初始化
  149. fullSeasonSubDict[seasonEpsKey] = make([]string, 0)
  150. }
  151. fullSeasonSubDict[seasonEpsKey] = append(fullSeasonSubDict[seasonEpsKey], sub)
  152. }
  153. }
  154. return fullSeasonSubDict
  155. }