1
0
Эх сурвалжийг харах

移除多余代码

Signed-off-by: allan716 <[email protected]>
allan716 2 жил өмнө
parent
commit
ee290caa4c

+ 0 - 407
pkg/logic/cron_helper/upload_played_video_sub.go

@@ -1,407 +0,0 @@
-package cron_helper
-
-import (
-	"errors"
-	"fmt"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/common"
-
-	"github.com/ChineseSubFinder/ChineseSubFinder/internal/dao"
-	"github.com/ChineseSubFinder/ChineseSubFinder/internal/models"
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/mix_media_info"
-	"github.com/jinzhu/now"
-)
-
-// uploadVideoSub  上传字幕的定时器
-func (ch *CronHelper) uploadVideoSub() {
-
-	ch.uploadPlayedVideoSub()
-
-	ch.uploadLowTrustVideoSub()
-}
-
-func (ch *CronHelper) uploadPlayedVideoSub() {
-
-	// 找出没有上传过的字幕列表
-	var notUploadedVideoSubInfos []models.VideoSubInfo
-	dao.GetDb().Where("is_send = ?", false).Limit(1).Find(&notUploadedVideoSubInfos)
-
-	if len(notUploadedVideoSubInfos) < 1 {
-		ch.Logger.Debugln("No notUploadedVideoSubInfos")
-		return
-	}
-
-	var imdbInfos []models.IMDBInfo
-	dao.GetDb().Where("imdb_id = ?", notUploadedVideoSubInfos[0].IMDBInfoID).Find(&imdbInfos)
-	if len(imdbInfos) < 1 {
-		// 如果没有找到,那么就没有办法推断出 IMDB ID 的相关信息和 TMDB ID 信息,要来何用,删除即可
-		ch.Logger.Infoln("No imdbInfos, will delete this VideoSubInfo,", notUploadedVideoSubInfos[0].SubName)
-		dao.GetDb().Delete(&notUploadedVideoSubInfos[0])
-		return
-	}
-	videoType := ""
-	if imdbInfos[0].IsMovie == true {
-		videoType = "movie"
-	} else {
-		videoType = "series"
-	}
-	var err error
-	var finalQueryIMDBInfo *models.MediaInfo
-	if imdbInfos[0].TmdbId == "" {
-
-		// 需要先对这个字幕的 IMDB ID 转 TMDB ID 信息进行查询,得到 TMDB ID 和 Year (2019 2022)
-		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
-		if err != nil {
-			ch.Logger.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
-			return
-		}
-	} else {
-
-		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.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
-			if err != nil {
-				ch.Logger.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
-				return
-			}
-		} else {
-			finalQueryIMDBInfo = &mediaInfos[0]
-		}
-	}
-	// 在这之前,需要进行一次判断,这个字幕是否是有效的,因为可能会有是 1kb 的错误字幕
-	// 如果解析这个字幕是错误的,那么也可以标记完成
-	shareRootDir, err := pkg.GetShareSubRootFolder()
-	if err != nil {
-		ch.Logger.Errorln("GetShareSubRootFolder error:", err.Error())
-		return
-	}
-	bok, _, err := ch.FileDownloader.SubParserHub.DetermineFileTypeFromFile(filepath.Join(shareRootDir, notUploadedVideoSubInfos[0].StoreRPath))
-	if err != nil {
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Errorln("DetermineFileTypeFromFile upload sub error, mark is send,", err.Error())
-		return
-	}
-	if bok == false {
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Errorln("DetermineFileTypeFromFile upload sub == false, not match any SubType, mark is send")
-		return
-	}
-
-	ch.Logger.Infoln("AskFroUpload", notUploadedVideoSubInfos[0].SubName)
-	// 问询这个字幕是否上传过了,如果没有就需要进入上传的队列
-	askForUploadReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.AskFroUpload(
-		notUploadedVideoSubInfos[0].SHA256,
-		notUploadedVideoSubInfos[0].IsMovie,
-		true,
-		finalQueryIMDBInfo.ImdbId,
-		finalQueryIMDBInfo.TmdbId,
-		notUploadedVideoSubInfos[0].Season,
-		notUploadedVideoSubInfos[0].Episode,
-		notUploadedVideoSubInfos[0].Feature,
-	)
-	if err != nil {
-		ch.Logger.Errorln(fmt.Errorf("AskFroUpload err: %v", err))
-		return
-	}
-	if askForUploadReply.Status == 3 {
-		// 上传过了,直接标记本地的 is_send 字段为 true
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Infoln("Subtitle has been uploaded, so will not upload again")
-		return
-	} else if askForUploadReply.Status == 4 {
-		// 上传队列满了,等待下次定时器触发
-		ch.Logger.Infoln("Subtitle upload queue is full, will try ask upload again")
-		return
-	} else if askForUploadReply.Status == 2 {
-		// 这个上传任务已经在队列中了,也许有其他人也需要上传这个字幕,或者本机排队的时候故障了,重启也可能遇到这个故障
-		ch.Logger.Infoln("Subtitle is int the queue")
-		return
-	} else if askForUploadReply.Status == 1 {
-		// 正确放入了队列,然后需要按规划的时间进行上传操作
-		// 这里可能需要执行耗时操作来等待到安排的时间点进行字幕的上传,不能直接长时间的 Sleep 操作
-		// 每次 Sleep 1s 然后就判断一次定时器是否还允许允许,如果不运行了,那么也就需要退出循环
-
-		// 得到目标时间与当前时间的差值,单位是s
-		waitTime := askForUploadReply.ScheduledUnixTime - time.Now().Unix()
-		if waitTime <= 0 {
-			waitTime = 5
-		}
-		ch.Logger.Infoln("will wait", waitTime, "s 2 upload sub 2 server")
-		var sleepCounter int64
-		sleepCounter = 0
-		normalStatus := false
-		for ch.cronHelperRunning == true {
-			if sleepCounter > waitTime {
-				normalStatus = true
-				break
-			}
-			if sleepCounter%30 == 0 {
-				ch.Logger.Infoln("wait 2 upload sub")
-			}
-			time.Sleep(1 * time.Second)
-			sleepCounter++
-		}
-		if normalStatus == false || ch.cronHelperRunning == false {
-			// 说明不是正常跳出来的,是结束定时器来执行的
-			ch.Logger.Infoln("uploadVideoSub early termination")
-			return
-		}
-		// 发送字幕
-
-		releaseTime, err := now.Parse(finalQueryIMDBInfo.Year)
-		if err != nil {
-			ch.Logger.Errorln("now.Parse error:", err.Error())
-			return
-		}
-		ch.Logger.Infoln("UploadSub", notUploadedVideoSubInfos[0].SubName)
-		uploadSubReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.UploadSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()))
-		if err != nil {
-			ch.Logger.Errorln("UploadSub error:", err.Error())
-
-			if errors.Is(err, common.ErrorUpload413) == true {
-				// 文件发送大小超限
-				notUploadedVideoSubInfos[0].IsSend = true
-				dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-				ch.Logger.Infoln("subtitle upload file over size limit, will not upload again")
-				return
-			}
-
-			return
-		}
-		if uploadSubReply.Status == 1 {
-			// 成功,其他情况就等待 Ask for Upload
-			notUploadedVideoSubInfos[0].IsSend = true
-			dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-			ch.Logger.Infoln("subtitle is uploaded")
-			return
-		} else if uploadSubReply.Status == 0 {
-
-			// 发送失败,然后需要判断具体的错误,有一些需要直接标记已发送,跳过
-			if strings.Contains(uploadSubReply.Message, "sub file sha256 not match") == true ||
-				strings.Contains(uploadSubReply.Message, "determine sub file type error") == true ||
-				strings.Contains(uploadSubReply.Message, "determine sub file type not match") == true ||
-				strings.Contains(uploadSubReply.Message, "sub file has no chinese") == true {
-				notUploadedVideoSubInfos[0].IsSend = true
-				dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-				ch.Logger.Infoln("subtitle upload error, uploadSubReply.Status == 0, ", uploadSubReply.Message, "will not upload again")
-				return
-			} else {
-				ch.Logger.Errorln("subtitle upload error, uploadSubReply.Status == 0, not support error:", uploadSubReply.Message)
-				return
-			}
-		} else {
-			ch.Logger.Warningln("UploadSub Message:", uploadSubReply.Message)
-			return
-		}
-
-	} else {
-		// 不是预期的返回值,需要报警
-		ch.Logger.Errorln(fmt.Errorf("AskFroUpload Not the expected return value, Status: %d, Message: %v", askForUploadReply.Status, askForUploadReply.Message))
-		return
-	}
-}
-
-func (ch *CronHelper) uploadLowTrustVideoSub() {
-
-	// 找出没有上传过的字幕列表
-	var notUploadedVideoSubInfos []models.LowVideoSubInfo
-	dao.GetDb().Where("is_send = ?", false).Limit(1).Find(&notUploadedVideoSubInfos)
-
-	if len(notUploadedVideoSubInfos) < 1 {
-		ch.Logger.Debugln("No notUploadedVideoSubInfos")
-		return
-	}
-
-	var imdbInfos []models.IMDBInfo
-	dao.GetDb().Where("imdb_id = ?", notUploadedVideoSubInfos[0].IMDBID).Find(&imdbInfos)
-	if len(imdbInfos) < 1 {
-		// 如果没有找到,那么就没有办法推断出 IMDB ID 的相关信息和 TMDB ID 信息,要来何用,删除即可
-		ch.Logger.Infoln("No imdbInfos, will delete this VideoSubInfo,", notUploadedVideoSubInfos[0].SubName)
-		dao.GetDb().Delete(&notUploadedVideoSubInfos[0])
-		return
-	}
-
-	videoType := ""
-	if notUploadedVideoSubInfos[0].Season == 0 && notUploadedVideoSubInfos[0].Episode == 0 {
-		videoType = "movie"
-	} else if (notUploadedVideoSubInfos[0].Season == 0 && notUploadedVideoSubInfos[0].Episode != 0) || (notUploadedVideoSubInfos[0].Season != 0 && notUploadedVideoSubInfos[0].Episode == 0) {
-		ch.Logger.Errorln(notUploadedVideoSubInfos[0].SubName, "has Season or Episode error")
-		ch.Logger.Errorln("season - episode", notUploadedVideoSubInfos[0].Season, notUploadedVideoSubInfos[0].Episode)
-		// 成功,其他情况就等待 Ask for Upload
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Infoln("subtitle will skip upload")
-		return
-	} else {
-		videoType = "series"
-	}
-
-	var err error
-	var finalQueryIMDBInfo *models.MediaInfo
-	if imdbInfos[0].TmdbId == "" {
-
-		// 需要先对这个字幕的 IMDB ID 转 TMDB ID 信息进行查询,得到 TMDB ID 和 Year (2019 2022)
-		finalQueryIMDBInfo, err = mix_media_info.GetMediaInfoAndSave(ch.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
-		if err != nil {
-			ch.Logger.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
-			return
-		}
-	} else {
-
-		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.FileDownloader.MediaInfoDealers, &imdbInfos[0], imdbInfos[0].IMDBID, "imdb", videoType)
-			if err != nil {
-				ch.Logger.Errorln(errors.New("GetMediaInfoAndSave error:" + err.Error()))
-				return
-			}
-		} else {
-			finalQueryIMDBInfo = &mediaInfos[0]
-		}
-	}
-	// 在这之前,需要进行一次判断,这个字幕是否是有效的,因为可能会有是 1kb 的错误字幕
-	// 如果解析这个字幕是错误的,那么也可以标记完成
-	shareRootDir, err := pkg.GetShareSubRootFolder()
-	if err != nil {
-		ch.Logger.Errorln("GetShareSubRootFolder error:", err.Error())
-		return
-	}
-	bok, _, err := ch.FileDownloader.SubParserHub.DetermineFileTypeFromFile(filepath.Join(shareRootDir, notUploadedVideoSubInfos[0].StoreRPath))
-	if err != nil {
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Errorln("DetermineFileTypeFromFile upload sub error, mark is send,", err.Error())
-		return
-	}
-	if bok == false {
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Errorln("DetermineFileTypeFromFile upload sub == false, not match any SubType, mark is send")
-		return
-	}
-
-	ch.Logger.Infoln("AskFroUpload", notUploadedVideoSubInfos[0].SubName)
-	// 问询这个字幕是否上传过了,如果没有就需要进入上传的队列
-	askForUploadReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.AskFroUpload(
-		notUploadedVideoSubInfos[0].SHA256,
-		notUploadedVideoSubInfos[0].IsMovie,
-		false,
-		"",
-		"",
-		0,
-		0,
-		notUploadedVideoSubInfos[0].Feature,
-	)
-	if err != nil {
-		ch.Logger.Errorln(fmt.Errorf("AskFroUpload err: %v", err))
-		return
-	}
-	if askForUploadReply.Status == 3 {
-		// 上传过了,直接标记本地的 is_send 字段为 true
-		notUploadedVideoSubInfos[0].IsSend = true
-		dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-		ch.Logger.Infoln("Subtitle has been uploaded, so will not upload again")
-		return
-	} else if askForUploadReply.Status == 4 {
-		// 上传队列满了,等待下次定时器触发
-		ch.Logger.Infoln("Subtitle upload queue is full, will try ask upload again")
-		return
-	} else if askForUploadReply.Status == 2 {
-		// 这个上传任务已经在队列中了,也许有其他人也需要上传这个字幕,或者本机排队的时候故障了,重启也可能遇到这个故障
-		ch.Logger.Infoln("Subtitle is int the queue")
-		return
-	} else if askForUploadReply.Status == 1 {
-		// 正确放入了队列,然后需要按规划的时间进行上传操作
-		// 这里可能需要执行耗时操作来等待到安排的时间点进行字幕的上传,不能直接长时间的 Sleep 操作
-		// 每次 Sleep 1s 然后就判断一次定时器是否还允许允许,如果不运行了,那么也就需要退出循环
-
-		// 得到目标时间与当前时间的差值,单位是s
-		waitTime := askForUploadReply.ScheduledUnixTime - time.Now().Unix()
-		if waitTime <= 0 {
-			waitTime = 5
-		}
-		ch.Logger.Infoln("will wait", waitTime, "s 2 upload sub 2 server")
-		var sleepCounter int64
-		sleepCounter = 0
-		normalStatus := false
-		for ch.cronHelperRunning == true {
-			if sleepCounter > waitTime {
-				normalStatus = true
-				break
-			}
-			if sleepCounter%30 == 0 {
-				ch.Logger.Infoln("wait 2 upload sub")
-			}
-			time.Sleep(1 * time.Second)
-			sleepCounter++
-		}
-		if normalStatus == false || ch.cronHelperRunning == false {
-			// 说明不是正常跳出来的,是结束定时器来执行的
-			ch.Logger.Infoln("uploadVideoSub early termination")
-			return
-		}
-		// 发送字幕
-
-		releaseTime, err := now.Parse(finalQueryIMDBInfo.Year)
-		if err != nil {
-			ch.Logger.Errorln("now.Parse error:", err.Error())
-			return
-		}
-		ch.Logger.Infoln("UploadSub", notUploadedVideoSubInfos[0].SubName)
-		uploadSubReply, err := ch.FileDownloader.MediaInfoDealers.SubtitleBestApi.UploadLowTrustSub(&notUploadedVideoSubInfos[0], shareRootDir, finalQueryIMDBInfo.TmdbId, strconv.Itoa(releaseTime.Year()), "")
-		if err != nil {
-			ch.Logger.Errorln("UploadLowTrustSub error:", err.Error())
-
-			if errors.Is(err, common.ErrorUpload413) == true {
-				// 文件发送大小超限
-				notUploadedVideoSubInfos[0].IsSend = true
-				dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-				ch.Logger.Infoln("subtitle upload file over size limit, will not upload again")
-				return
-			}
-
-			return
-		}
-		if uploadSubReply.Status == 1 {
-			// 成功,其他情况就等待 Ask for Upload
-			notUploadedVideoSubInfos[0].IsSend = true
-			dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-			ch.Logger.Infoln("subtitle is uploaded")
-			return
-		} else if uploadSubReply.Status == 0 {
-
-			// 发送失败,然后需要判断具体的错误,有一些需要直接标记已发送,跳过
-			if strings.Contains(uploadSubReply.Message, "sub file sha256 not match") == true ||
-				strings.Contains(uploadSubReply.Message, "determine sub file type error") == true ||
-				strings.Contains(uploadSubReply.Message, "determine sub file type not match") == true ||
-				strings.Contains(uploadSubReply.Message, "sub file has no chinese") == true {
-				notUploadedVideoSubInfos[0].IsSend = true
-				dao.GetDb().Save(&notUploadedVideoSubInfos[0])
-				ch.Logger.Infoln("subtitle upload error, uploadSubReply.Status == 0, Message:", uploadSubReply.Message, "will not upload again")
-				return
-			} else {
-				ch.Logger.Errorln("subtitle upload error, uploadSubReply.Status == 0, not support error:", uploadSubReply.Message)
-				return
-			}
-		} else {
-			ch.Logger.Warningln("UploadSub Message:", uploadSubReply.Message)
-			return
-		}
-
-	} else {
-		// 不是预期的返回值,需要报警
-		ch.Logger.Errorln(fmt.Errorf("AskFroUpload Not the expected return value, Status: %d, Message: %v", askForUploadReply.Status, askForUploadReply.Message))
-		return
-	}
-}

