mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-27 14:10:48 +08:00
163 lines
3.8 KiB
Go
163 lines
3.8 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"polaris/db"
|
|
"polaris/log"
|
|
"polaris/pkg/metadata"
|
|
"polaris/pkg/torznab"
|
|
"polaris/pkg/utils"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func SearchSeasonPackage(db1 *db.Client, seriesId, seasonNum int, checkResolution bool) ([]torznab.Result, error) {
|
|
return SearchEpisode(db1, seriesId, seasonNum, -1, checkResolution)
|
|
}
|
|
|
|
func isNumberedSeries(detail *db.MediaDetails) bool {
|
|
hasSeason2 := false
|
|
season2HasEpisode1 := false
|
|
for _, ep := range detail.Episodes {
|
|
if ep.SeasonNumber == 2 {
|
|
hasSeason2 = true
|
|
if ep.EpisodeNumber == 1 {
|
|
season2HasEpisode1 = true
|
|
}
|
|
|
|
}
|
|
}
|
|
return hasSeason2 && !season2HasEpisode1//only one 1st episode
|
|
}
|
|
|
|
func SearchEpisode(db1 *db.Client, seriesId, seasonNum, episodeNum int, checkResolution bool) ([]torznab.Result, error) {
|
|
series := db1.GetMediaDetails(seriesId)
|
|
if series == nil {
|
|
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
|
}
|
|
|
|
res := searchWithTorznab(db1, series.NameEn)
|
|
resCn := searchWithTorznab(db1, series.NameCn)
|
|
res = append(res, resCn...)
|
|
|
|
var filtered []torznab.Result
|
|
for _, r := range res {
|
|
//log.Infof("torrent resource: %+v", r)
|
|
meta := metadata.ParseTv(r.Name)
|
|
if meta == nil { //cannot parse name
|
|
continue
|
|
}
|
|
if !isNumberedSeries(series) { //do not check season on series that only rely on episode number
|
|
if meta.Season != seasonNum {
|
|
continue
|
|
}
|
|
}
|
|
if isNumberedSeries(series) && episodeNum == -1 {
|
|
//should not want season
|
|
continue
|
|
}
|
|
|
|
if episodeNum != -1 && meta.Episode != episodeNum { //not season pack, episode number equals
|
|
continue
|
|
} else if seasonNum == -1 && !meta.IsSeasonPack { //want season pack, but not season pack
|
|
continue
|
|
}
|
|
if checkResolution && meta.Resolution != series.Resolution.String() {
|
|
continue
|
|
}
|
|
if !utils.IsNameAcceptable(meta.NameEn, series.NameEn) && !utils.IsNameAcceptable(meta.NameCn, series.NameCn) {
|
|
continue
|
|
}
|
|
filtered = append(filtered, r)
|
|
}
|
|
if len(filtered) == 0 {
|
|
return nil, errors.New("no resource found")
|
|
}
|
|
|
|
return filtered, nil
|
|
|
|
}
|
|
|
|
func SearchMovie(db1 *db.Client, movieId int, checkResolution bool) ([]torznab.Result, error) {
|
|
movieDetail := db1.GetMediaDetails(movieId)
|
|
if movieDetail == nil {
|
|
return nil, errors.New("no media found of id")
|
|
}
|
|
|
|
res := searchWithTorznab(db1, movieDetail.NameEn)
|
|
|
|
res1 := searchWithTorznab(db1, movieDetail.NameCn)
|
|
res = append(res, res1...)
|
|
|
|
if len(res) == 0 {
|
|
return nil, fmt.Errorf("no resource found")
|
|
}
|
|
var filtered []torznab.Result
|
|
for _, r := range res {
|
|
meta := metadata.ParseMovie(r.Name)
|
|
if !utils.IsNameAcceptable(meta.NameEn, movieDetail.NameEn) {
|
|
continue
|
|
}
|
|
if checkResolution && meta.Resolution != movieDetail.Resolution.String() {
|
|
continue
|
|
}
|
|
ss := strings.Split(movieDetail.AirDate, "-")[0]
|
|
year, _ := strconv.Atoi(ss)
|
|
if meta.Year != year && meta.Year != year-1 && meta.Year != year+1 { //year not match
|
|
continue
|
|
}
|
|
|
|
filtered = append(filtered, r)
|
|
|
|
}
|
|
if len(filtered) == 0 {
|
|
return nil, errors.New("no resource found")
|
|
}
|
|
|
|
return filtered, nil
|
|
|
|
}
|
|
|
|
func searchWithTorznab(db *db.Client, q string) []torznab.Result {
|
|
|
|
var res []torznab.Result
|
|
allTorznab := db.GetAllTorznabInfo()
|
|
resChan := make(chan []torznab.Result)
|
|
var wg sync.WaitGroup
|
|
|
|
for _, tor := range allTorznab {
|
|
wg.Add(1)
|
|
go func () {
|
|
log.Debugf("search torznab %v with %v", tor.Name, q)
|
|
defer wg.Done()
|
|
resp, err := torznab.Search(tor.URL, tor.ApiKey, q)
|
|
if err != nil {
|
|
log.Errorf("search %s error: %v", tor.Name, err)
|
|
return
|
|
}
|
|
resChan <- resp
|
|
|
|
}()
|
|
}
|
|
go func() {
|
|
wg.Wait()
|
|
close(resChan) // 在所有的worker完成后关闭Channel
|
|
}()
|
|
|
|
for result := range resChan {
|
|
res = append(res, result...)
|
|
}
|
|
|
|
sort.Slice(res, func(i, j int) bool {
|
|
var s1 = res[i]
|
|
var s2 = res[j]
|
|
return s1.Seeders > s2.Seeders
|
|
})
|
|
|
|
return res
|
|
}
|