فهرست منبع

正在重构支持用户自己设置 TMDB API

Signed-off-by: allan716 <[email protected]>
allan716 3 سال پیش
والد
کامیت
2b54206ce8

+ 1 - 1
go.mod

@@ -69,7 +69,7 @@ require (
 require (
 	github.com/allanpk716/is_running_in_docker v0.0.1
 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
-	github.com/cyruzin/golang-tmdb v1.4.3
+	github.com/cyruzin/golang-tmdb v1.4.4
 	github.com/elazarl/goproxy v0.0.0-20220417044921-416226498f94
 	github.com/longbridgeapp/opencc v0.1.7
 	github.com/pkg/errors v0.9.1

+ 4 - 0
go.sum

@@ -131,6 +131,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/cyruzin/golang-tmdb v1.4.3 h1:68vNEG4djN5eTeQQCajPDi0VpR+WwFGaham/Or0ef84=
 github.com/cyruzin/golang-tmdb v1.4.3/go.mod h1:HSTffPiDK+Q8gzRlZ22oCu6Otj/7TwUlTqEzFqJoG00=
+github.com/cyruzin/golang-tmdb v1.4.4 h1:EGYWPSHsYISUOIKWKffHJzRXtDh9RDW7wqcZJxjZWeU=
+github.com/cyruzin/golang-tmdb v1.4.4/go.mod h1:ZSryJLCcY+9TiKU+LbouXKns++YBrM8Tizannr05c+I=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -583,6 +585,7 @@ github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
@@ -973,6 +976,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
 gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
 gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=

+ 1 - 1
pkg/logic/cron_helper/cron_helper.go

@@ -250,7 +250,7 @@ func (ch *CronHelper) scanPlayedVideoSub() {
 
 	ch.log.Infoln("Update Info...")
 	nowInfo := dao.UpdateInfo(pkg.AppVersion(), ch.Settings)
-	_, err := ch.FileDownloader.SubtitleBestApi.FeedBack(
+	_, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.FeedBack(
 		nowInfo.Id,
 		nowInfo.Version, nowInfo.MediaServer,
 		nowInfo.EnableShare, nowInfo.EnableApiKey)

+ 10 - 9
pkg/logic/cron_helper/upload_played_video_sub.go

@@ -3,12 +3,13 @@ package cron_helper
 import (
 	"errors"
 	"fmt"
-	"github.com/allanpk716/ChineseSubFinder/pkg"
 	"path/filepath"
 	"strconv"
 	"strings"
 	"time"
 
+	"github.com/allanpk716/ChineseSubFinder/pkg"
+
 	"github.com/allanpk716/ChineseSubFinder/pkg/common"
 
 	"github.com/allanpk716/ChineseSubFinder/internal/dao"
@@ -55,7 +56,7 @@ func (ch *CronHelper) uploadPlayedVideoSub() {
 	if imdbInfos[0].TmdbId == "" {
 
 		// 需要先对这个字幕的 IMDB ID 转 TMDB ID 信息进行查询,得到 TMDB ID 和 Year (2019 2022)
-		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.log, ch.FileDownloader.SubtitleBestApi, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
+		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
 		if err != nil {
 			ch.log.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
 			return
@@ -65,7 +66,7 @@ func (ch *CronHelper) uploadPlayedVideoSub() {
 		var mediaInfos []models.MediaInfo
 		dao.GetDb().Where("tmdb_id = ?", imdbInfos[0].TmdbId).Find(&mediaInfos)
 		if len(mediaInfos) < 1 {
-			finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.log, ch.FileDownloader.SubtitleBestApi, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
+			finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
 			if err != nil {
 				ch.log.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
 				return
@@ -97,7 +98,7 @@ func (ch *CronHelper) uploadPlayedVideoSub() {
 
 	ch.log.Infoln("AskFroUpload", notUploadedVideoSubInfos[0].SubName)
 	// 问询这个字幕是否上传过了,如果没有就需要进入上传的队列
-	askForUploadReply, err := ch.FileDownloader.SubtitleBestApi.AskFroUpload(
+	askForUploadReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.AskFroUpload(
 		notUploadedVideoSubInfos[0].SHA256,
 		notUploadedVideoSubInfos[0].IsMovie,
 		true,
@@ -163,7 +164,7 @@ func (ch *CronHelper) uploadPlayedVideoSub() {
 			return
 		}
 		ch.log.Infoln("UploadSub", notUploadedVideoSubInfos[0].SubName)
-		uploadSubReply, err := ch.FileDownloader.SubtitleBestApi.UploadSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()))
+		uploadSubReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.UploadSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()))
 		if err != nil {
 			ch.log.Errorln("UploadSub error:", err.Error())
 
@@ -250,7 +251,7 @@ func (ch *CronHelper) uploadLowTrustVideoSub() {
 	if imdbInfos[0].TmdbId == "" {
 
 		// 需要先对这个字幕的 IMDB ID 转 TMDB ID 信息进行查询,得到 TMDB ID 和 Year (2019 2022)
-		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.log, ch.FileDownloader.SubtitleBestApi, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
+		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
 		if err != nil {
 			ch.log.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
 			return
@@ -260,7 +261,7 @@ func (ch *CronHelper) uploadLowTrustVideoSub() {
 		var mediaInfos []models.MediaInfo
 		dao.GetDb().Where("tmdb_id = ?", imdbInfos[0].TmdbId).Find(&mediaInfos)
 		if len(mediaInfos) < 1 {
-			finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.log, ch.FileDownloader.SubtitleBestApi, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
+			finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
 			if err != nil {
 				ch.log.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
 				return
@@ -292,7 +293,7 @@ func (ch *CronHelper) uploadLowTrustVideoSub() {
 
 	ch.log.Infoln("AskFroUpload", notUploadedVideoSubInfos[0].SubName)
 	// 问询这个字幕是否上传过了,如果没有就需要进入上传的队列
-	askForUploadReply, err := ch.FileDownloader.SubtitleBestApi.AskFroUpload(
+	askForUploadReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.AskFroUpload(
 		notUploadedVideoSubInfos[0].SHA256,
 		notUploadedVideoSubInfos[0].IsMovie,
 		false,
@@ -358,7 +359,7 @@ func (ch *CronHelper) uploadLowTrustVideoSub() {
 			return
 		}
 		ch.log.Infoln("UploadSub", notUploadedVideoSubInfos[0].SubName)
-		uploadSubReply, err := ch.FileDownloader.SubtitleBestApi.UploadLowTrustSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()), "")
+		uploadSubReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.UploadLowTrustSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()), "")
 		if err != nil {
 			ch.log.Errorln("UploadLowTrustSub error:", err.Error())
 

+ 11 - 9
pkg/logic/file_downloader/downloader_hub.go

@@ -5,6 +5,8 @@ import (
 	"fmt"
 	"path/filepath"
 
+	"github.com/allanpk716/ChineseSubFinder/pkg/media_info_dealers"
+
 	"github.com/allanpk716/ChineseSubFinder/pkg"
 
 	"github.com/allanpk716/ChineseSubFinder/pkg/types/language"
@@ -24,20 +26,20 @@ import (
 )
 
 type FileDownloader struct {
-	Settings        *settings.Settings
-	Log             *logrus.Logger
-	CacheCenter     *cache_center.CacheCenter
-	SubParserHub    *sub_parser_hub.SubParserHub
-	SubtitleBestApi *subtitle_best_api.SubtitleBestApi
+	Settings         *settings.Settings
+	Log              *logrus.Logger
+	CacheCenter      *cache_center.CacheCenter
+	SubParserHub     *sub_parser_hub.SubParserHub
+	MediaInfoDealers *media_info_dealers.Dealers
 }
 
 func NewFileDownloader(cacheCenter *cache_center.CacheCenter, authKey random_auth_key.AuthKey) *FileDownloader {
 
 	f := FileDownloader{Settings: cacheCenter.Settings,
-		Log:             cacheCenter.Log,
-		CacheCenter:     cacheCenter,
-		SubParserHub:    sub_parser_hub.NewSubParserHub(cacheCenter.Log, ass.NewParser(cacheCenter.Log), srt.NewParser(cacheCenter.Log)),
-		SubtitleBestApi: subtitle_best_api.NewSubtitleBestApi(cacheCenter.Log, authKey, cacheCenter.Settings.AdvancedSettings.ProxySettings),
+		Log:              cacheCenter.Log,
+		CacheCenter:      cacheCenter,
+		SubParserHub:     sub_parser_hub.NewSubParserHub(cacheCenter.Log, ass.NewParser(cacheCenter.Log), srt.NewParser(cacheCenter.Log)),
+		MediaInfoDealers: media_info_dealers.NewDealers(cacheCenter.Log, cacheCenter.Settings, subtitle_best_api.NewSubtitleBestApi(cacheCenter.Log, authKey, cacheCenter.Settings.AdvancedSettings.ProxySettings)),
 	}
 	return &f
 }

+ 1 - 2
pkg/logic/scan_played_video_subinfo/scan_played_video_subinfo.go

@@ -399,8 +399,7 @@ func (s *ScanPlayedVideoSubInfo) dealOneVideo(index int, videoFPath, orgSubFPath
 			videoType = "series"
 		}
 		_, err = mix_media_info.GetMediaInfoAndSave(
-			s.log,
-			s.fileDownloader.SubtitleBestApi,
+			s.fileDownloader.MediaInfoDealers,
 			imdbInfo,
 			imdbInfo.IMDBID, "imdb", videoType)
 		if err != nil {

+ 2 - 2
pkg/logic/sub_supplier/a4k/a4k.go

@@ -112,7 +112,7 @@ func (s *Supplier) GetSubListFromFile4Movie(videoFPath string) ([]supplier.SubIn
 
 	outSubInfos := make([]supplier.SubInfo, 0)
 
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi,
+	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers,
 		videoFPath, true, s.settings.AdvancedSettings.ProxySettings)
 	if err != nil {
 		s.log.Errorln(s.GetSupplierName(), "GetMixMediaInfo", err)
@@ -175,7 +175,7 @@ func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]s
 	// 这里拿到的 seriesInfo ,里面包含了,需要下载字幕的 Eps 信息
 	for _, episodeInfo := range seriesInfo.NeedDlEpsKeyList {
 
-		mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi,
+		mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers,
 			episodeInfo.FileFullPath, false, s.settings.AdvancedSettings.ProxySettings)
 		if err != nil {
 			s.log.Errorln(s.GetSupplierName(), "GetMixMediaInfo", err)

+ 1 - 1
pkg/logic/sub_supplier/assrt/assrt.go

@@ -154,7 +154,7 @@ func (s *Supplier) getSubListFromFile(videoFPath string, isMovie bool) ([]suppli
 	s.log.Debugln(s.GetSupplierName(), videoFPath, "Start...")
 
 	outSubInfoList := make([]supplier.SubInfo, 0)
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi, videoFPath, isMovie, s.settings.AdvancedSettings.ProxySettings)
+	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers, videoFPath, isMovie, s.settings.AdvancedSettings.ProxySettings)
 	if err != nil {
 		s.log.Errorln(s.GetSupplierName(), videoFPath, "GetMixMediaInfo", err)
 		return nil, err

+ 1 - 1
pkg/logic/sub_supplier/csf/csf.go

@@ -158,7 +158,7 @@ func (s *Supplier) findAndDownload(videoFPath string, isMovie bool, Season, Epis
 		err = errors.New(fmt.Sprintf("%s.Calculate %s %s", s.GetSupplierName(), videoFPath, err))
 		return
 	}
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi, videoFPath, isMovie, s.settings.AdvancedSettings.ProxySettings)
+	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers, videoFPath, isMovie, s.settings.AdvancedSettings.ProxySettings)
 	if err != nil {
 		err = errors.New(fmt.Sprintf("%s.GetMixMediaInfo %s %s", s.GetSupplierName(), videoFPath, err))
 		return

+ 2 - 2
pkg/logic/sub_supplier/subhd/subhd.go

@@ -151,7 +151,7 @@ func (s *Supplier) GetSubListFromFile4Series(seriesInfo *series.SeriesInfo) ([]s
 		_ = browser.Close()
 	}()
 
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi,
+	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers,
 		seriesInfo.EpList[0].FileFullPath, false,
 		s.settings.AdvancedSettings.ProxySettings)
 	if err != nil {
@@ -262,7 +262,7 @@ func (s *Supplier) getSubListFromFile4Movie(filePath string) ([]supplier.SubInfo
 		}
 	}
 	s.log.Infoln(s.GetSupplierName(), filePath, "No subtitle found", "KeyWord:", imdbInfo.ImdbId)
-	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.SubtitleBestApi,
+	mediaInfo, err := mix_media_info.GetMixMediaInfo(s.log, s.fileDownloader.MediaInfoDealers,
 		filePath, true,
 		s.settings.AdvancedSettings.ProxySettings)
 	if err != nil {

+ 158 - 0
pkg/media_info_dealers/dealers.go

@@ -0,0 +1,158 @@
+package media_info_dealers
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/allanpk716/ChineseSubFinder/internal/models"
+	"github.com/allanpk716/ChineseSubFinder/pkg/settings"
+	"github.com/allanpk716/ChineseSubFinder/pkg/subtitle_best_api"
+	"github.com/allanpk716/ChineseSubFinder/pkg/tmdb_api"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+type Dealers struct {
+	log             *logrus.Logger
+	settings        *settings.Settings
+	SubtitleBestApi *subtitle_best_api.SubtitleBestApi
+	tmdbHelper      *tmdb_api.TmdbApi
+}
+
+func NewDealers(log *logrus.Logger, settings *settings.Settings, subtitleBestApi *subtitle_best_api.SubtitleBestApi) *Dealers {
+	return &Dealers{log: log, settings: settings, SubtitleBestApi: subtitleBestApi}
+}
+
+func (d *Dealers) SetTmdbHelperInstance(tmdbHelper *tmdb_api.TmdbApi) {
+	d.tmdbHelper = tmdbHelper
+}
+
+func (d *Dealers) GetMediaInfo(id, source, videoType string) (*models.MediaInfo, error) {
+
+	if d.settings.AdvancedSettings.TmdbApiSettings.Enable == true && d.settings.AdvancedSettings.TmdbApiSettings.ApiKey != "" {
+		// 优先使用用户自己的 tmdb api
+		return d.getMediaInfoFromSelfApi(id, source, videoType)
+	} else {
+		// 使用默认的公用服务器 tmdb api
+		return d.getMediaInfoFromSubtitleBestApi(id, source, videoType)
+	}
+}
+
+// getMediaInfoFromSelfApi 通过用户自己的 tmdb api 查询媒体信息 "source"=imdb|tmdb  "video_type"=movie|series
+func (d *Dealers) getMediaInfoFromSelfApi(id, source, videoType string) (*models.MediaInfo, error) {
+
+	imdbId := ""
+	var tmdbID int64
+	idType := ""
+	isMovieOrSeries := false
+	if source == "imdb" {
+		idType = tmdb_api.ImdbID
+		imdbId = id
+	} else if source == "tmdb" {
+
+		if videoType == "movie" {
+			idType = tmdb_api.TmdbID
+			isMovieOrSeries = true
+		} else if videoType == "series" {
+			idType = tmdb_api.TmdbID
+			isMovieOrSeries = false
+		} else {
+			return nil, errors.New("videoType is wrong")
+		}
+	} else {
+		return nil, errors.New("source is not support")
+	}
+	// 先查询英文信息,然后再查询中文信息
+	findByIDEn, err := d.tmdbHelper.GetInfo(id, idType, isMovieOrSeries, true)
+	if err != nil {
+		return nil, fmt.Errorf("error while getting info from TMDB: %v", err)
+	}
+	findByIDCn, err := d.tmdbHelper.GetInfo(id, idType, isMovieOrSeries, false)
+	if err != nil {
+		return nil, fmt.Errorf("error while getting info from TMDB: %v", err)
+	}
+
+	OriginalTitle := ""
+	OriginalLanguage := ""
+	TitleEn := ""
+	TitleCn := ""
+	Year := ""
+	if isMovieOrSeries == true {
+		// 电影
+		tmdbID = findByIDEn.MovieResults[0].ID
+		OriginalTitle = findByIDEn.MovieResults[0].OriginalTitle
+		OriginalLanguage = findByIDEn.MovieResults[0].OriginalLanguage
+		TitleEn = findByIDEn.MovieResults[0].Title
+		TitleCn = findByIDCn.MovieResults[0].Title
+		Year = findByIDEn.MovieResults[0].ReleaseDate
+
+	} else {
+		// 电视剧
+		tmdbID = findByIDEn.TvResults[0].ID
+		OriginalTitle = findByIDEn.TvResults[0].OriginalName
+		OriginalLanguage = findByIDEn.TvResults[0].OriginalLanguage
+		TitleEn = findByIDEn.TvResults[0].Name
+		TitleCn = findByIDCn.TvResults[0].Name
+		Year = findByIDEn.TvResults[0].FirstAirDate
+	}
+
+	mediaInfo := &models.MediaInfo{
+		TmdbId:           fmt.Sprintf("%d", tmdbID),
+		ImdbId:           imdbId,
+		OriginalTitle:    OriginalTitle,
+		OriginalLanguage: OriginalLanguage,
+		TitleEn:          TitleEn,
+		TitleCn:          TitleCn,
+		Year:             Year,
+	}
+
+	return mediaInfo, nil
+}
+
+// getMediaInfoFromSubtitleBestApi 通过 subtitle.best api 查询媒体信息 "source"=imdb|tmdb  "video_type"=movie|series
+func (d *Dealers) getMediaInfoFromSubtitleBestApi(id, source, videoType string) (*models.MediaInfo, error) {
+
+	var mediaInfo *models.MediaInfo
+	queryCount := 0
+	for {
+		queryCount++
+		mediaInfoReply, err := d.SubtitleBestApi.GetMediaInfo(id, source, videoType)
+		if err != nil {
+			return nil, err
+		}
+		if mediaInfoReply.Status == 2 {
+			// 说明进入了查询队列,可以等 30s 以上再次查询
+			d.log.Infoln("query queue, sleep 30s")
+			time.Sleep(30 * time.Second)
+
+		} else if mediaInfoReply.Status == 1 {
+
+			imdbId := ""
+			if source == "imdb" {
+				imdbId = id
+			} else if source == "tmdb" {
+				imdbId = ""
+			}
+
+			// 说明查询成功
+			mediaInfo = &models.MediaInfo{
+				TmdbId:           mediaInfoReply.TMDBId,
+				ImdbId:           imdbId,
+				OriginalTitle:    mediaInfoReply.OriginalTitle,
+				OriginalLanguage: mediaInfoReply.OriginalLanguage,
+				TitleEn:          mediaInfoReply.TitleEN,
+				TitleCn:          mediaInfoReply.TitleCN,
+				Year:             mediaInfoReply.Year,
+			}
+		} else {
+			// 说明查询失败
+			return nil, errors.New("SubtitleBestApi.GetMediaInfo failed, Message: " + mediaInfoReply.Message)
+		}
+
+		if queryCount > 9 {
+			break
+		}
+	}
+
+	return mediaInfo, nil
+}

+ 7 - 54
pkg/mix_media_info/mix_media_info.go

@@ -2,7 +2,8 @@ package mix_media_info
 
 import (
 	"errors"
-	"time"
+
+	"github.com/allanpk716/ChineseSubFinder/pkg/media_info_dealers"
 
 	"github.com/allanpk716/ChineseSubFinder/pkg"
 
@@ -14,12 +15,11 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/models"
 	"github.com/allanpk716/ChineseSubFinder/pkg/imdb_helper"
 	"github.com/allanpk716/ChineseSubFinder/pkg/settings"
-	"github.com/allanpk716/ChineseSubFinder/pkg/subtitle_best_api"
 	"github.com/sirupsen/logrus"
 )
 
 func GetMixMediaInfo(log *logrus.Logger,
-	SubtitleBestApi *subtitle_best_api.SubtitleBestApi,
+	dealers *media_info_dealers.Dealers,
 	videoFPath string, isMovie bool, _proxySettings *settings.ProxySettings) (*models.MediaInfo, error) {
 
 	imdbInfo, err := imdb_helper.GetIMDBInfoFromVideoFile(log, videoFPath, isMovie, _proxySettings)
@@ -37,7 +37,7 @@ func GetMixMediaInfo(log *logrus.Logger,
 	if imdbInfo.TmdbId == "" {
 		// 需要去 web 查询
 		source = "imdb"
-		return GetMediaInfoAndSave(log, SubtitleBestApi, imdbInfo, imdbInfo.IMDBID, source, videoType)
+		return GetMediaInfoAndSave(dealers, imdbInfo, imdbInfo.IMDBID, source, videoType)
 	} else {
 		// 已经存在,从本地拿去信息
 		// 首先从数据库中查找是否存在这个 IMDB 信息,如果不存在再使用 Web 查找,且写入数据库
@@ -51,62 +51,15 @@ func GetMixMediaInfo(log *logrus.Logger,
 		} else {
 			// 没有找到本地缓存的 TMDB ID 信息,需要去 web 查询
 			source = "imdb"
-			return GetMediaInfoAndSave(log, SubtitleBestApi, imdbInfo, imdbInfo.IMDBID, source, videoType)
+			return GetMediaInfoAndSave(dealers, imdbInfo, imdbInfo.IMDBID, source, videoType)
 		}
 	}
 }
 
-func getMediaInfoEx(log *logrus.Logger, SubtitleBestApi *subtitle_best_api.SubtitleBestApi, id, source, videoType string) (*models.MediaInfo, error) {
-
-	var mediaInfo *models.MediaInfo
-	queryCount := 0
-	for {
-		queryCount++
-		mediaInfoReply, err := SubtitleBestApi.GetMediaInfo(id, source, videoType)
-		if err != nil {
-			return nil, err
-		}
-		if mediaInfoReply.Status == 2 {
-			// 说明进入了查询队列,可以等 30s 以上再次查询
-			log.Infoln("query queue, sleep 30s")
-			time.Sleep(30 * time.Second)
-
-		} else if mediaInfoReply.Status == 1 {
-
-			imdbId := ""
-			if source == "imdb" {
-				imdbId = id
-			} else if source == "tmdb" {
-				imdbId = ""
-			}
-
-			// 说明查询成功
-			mediaInfo = &models.MediaInfo{
-				TmdbId:           mediaInfoReply.TMDBId,
-				ImdbId:           imdbId,
-				OriginalTitle:    mediaInfoReply.OriginalTitle,
-				OriginalLanguage: mediaInfoReply.OriginalLanguage,
-				TitleEn:          mediaInfoReply.TitleEN,
-				TitleCn:          mediaInfoReply.TitleCN,
-				Year:             mediaInfoReply.Year,
-			}
-		} else {
-			// 说明查询失败
-			return nil, errors.New("SubtitleBestApi.GetMediaInfo failed, Message: " + mediaInfoReply.Message)
-		}
-
-		if queryCount > 9 {
-			break
-		}
-	}
-
-	return mediaInfo, nil
-}
-
 // GetMediaInfoAndSave 通过 IMDB ID 查询媒体信息,并保存到数据库,IMDB 和 MediaInfo 都会进行保存 // source,options=imdb|tmdb  videoType,options=movie|series
-func GetMediaInfoAndSave(log *logrus.Logger, SubtitleBestApi *subtitle_best_api.SubtitleBestApi, imdbInfo *models.IMDBInfo, id, source, videoType string) (*models.MediaInfo, error) {
+func GetMediaInfoAndSave(dealers *media_info_dealers.Dealers, imdbInfo *models.IMDBInfo, id, source, videoType string) (*models.MediaInfo, error) {
 
-	mediaInfo, err := getMediaInfoEx(log, SubtitleBestApi, id, source, videoType)
+	mediaInfo, err := dealers.GetMediaInfo(id, source, videoType)
 	if err != nil {
 		return nil, err
 	}

+ 1 - 0
pkg/settings/advanced_settings.go

@@ -7,6 +7,7 @@ import (
 
 type AdvancedSettings struct {
 	ProxySettings              *ProxySettings     `json:"proxy_settings"`
+	TmdbApiSettings            *TmdbApiSettings   `json:"tmdb_api_settings"`
 	DebugMode                  bool               `json:"debug_mode"`                     // 是否开启调试模式,这个是写入一个特殊的文件来开启日志的 Debug 输出
 	SaveFullSeasonTmpSubtitles bool               `json:"save_full_season_tmp_subtitles"` // 保存整季的缓存字幕
 	SubTypePriority            int                `json:"sub_type_priority"`              // 字幕下载的优先级,0 是自动,1 是 srt 优先,2 是 ass/ssa 优先

+ 6 - 0
pkg/settings/tmdb_api_settings.go

@@ -0,0 +1,6 @@
+package settings
+
+type TmdbApiSettings struct {
+	Enable bool   `json:"enable"`
+	ApiKey string `json:"api_key"`
+}

+ 197 - 0
pkg/tmdb_api/tmdb.go

@@ -0,0 +1,197 @@
+package tmdb_api
+
+import (
+	"fmt"
+	"strconv"
+
+	"github.com/allanpk716/ChineseSubFinder/pkg"
+	"github.com/allanpk716/ChineseSubFinder/pkg/settings"
+	tmdb "github.com/cyruzin/golang-tmdb"
+	"github.com/sirupsen/logrus"
+)
+
+type TmdbApi struct {
+	l          *logrus.Logger
+	apiKey     string
+	tmdbClient *tmdb.Client
+}
+
+func NewTmdbHelper(l *logrus.Logger, apiKey string, _proxySettings ...*settings.ProxySettings) (*TmdbApi, error) {
+
+	tmdbClient, err := tmdb.Init(apiKey)
+	if err != nil {
+		err = fmt.Errorf("error initializing tmdb client: %s", err)
+		return nil, err
+	}
+	// 获取 http client 实例
+	restyClient, err := pkg.NewHttpClient(_proxySettings...)
+	if err != nil {
+		err = fmt.Errorf("error initializing resty client: %s", err)
+		return nil, err
+	}
+	tmdbClient.SetClientConfig(*restyClient.GetClient())
+	return &TmdbApi{
+		l:          l,
+		apiKey:     apiKey,
+		tmdbClient: tmdbClient,
+	}, nil
+}
+
+// GetInfo 获取视频的信息 idType: imdb_id or tmdb_id
+func (t *TmdbApi) GetInfo(iD string, idType string, isMovieOrSeries, isQueryEnOrCNInfo bool) (outFindByID *tmdb.FindByID, err error) {
+
+	// 查询的参数
+	options := make(map[string]string)
+	if isQueryEnOrCNInfo == true {
+		options["language"] = "en-US"
+	} else {
+		options["language"] = "zh-CN"
+	}
+	if idType == ImdbID {
+
+		options["external_source"] = "imdb_id"
+		outFindByID, err = t.tmdbClient.GetFindByID(iD, options)
+		if err != nil {
+			return nil, fmt.Errorf("error getting tmdb info by id = %s: %s", iD, err)
+		}
+	} else if idType == TmdbID {
+
+		intVar, err := strconv.Atoi(iD)
+		if err != nil {
+			return nil, fmt.Errorf("error converting tmdb id = %s to int: %s", iD, err)
+		}
+
+		if isMovieOrSeries == true {
+			movieDetails, err := t.tmdbClient.GetMovieDetails(intVar, options)
+			if err != nil {
+				return nil, fmt.Errorf("error getting tmdb movie details by id = %s: %s", iD, err)
+			}
+			outFindByID = &tmdb.FindByID{
+				MovieResults: []struct {
+					Adult            bool    `json:"adult"`
+					BackdropPath     string  `json:"backdrop_path"`
+					GenreIDs         []int64 `json:"genre_ids"`
+					ID               int64   `json:"id"`
+					OriginalLanguage string  `json:"original_language"`
+					OriginalTitle    string  `json:"original_title"`
+					Overview         string  `json:"overview"`
+					PosterPath       string  `json:"poster_path"`
+					ReleaseDate      string  `json:"release_date"`
+					Title            string  `json:"title"`
+					Video            bool    `json:"video"`
+					VoteAverage      float32 `json:"vote_average"`
+					VoteCount        int64   `json:"vote_count"`
+					Popularity       float32 `json:"popularity"`
+				}{
+					{
+						Adult:            movieDetails.Adult,
+						BackdropPath:     movieDetails.BackdropPath,
+						ID:               movieDetails.ID,
+						OriginalLanguage: movieDetails.OriginalLanguage,
+						OriginalTitle:    movieDetails.OriginalTitle,
+						Overview:         movieDetails.Overview,
+						PosterPath:       movieDetails.PosterPath,
+						ReleaseDate:      movieDetails.ReleaseDate,
+						Title:            movieDetails.Title,
+						Video:            movieDetails.Video,
+						VoteAverage:      movieDetails.VoteAverage,
+						VoteCount:        movieDetails.VoteCount,
+						Popularity:       movieDetails.Popularity,
+					},
+				},
+			}
+		} else {
+			tvDetails, err := t.tmdbClient.GetTVDetails(intVar, options)
+			if err != nil {
+				return nil, fmt.Errorf("error getting tmdb tv details by id = %s: %s", iD, err)
+			}
+			outFindByID = &tmdb.FindByID{
+				TvResults: []struct {
+					OriginalName     string   `json:"original_name"`
+					ID               int64    `json:"id"`
+					Name             string   `json:"name"`
+					VoteCount        int64    `json:"vote_count"`
+					VoteAverage      float32  `json:"vote_average"`
+					FirstAirDate     string   `json:"first_air_date"`
+					PosterPath       string   `json:"poster_path"`
+					GenreIDs         []int64  `json:"genre_ids"`
+					OriginalLanguage string   `json:"original_language"`
+					BackdropPath     string   `json:"backdrop_path"`
+					Overview         string   `json:"overview"`
+					OriginCountry    []string `json:"origin_country"`
+					Popularity       float32  `json:"popularity"`
+				}{
+					{
+						OriginalName:     tvDetails.OriginalName,
+						ID:               tvDetails.ID,
+						Name:             tvDetails.Name,
+						VoteCount:        tvDetails.VoteCount,
+						VoteAverage:      tvDetails.VoteAverage,
+						FirstAirDate:     tvDetails.FirstAirDate,
+						PosterPath:       tvDetails.PosterPath,
+						OriginalLanguage: tvDetails.OriginalLanguage,
+						BackdropPath:     tvDetails.BackdropPath,
+						Overview:         tvDetails.Overview,
+						OriginCountry:    tvDetails.OriginCountry,
+						Popularity:       tvDetails.Popularity,
+					},
+				},
+			}
+		}
+
+	}
+
+	return outFindByID, nil
+}
+
+func (t TmdbApi) CovertId(iD string, idType string, isMovieOrSeries bool) (convertIdResult *ConvertIdResult, err error) {
+
+	if idType == ImdbID {
+		return nil, fmt.Errorf("imdb id type is not supported")
+	} else if idType == TmdbID {
+		var intVar int
+		intVar, err = strconv.Atoi(iD)
+		if err != nil {
+			return nil, fmt.Errorf("error converting tmdb id = %s to int: %s", iD, err)
+		}
+		options := make(map[string]string)
+		if isMovieOrSeries == true {
+			movieExternalIDs, err := t.tmdbClient.GetMovieExternalIDs(intVar, options)
+			if err != nil {
+				return nil, err
+			}
+			convertIdResult = &ConvertIdResult{
+				ImdbID: movieExternalIDs.IMDbID,
+				TmdbID: iD,
+			}
+
+			return convertIdResult, nil
+		} else {
+			tvExternalIDs, err := t.tmdbClient.GetTVExternalIDs(intVar, options)
+			if err != nil {
+				return nil, err
+			}
+
+			convertIdResult = &ConvertIdResult{
+				ImdbID: tvExternalIDs.IMDbID,
+				TmdbID: iD,
+				TvdbID: fmt.Sprintf("%d", tvExternalIDs.TVDBID),
+			}
+
+			return convertIdResult, nil
+		}
+	} else {
+		return nil, fmt.Errorf("id type is not supported")
+	}
+}
+
+const (
+	ImdbID = "imdb_id"
+	TmdbID = "tmdb_id"
+)
+
+type ConvertIdResult struct {
+	ImdbID string `json:"imdb_id"`
+	TmdbID string `json:"tmdb_id"`
+	TvdbID string `json:"tvdb_id"`
+}

+ 2 - 2
pkg/video_scan_and_refresh_helper/video_scan_and_refresh_helper.go

@@ -380,7 +380,7 @@ func (v *VideoScanAndRefreshHelper) scanLowVideoSubInfo(scanVideoResult *ScanVid
 
 			v.log.Infoln("--------------------------------------------------------------------------------")
 			v.log.Infoln("scanLowVideoSubInfo.MovieHasChineseSub", videoIndex, videoFPath)
-			mixMediaInfo, err := mix_media_info.GetMixMediaInfo(v.log, v.fileDownloader.SubtitleBestApi, videoFPath, true, v.settings.AdvancedSettings.ProxySettings)
+			mixMediaInfo, err := mix_media_info.GetMixMediaInfo(v.log, v.fileDownloader.MediaInfoDealers, videoFPath, true, v.settings.AdvancedSettings.ProxySettings)
 			if err != nil {
 				v.log.Warningln("scanLowVideoSubInfo.GetMixMediaInfo", videoFPath, err)
 				continue
@@ -440,7 +440,7 @@ func (v *VideoScanAndRefreshHelper) scanLowVideoSubInfo(scanVideoResult *ScanVid
 				continue
 			}
 
-			mixMediaInfo, err := mix_media_info.GetMixMediaInfo(v.log, v.fileDownloader.SubtitleBestApi, seriesInfo.EpList[0].FileFullPath, false, v.settings.AdvancedSettings.ProxySettings)
+			mixMediaInfo, err := mix_media_info.GetMixMediaInfo(v.log, v.fileDownloader.MediaInfoDealers, seriesInfo.EpList[0].FileFullPath, false, v.settings.AdvancedSettings.ProxySettings)
 			if err != nil {
 				v.log.Warningln("scanLowVideoSubInfo.GetMixMediaInfo", seriesInfo.EpList[0].FileFullPath, err)
 				continue