+ 0 - 17
pkg/subtitle_best_api/ask_download_task.go

@@ -1,17 +0,0 @@
-package subtitle_best_api
-
-type AskDownloadTaskReply struct {
-	Status       int          `json:"status"`                 // 0 失败,1 有任务,2 没有任务
-	Message      string       `json:"message"`                // 返回的信息,包括成功和失败的原因
-	DownloadInfo DownloadInfo `json:"download_info,optional"` // 下载信息
-}
-
-type DownloadInfo struct {
-	TaskID       string `json:"task_id"`       // 任务id
-	VideoFeature string `json:"video_feature"` // VideoFeature ID
-	ImdbId       string `json:"imdb_id"`       // IMDB ID
-	TmdbId       string `json:"tmdb_id"`       // TMDB ID,这里是这个剧集的 TMDB ID 不是这一集的哈
-	Season       int    `json:"season"`        // 如果对应的是电影则可能是 0,没有
-	Episode      int    `json:"episode"`       // 如果对应的是电影则可能是 0,没有
-	IsMovie      bool   `json:"is_movie"`      // 是否是电影,如果是电影则 season 和 episode 可能是 0,没有
-}

+ 0 - 18
pkg/subtitle_best_api/ask_find_sub.go

@@ -1,18 +0,0 @@
-package subtitle_best_api
-
-type AskFindSubReq struct {
-	VideoFeature string `form:"video_feature"`    // VideoFeature ID
-	ImdbId       string `form:"imdb_id"`          // IMDB ID
-	TmdbId       string `form:"tmdb_id"`          // TMDB ID,这里是这个剧集的 TMDB ID 不是这一集的哈
-	Season       int    `form:"season"`           // 如果对应的是电影则可能是 0,没有
-	Episode      int    `form:"episode"`          // 如果对应的是电影则可能是 0,没有
-	FindSubToken string `form:"find_sub_token"`   // 查询令牌,由 Client 生成的 8 位随机字符,不包含特殊字符即可
-	ApiKey       string `form:"api_key,optional"` // API Key,非必须,可能是某些用户才有的权限
-}
-
-type AskFindSubReply struct {
-	Status            int        `json:"status"`              // 0 失败,1 成功,在缓存中有对应的信息,2 放入了队列,根据返回的时间再查询,3 查询队列满了,需要等待
-	Message           string     `json:"message"`             // 返回的信息,包括成功和失败的原因
-	Subtitle          []Subtitle `json:"subtitle,optional"`   // 如果查询成功,返回的字幕信息
-	ScheduledUnixTime int64      `json:"scheduled_unix_time"` // 预约查询的时间
-}

