imdb.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package imdb_helper
  2. import (
  3. "errors"
  4. "strconv"
  5. "strings"
  6. "github.com/allanpk716/ChineseSubFinder/pkg"
  7. "github.com/allanpk716/ChineseSubFinder/pkg/media_info_dealers"
  8. "github.com/allanpk716/ChineseSubFinder/pkg/decode"
  9. "github.com/StalkR/imdb"
  10. "github.com/allanpk716/ChineseSubFinder/internal/dao"
  11. "github.com/allanpk716/ChineseSubFinder/internal/models"
  12. "github.com/allanpk716/ChineseSubFinder/pkg/notify_center"
  13. "github.com/allanpk716/ChineseSubFinder/pkg/settings"
  14. "github.com/allanpk716/ChineseSubFinder/pkg/types"
  15. )
  16. // GetIMDBInfoFromVideoFile 先从本地拿缓存,如果没有就从 Web 获取
  17. func GetIMDBInfoFromVideoFile(dealers *media_info_dealers.Dealers, videoFPath string, isMovie bool, _proxySettings *settings.ProxySettings) (*models.IMDBInfo, error) {
  18. var err error
  19. var videoNfoInfo types.VideoNfoInfo
  20. if isMovie == true {
  21. videoNfoInfo, err = decode.GetVideoNfoInfo4Movie(videoFPath)
  22. } else {
  23. videoNfoInfo, err = decode.GetVideoNfoInfoFromEpisode(videoFPath)
  24. }
  25. if err != nil {
  26. // 如果找不到当前电影的 IMDB Info 本地文件,那么就跳过
  27. dealers.Logger.Warningln("getSubListFromFile", videoFPath, err)
  28. return nil, err
  29. }
  30. imdbInfo, err := GetIMDBInfoFromVideoNfoInfo(dealers, videoNfoInfo, _proxySettings)
  31. if err != nil {
  32. dealers.Logger.Warningln("GetIMDBInfoFromVideoNfoInfo", videoFPath, err)
  33. return nil, err
  34. }
  35. if len(imdbInfo.Description) <= 0 {
  36. // 需要去外网获去补全信息,然后更新本地的信息
  37. if imdbInfo.IMDBID != "" && videoNfoInfo.ImdbId == "" {
  38. // 可能本地没有获取到 IMDB ID 信息,那么从上面的 GetIMDBInfoFromVideoNfoInfo 可以从 TMDB ID 获取到 IMDB ID,那么需要传递下去
  39. videoNfoInfo.ImdbId = imdbInfo.IMDBID
  40. }
  41. t, err := getVideoInfoFromIMDBWeb(videoNfoInfo, _proxySettings)
  42. if err != nil {
  43. dealers.Logger.Errorln("getVideoInfoFromIMDBWeb,", videoNfoInfo.Title, err)
  44. return nil, err
  45. }
  46. imdbInfo.Year = t.Year
  47. imdbInfo.AKA = t.AKA
  48. imdbInfo.Description = t.Description
  49. imdbInfo.Languages = t.Languages
  50. dao.GetDb().Save(imdbInfo)
  51. }
  52. return imdbInfo, nil
  53. }
  54. // GetIMDBInfoFromVideoNfoInfo 从本地获取 IMDB 信息,注意,如果需要跳过,那么返回 Error == common.SkipCreateInDB
  55. func GetIMDBInfoFromVideoNfoInfo(dealers *media_info_dealers.Dealers, videoNfoInfo types.VideoNfoInfo, _proxySettings *settings.ProxySettings) (*models.IMDBInfo, error) {
  56. /*
  57. 这里需要注意一个细节,之前理想情况下是从 Web 获取完整的 IMDB Info 回来,放入本地存储
  58. 获取的时候如果本地有就拿本地的,没有则从 Web 获取,然后写入本地存储
  59. 但是实际的使用中发现,其实只有在判断视频是否是中文的时候才有必要去获取 Web 上完整的 IMDB Info 信息
  60. 如果一开始就需要从 Web 上获取,那么这个过程非常的缓慢,很耽误时间,所以还是切换为两层逻辑
  61. 1. 第一次,优先获取本地的 IMDB Info,写入数据库缓存
  62. 2. 如果需要判断视频是否是中文的时候,再去获取 Web 上完整的 IMDB Info 信息,更新写入本地存储
  63. 3. 因为现在默认是不跳过中文视频扫描的,所以如果开启后,则会再判断的时候访问外网获取,然后写入本地,过程会比较慢
  64. 4. 同时,再发送字幕和 IMDB Info 到服务器的时候,也需要判断是否 IMDB Info 信息是否齐全,否则就需要从外网获取齐全后再上传
  65. */
  66. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", "IMDBID:", videoNfoInfo.ImdbId, "TMDBID:", videoNfoInfo.TmdbId, videoNfoInfo.Title, videoNfoInfo.Season, videoNfoInfo.Episode)
  67. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 0)
  68. if videoNfoInfo.ImdbId != "" {
  69. // 优先从 IMDB ID 去查找本地的信息
  70. // 首先从数据库中查找是否存在这个 IMDB 信息,如果不存在再使用 Web 查找,且写入数据库
  71. var imdbInfos []models.IMDBInfo
  72. // 把嵌套关联的 has many 的信息都查询出来
  73. dao.GetDb().
  74. Preload("VideoSubInfos").
  75. Limit(1).Where(&models.IMDBInfo{IMDBID: videoNfoInfo.ImdbId}).Find(&imdbInfos)
  76. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 1)
  77. if len(imdbInfos) <= 0 {
  78. // 没有找到,新增,存储本地,但是信息肯定是不完整的,需要在判断是否是中文的时候再次去外网获取补全信息
  79. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 2)
  80. // 存入数据库
  81. nowIMDBInfo := models.NewIMDBInfo(videoNfoInfo.ImdbId, "", 0, "", []string{}, []string{})
  82. dao.GetDb().Create(nowIMDBInfo)
  83. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 3)
  84. return nowIMDBInfo, nil
  85. } else {
  86. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 4)
  87. // 找到
  88. return &imdbInfos[0], nil
  89. }
  90. } else if videoNfoInfo.TmdbId != "" {
  91. // 如果 IMDB ID 在本地没有获取到,但是 TMDB ID 获取到了,那么就从 Web 去查询 IMDB ID 出来
  92. var imdbInfos []models.IMDBInfo
  93. // 把嵌套关联的 has many 的信息都查询出来
  94. dao.GetDb().
  95. Preload("VideoSubInfos").
  96. Limit(1).Where(&models.IMDBInfo{TmdbId: videoNfoInfo.TmdbId}).Find(&imdbInfos)
  97. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 1)
  98. if len(imdbInfos) <= 0 {
  99. // 没有找到那么就从 Web 端获取 imdb id 信息
  100. } else if len(imdbInfos) > 1 {
  101. // 如果找到多个,那么就应该删除这些,因为这些都是重复的,然后再次从 Web 去获取 imdb id 信息
  102. dao.GetDb().Where(&models.IMDBInfo{TmdbId: videoNfoInfo.TmdbId}).Delete(&models.IMDBInfo{})
  103. } else {
  104. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 4)
  105. // 找到
  106. return &imdbInfos[0], nil
  107. }
  108. // 确定需要从 Web 端获取 imdb id 信息
  109. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 2)
  110. // 联网查询
  111. idConvertReply, err := dealers.ConvertId(videoNfoInfo.TmdbId, "tmdb", videoNfoInfo.IsMovie)
  112. if err != nil {
  113. return nil, err
  114. }
  115. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 3)
  116. // 存入数据库
  117. nowIMDBInfo := models.NewIMDBInfo(idConvertReply.ImdbID, "", 0, "", []string{}, []string{})
  118. dao.GetDb().Create(nowIMDBInfo)
  119. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo", 4)
  120. return nowIMDBInfo, nil
  121. } else {
  122. // 都没有,那么就报错
  123. dealers.Logger.Debugln("GetIMDBInfoFromVideoNfoInfo IMDB TMDB ID is empty")
  124. return nil, errors.New("IMDB TMDB ID is empty")
  125. }
  126. }
  127. // IsChineseVideo 从 imdbID 去查询判断是否是中文视频
  128. func IsChineseVideo(dealers *media_info_dealers.Dealers, videoNfoInfo types.VideoNfoInfo, _proxySettings *settings.ProxySettings) (bool, *models.IMDBInfo, error) {
  129. const chName0 = "chinese"
  130. const chName1 = "mandarin"
  131. dealers.Logger.Debugln("IsChineseVideo", 0)
  132. localIMDBInfo, err := GetIMDBInfoFromVideoNfoInfo(dealers, videoNfoInfo, _proxySettings)
  133. if err != nil {
  134. return false, nil, err
  135. }
  136. if len(localIMDBInfo.Description) <= 0 {
  137. // 需要去外网获去补全信息,然后更新本地的信息
  138. dealers.Logger.Debugln("IsChineseVideo", 1)
  139. t, err := getVideoInfoFromIMDBWeb(videoNfoInfo, _proxySettings)
  140. if err != nil {
  141. dealers.Logger.Errorln("IsChineseVideo.getVideoInfoFromIMDBWeb,", videoNfoInfo.Title, err)
  142. return false, nil, err
  143. }
  144. dealers.Logger.Debugln("IsChineseVideo", 2)
  145. localIMDBInfo.Year = t.Year
  146. localIMDBInfo.Name = t.Name
  147. localIMDBInfo.Year = t.Year
  148. localIMDBInfo.AKA = t.AKA
  149. localIMDBInfo.Description = t.Description
  150. localIMDBInfo.Languages = t.Languages
  151. dealers.Logger.Debugln("IsChineseVideo", 3)
  152. dao.GetDb().Save(localIMDBInfo)
  153. dealers.Logger.Debugln("IsChineseVideo", 4)
  154. }
  155. if len(localIMDBInfo.Languages) < 1 {
  156. return false, localIMDBInfo, nil
  157. }
  158. firstLangLowCase := strings.ToLower(localIMDBInfo.Languages[0])
  159. dealers.Logger.Debugln("IsChineseVideo", 5)
  160. // 判断第一语言是否是中文
  161. switch firstLangLowCase {
  162. case chName0, chName1:
  163. return true, localIMDBInfo, nil
  164. default:
  165. return false, localIMDBInfo, nil
  166. }
  167. }
  168. // getVideoInfoFromIMDBWeb 从 IMDB 网站 ID 查询影片的信息
  169. func getVideoInfoFromIMDBWeb(videoNfoInfo types.VideoNfoInfo, _proxySettings ...*settings.ProxySettings) (*imdb.Title, error) {
  170. client, err := pkg.NewHttpClient(_proxySettings...)
  171. if err != nil {
  172. return nil, err
  173. }
  174. t, err := imdb.NewTitle(client.GetClient(), videoNfoInfo.ImdbId)
  175. if err != nil {
  176. notify_center.Notify.Add("imdb model - imdb.NewTitle :", err.Error())
  177. return nil, err
  178. }
  179. if t.Year == 0 {
  180. // IMDB 信息获取的库(1.0.7),目前有bug,比如,tt6856242 年份为 0
  181. if videoNfoInfo.Year != "" {
  182. year, err := strconv.Atoi(videoNfoInfo.Year)
  183. if err != nil {
  184. return nil, err
  185. }
  186. t.Year = year
  187. }
  188. }
  189. return t, nil
  190. }