+ 0 - 13
pkg/subtitle_best_api/ask_for_download.go

@@ -1,13 +0,0 @@
-package subtitle_best_api
-
-type AskForDownloadReq struct {
-	SubSha256     string `form:"sub_sha256"`       // 文件的 SHA256
-	DownloadToken string `form:"download_token"`   // 下载令牌,对应具体服务器会相应回复对应的数据
-	ApiKey        string `form:"api_key,optional"` // API Key,非必须,可能是某些用户才有的权限
-}
-
-type AskForDownloadReply struct {
-	Status            int    `json:"status"`              // 0 失败,1 成功,2 放入了队列,根据返回的时间再下载,3 下载队列满了,需要等待
-	Message           string `json:"message"`             // 返回的信息,包括成功和失败的原因
-	ScheduledUnixTime int64  `json:"scheduled_unix_time"` // 预约的下载时间
-}

+ 0 - 16
pkg/subtitle_best_api/ask_for_upload.go

@@ -1,16 +0,0 @@
-package subtitle_best_api
-
-type AskForUploadReq struct {
-	SubSha256 string `json:"sub_sha256"`
-	Trusted   bool   `json:"trusted,optional"` // 是否是信任的字幕
-	ImdbId    string `form:"imdb_id,optional"` // IMDB ID
-	TmdbId    string `form:"tmdb_id,optional"` // TMDB ID,这里是这个剧集的 TMDB ID 不是这一集的哈
-	Season    int    `form:"season,optional"`  // 如果对应的是电影则可能是 0,没有
-	Episode   int    `form:"episode,optional"` // 如果对应的是电影则可能是 0,没有
-}
-
-type AskForUploadReply struct {
-	Status            int    `json:"status"` // 0 失败,1 成功,2 放入了队列,根据返回的时间再上传,3 已经存在,无需上传,本地标记上传了,4 上传队列满了,需要等待
-	Message           string `json:"message"`
-	ScheduledUnixTime int64  `json:"scheduled_unix_time,omitempty"`
-}

+ 0 - 13
pkg/subtitle_best_api/download_sub.go

@@ -1,13 +0,0 @@
-package subtitle_best_api
-
-type DownloadSubReq struct {
-	SubSha256     string `form:"sub_sha256"`       // 文件的 SHA256
-	DownloadToken string `form:"download_token"`   // 下载令牌
-	ApiKey        string `form:"api_key,optional"` // API Key,非必须,可能是某些用户才有的权限
-}
-
-type DownloadSubReply struct {
-	Status     int    `json:"status"`                // 0 失败,1 成功。应该说正常就是下载文件了,失败才会使用这个结构体
-	Message    string `json:"message"`               // 返回的信息,包括成功和失败的原因
-	StoreRPath string `json:"store_r_path,optional"` // 存储路径
-}

+ 0 - 18
pkg/subtitle_best_api/find_sub.go

@@ -1,18 +0,0 @@
-package subtitle_best_api
-
-type FindSubReq struct {
-	VideoFeature string `form:"video_feature"`    // VideoFeature ID
-	ImdbId       string `form:"imdb_id"`          // IMDB ID
-	TmdbId       string `form:"tmdb_id"`          // TMDB ID,这里是这个剧集的 TMDB ID 不是这一集的哈
-	Season       int    `form:"season"`           // 如果对应的是电影则可能是 0,没有
-	Episode      int    `form:"episode"`          // 如果对应的是电影则可能是 0,没有
-	FindSubToken string `form:"find_sub_token"`   // 查询令牌,由 Client 生成的 8 位随机字符,不包含特殊字符即可
-	ApiKey       string `form:"api_key,optional"` // API Key,非必须,可能是某些用户才有的权限
-}
-
-type FindSubReply struct {
-	Status            int        `json:"status"`  // 0 失败,1 成功
-	Message           string     `json:"message"` // 返回的信息,包括成功和失败的原因
-	Subtitle          []Subtitle `json:"subtitle,optional"`
-	ScheduledUnixTime int64      `json:"scheduled_unix_time"` // 预约的下载时间,可以不用,为了占位置用的
-}

+ 0 - 11
pkg/subtitle_best_api/subtitle.go

@@ -1,11 +0,0 @@
-package subtitle_best_api
-
-type Subtitle struct {
-	SubSha256         string `json:"sub_sha256"`              // 文件的 SHA256
-	IsDouble          bool   `json:"is_double"`               // 是否是双语,基础是中文
-	MyLanguage        string `json:"my_language"`             // 这个是本程序定义的语言类型,见 my_language.go 文件
-	LowTrust          bool   `json:"low_trust"`               // 是否是低信任的
-	ExtraPreName      string `json:"extra_pre_name,optional"` //字幕额外的命名信息,指 Emby 字幕命名格式(简英,subhd),的 subhd
-	MatchVideoFeature bool   `json:"match_video_feature"`     // 是否匹配到 VideoFeature
-	Ext               string `json:"ext"`                     // 字幕的后缀名
-}

+ 0 - 492
pkg/subtitle_best_api/subtitle_best_api.go

@@ -1,25 +1,16 @@
 package subtitle_best_api
 
 import (
-	"bytes"
 	"encoding/base64"
-	"encoding/json"
 	"errors"
 	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
 	"strconv"
 	"time"
 
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg"
 
-	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/common"
-
 	"github.com/sirupsen/logrus"
 
-	"github.com/ChineseSubFinder/ChineseSubFinder/internal/models"
-
 	"github.com/ChineseSubFinder/ChineseSubFinder/pkg/random_auth_key"
 )
 
@@ -161,441 +152,6 @@ func (s *SubtitleBestApi) GetMediaInfo(id, source, videoType string) (*MediaInfo
 	return &mediaInfoReply, nil
 }
 
-// AskFroUpload 在使用这个接口前,需要从 IMDB ID 获取到 TMDB ID
-func (s *SubtitleBestApi) AskFroUpload(subSha256 string, IsMovie, trusted bool, ImdbId, TmdbId string, Season, Episode int, VideoFeature string) (*AskForUploadReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	postUrl := webUrlBase + "/v1/ask-for-upload"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	isMovieStr := "false"
-	if IsMovie == true {
-		isMovieStr = "true"
-	}
-
-	trustedStr := "false"
-	if trusted == true {
-		trustedStr = "true"
-	}
-
-	formData := make(map[string]string)
-	if trusted == true {
-		formData["sub_sha256"] = subSha256
-		formData["is_movie"] = isMovieStr
-		formData["trusted"] = trustedStr
-		formData["imdb_id"] = ImdbId
-		formData["tmdb_id"] = TmdbId
-		formData["season"] = strconv.Itoa(Season)
-		formData["episode"] = strconv.Itoa(Episode)
-		formData["video_feature"] = VideoFeature
-	} else {
-		formData["sub_sha256"] = subSha256
-		formData["is_movie"] = isMovieStr
-	}
-
-	var askForUploadReply AskForUploadReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(formData).
-		SetResult(&askForUploadReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("ask for upload error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if askForUploadReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	return &askForUploadReply, nil
-}
-
-// UploadSub 在使用这个接口前,需要从 IMDB ID 获取到 TMDB ID,其实在这一步应该默认就拿到了 TMDB ID,需要提前在 AskFroUpload 接口调用前就搞定这个
-// year 这个也是从之前的接口拿到, 2019  or  2022
-func (s *SubtitleBestApi) UploadSub(videoSubInfo *models.VideoSubInfo, subSaveRootDirPath string, tmdbId, year string) (*UploadSubReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-
-	postUrl := webUrlBase + "/v1/upload-sub"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	// 从相对路径转换为绝对路径
-	subFileFPath := filepath.Join(subSaveRootDirPath, videoSubInfo.StoreRPath)
-	if pkg.IsFile(subFileFPath) == false {
-		return nil, errors.New(fmt.Sprintf("sub file not exist, %s", subFileFPath))
-	}
-	file, err := os.Open(subFileFPath)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("open sub file failed, %s", subFileFPath))
-	}
-	defer func() {
-		_ = file.Close()
-	}()
-	fd, err := ioutil.ReadAll(file)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("read sub file failed, %s", subFileFPath))
-	}
-
-	isDouble := "false"
-	if videoSubInfo.IsDouble == true {
-		isDouble = "true"
-	}
-
-	isMovieStr := "false"
-	if videoSubInfo.IsMovie == true {
-		isMovieStr = "true"
-	}
-
-	var uploadSubReply UploadSubReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFileReader("sub_file_context", videoSubInfo.SubName, bytes.NewReader(fd)).
-		SetFormData(map[string]string{
-			"sub_sha256":     videoSubInfo.SHA256,
-			"is_movie":       isMovieStr,
-			"season":         strconv.Itoa(videoSubInfo.Season),
-			"episode":        strconv.Itoa(videoSubInfo.Episode),
-			"is_double":      isDouble,
-			"language_iso":   videoSubInfo.LanguageISO,
-			"my_language":    videoSubInfo.MyLanguage,
-			"extra_pre_name": videoSubInfo.ExtraPreName,
-			"imdb_id":        videoSubInfo.IMDBInfoID,
-			"tmdb_id":        tmdbId,
-			"video_feature":  videoSubInfo.Feature,
-			"year":           year,
-		}).
-		SetResult(&uploadSubReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("upload sub error, status code:", resp.StatusCode(), "Error:", err)
-		if resp != nil && resp.StatusCode() == 413 {
-			// 文件上传大小超限
-			return nil, common.ErrorUpload413
-		}
-
-		return nil, err
-	}
-
-	if uploadSubReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-	if resp.StatusCode() == 413 {
-		// 文件上传大小超限
-		return nil, common.ErrorUpload413
-	}
-
-	return &uploadSubReply, nil
-}
-
-func (s *SubtitleBestApi) UploadLowTrustSub(lowTrustVideoSubInfo *models.LowVideoSubInfo, subSaveRootDirPath string, tmdbId, year, taskID string) (*UploadSubReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-
-	postUrl := webUrlBase + "/v1/upload-sub"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	// 从相对路径转换为绝对路径
-	subFileFPath := filepath.Join(subSaveRootDirPath, lowTrustVideoSubInfo.StoreRPath)
-	if pkg.IsFile(subFileFPath) == false {
-		return nil, errors.New(fmt.Sprintf("sub file not exist, %s", subFileFPath))
-	}
-	file, err := os.Open(subFileFPath)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("open sub file failed, %s", subFileFPath))
-	}
-	defer func() {
-		_ = file.Close()
-	}()
-	fd, err := ioutil.ReadAll(file)
-	if err != nil {
-		return nil, errors.New(fmt.Sprintf("read sub file failed, %s", subFileFPath))
-	}
-
-	isDouble := "false"
-	if lowTrustVideoSubInfo.IsDouble == true {
-		isDouble = "true"
-	}
-
-	isMovieStr := "false"
-	if lowTrustVideoSubInfo.IsMovie == true {
-		isMovieStr = "true"
-	}
-
-	var uploadSubReply UploadSubReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFileReader("sub_file_context", lowTrustVideoSubInfo.SubName, bytes.NewReader(fd)).
-		SetFormData(map[string]string{
-			"sub_sha256":     lowTrustVideoSubInfo.SHA256,
-			"is_movie":       isMovieStr,
-			"season":         strconv.Itoa(lowTrustVideoSubInfo.Season),
-			"episode":        strconv.Itoa(lowTrustVideoSubInfo.Episode),
-			"is_double":      isDouble,
-			"language_iso":   lowTrustVideoSubInfo.LanguageISO,
-			"my_language":    lowTrustVideoSubInfo.MyLanguage,
-			"extra_pre_name": lowTrustVideoSubInfo.ExtraPreName,
-			"imdb_id":        lowTrustVideoSubInfo.IMDBID,
-			"tmdb_id":        tmdbId,
-			"video_feature":  lowTrustVideoSubInfo.Feature,
-			"year":           year,
-			"low_trust":      "true",
-			"task_id":        taskID,
-		}).
-		SetResult(&uploadSubReply).
-		Post(postUrl)
-	if err != nil {
-
-		if resp != nil && resp.StatusCode() == 413 {
-			// 文件上传大小超限
-			s.log.Errorln("upload sub error, status code:", resp.StatusCode(), "Error:", err)
-			return nil, common.ErrorUpload413
-		}
-
-		s.log.Errorln("upload sub Error:", err)
-		return nil, err
-	}
-
-	if uploadSubReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	if resp.StatusCode() == 413 {
-		// 文件上传大小超限
-		return nil, common.ErrorUpload413
-	}
-
-	return &uploadSubReply, nil
-}
-
-func (s *SubtitleBestApi) AskFindSub(VideoFeature, ImdbId, TmdbId, Season, Episode, FindSubToken, ApiKey string) (*AskFindSubReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	postUrl := webUrlBase + "/v1/ask-find-sub"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	postData := map[string]string{
-		"video_feature":  VideoFeature,
-		"imdb_id":        ImdbId,
-		"tmdb_id":        TmdbId,
-		"season":         Season,
-		"episode":        Episode,
-		"find_sub_token": FindSubToken,
-	}
-	if ApiKey != "" {
-		postData["api_key"] = ApiKey
-	}
-	var askFindSubReply AskFindSubReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(postData).
-		SetResult(&askFindSubReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("ask find sub error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if askFindSubReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	return &askFindSubReply, nil
-}
-
-func (s *SubtitleBestApi) FindSub(VideoFeature, ImdbId, TmdbId, Season, Episode, FindSubToken, ApiKey string) (*FindSubReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	postUrl := webUrlBase + "/v1/find-sub"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	postData := map[string]string{
-		"video_feature":  VideoFeature,
-		"imdb_id":        ImdbId,
-		"tmdb_id":        TmdbId,
-		"season":         Season,
-		"episode":        Episode,
-		"find_sub_token": FindSubToken,
-	}
-	if ApiKey != "" {
-		postData["api_key"] = ApiKey
-	}
-	var findSubReply FindSubReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(postData).
-		SetResult(&findSubReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("find sub error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if findSubReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	return &findSubReply, nil
-}
-
-func (s *SubtitleBestApi) AskDownloadSub(SubSha256, DownloadToken, ApiKey string) (*AskForDownloadReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	postUrl := webUrlBase + "/v1/ask-for-download"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	postData := map[string]string{
-		"sub_sha256":     SubSha256,
-		"download_token": DownloadToken,
-	}
-	if ApiKey != "" {
-		postData["api_key"] = ApiKey
-	}
-	var askDownloadReply AskForDownloadReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(postData).
-		SetResult(&askDownloadReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("ask download sub error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if askDownloadReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	return &askDownloadReply, nil
-}
-
-// DownloadSub 首先要确认 downloadFileDesFPath 这个文件是否存在,如果存在且跟需要下载的文件的 sha256 一样就要跳过,然后下载完毕后,也需要 check 这个文件是否存在,存在则需要判断是否是字幕
-func (s *SubtitleBestApi) DownloadSub(SubSha256, DownloadToken, ApiKey, downloadFileDesFPath string) (*DownloadSubReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	postUrl := webUrlBase + "/v1/download-sub"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	postData := map[string]string{
-		"sub_sha256":     SubSha256,
-		"download_token": DownloadToken,
-	}
-	if ApiKey != "" {
-		postData["api_key"] = ApiKey
-	}
-
-	if pkg.IsFile(downloadFileDesFPath) == true {
-		err = os.Remove(downloadFileDesFPath)
-		if err != nil {
-			return nil, errors.New("remove file error: " + err.Error())
-		}
-	}
-
-	var downloadReply DownloadSubReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(postData).
-		SetOutput(downloadFileDesFPath).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("download sub error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if downloadReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	readFile, err := ioutil.ReadFile(downloadFileDesFPath)
-	if err != nil {
-		return nil, errors.New("read file error: " + err.Error())
-	}
-	err = json.Unmarshal(readFile, &downloadReply)
-	if err != nil {
-		// 说明成功了,但是出去,还是要再次判断这个是不是字幕文件才行
-		downloadReply.Status = 1
-		downloadReply.Message = "success"
-		return &downloadReply, nil
-	}
-	// 正常来说,只会获取到字幕,不会有这个 DownloadSubReply 结构的返回,上面获取到了字幕文件,也是伪造一个返回而已
-	// 说明返回的这个文件是正常的 reply 文件,那么需要把下载的文件给删除了
-	err = os.Remove(downloadFileDesFPath)
-	if err != nil {
-		return nil, errors.New("remove file error: " + err.Error())
-	}
-	return &downloadReply, nil
-}
-
 // ConvertId 目前仅仅支持 TMDB ID 转 IMDB ID
 func (s *SubtitleBestApi) ConvertId(id, source, videoType string) (*IdConvertReply, error) {
 
@@ -689,54 +245,6 @@ func (s *SubtitleBestApi) FeedBack(id, version, MediaServer string, EnableShare,
 	return &feedReply, nil
 }
 
-func (s *SubtitleBestApi) AskDownloadTask(id string) (*AskDownloadTaskReply, error) {
-
-	if s.authKey.BaseKey == random_auth_key.BaseKey || s.authKey.AESKey16 == random_auth_key.AESKey16 || s.authKey.AESIv16 == random_auth_key.AESIv16 {
-		return nil, errors.New("auth key is not set")
-	}
-	if len(s.authKey.AESKey16) != 16 {
-		return nil, errors.New(fmt.Sprintf("AESKey16 is not set, %s", s.authKey.AESKey16))
-	}
-	if len(s.authKey.AESIv16) != 16 {
-		return nil, errors.New(fmt.Sprintf("AESIv16 is not set, %s", s.authKey.AESIv16))
-	}
-
-	postUrl := webUrlBase + "/v1/ask-download-task"
-	httpClient, err := pkg.NewHttpClient()
-	if err != nil {
-		return nil, err
-	}
-
-	authKey, err := s.randomAuthKey.GetAuthKey()
-	if err != nil {
-		return nil, err
-	}
-
-	major, minor, patch := pkg.AppVersionInt()
-	var askDownloadTaskReply AskDownloadTaskReply
-	resp, err := httpClient.R().
-		SetHeader("Authorization", "beer "+authKey).
-		SetFormData(map[string]string{
-			"fid":               id,
-			"app_version_major": fmt.Sprintf("%d", major),
-			"app_version_minor": fmt.Sprintf("%d", minor),
-			"app_version_patch": fmt.Sprintf("%d", patch),
-		}).
-		SetResult(&askDownloadTaskReply).
-		Post(postUrl)
-	if err != nil {
-		s.log.Errorln("ask download task error, status code:", resp.StatusCode(), "Error:", err)
-		return nil, err
-	}
-
-	if askDownloadTaskReply.Status == 0 {
-		s.log.Warningln("status code:", resp.StatusCode())
-	}
-
-	return &askDownloadTaskReply, nil
-}
-
 const (
 	webUrlBase = "https://api.subtitle.best"
-	//webUrlBase = "http://127.0.0.1:8893"
 )

+ 0 - 20
pkg/subtitle_best_api/upload_sub.go

@@ -1,20 +0,0 @@
-package subtitle_best_api
-
-type UploadSubReq struct {
-	SubSha256    string `json:"sub_sha256"`     // 文件的 SHA256
-	Season       int    `json:"season"`         // 如果对应的是电影则可能是 0,没有
-	Episode      int    `json:"episode"`        // 如果对应的是电影则可能是 0,没有
-	IsDouble     bool   `json:"is_double"`      // 是否是双语,基础是中文
-	LanguageISO  string `json:"language_iso"`   // 字幕的语言,目标语言,就算是双语,中英,也应该是中文。ISO_639-1_codes 标准,见 ISOLanguage.go 文件,这里无法区分简体繁体
-	MyLanguage   string `json:"my_language"`    // 这个是本程序定义的语言类型,见 my_language.go 文件
-	ExtraPreName string `json:"extra_pre_name"` // 字幕额外的命名信息,指 Emby 字幕命名格式(简英,subhd),的 subhd
-	ImdbId       string `json:"imdb_id"`        // IMDB ID
-	TmdbId       string `json:"tmdb_id"`        // TMDB ID,这里是这个剧集的 TMDB ID 不是这一集的哈
-	VideoFeature string `json:"video_feature"`  // VideoFeature ID
-	Year         int    `json:"year"`           // 年份,比如 2019、2022
-}
-
-type UploadSubReply struct {
-	Status  int    `json:"status"` // 0 失败,1 成功,2 超过了上传时间,需要再此申请上传(AskForUploadReply)
-	Message string `json:"message"`
-}