mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 23:21:00 +08:00
217 lines
5.4 KiB
Go
217 lines
5.4 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"polaris/db"
|
|
"polaris/ent"
|
|
"polaris/ent/episode"
|
|
"polaris/ent/history"
|
|
"polaris/log"
|
|
"polaris/pkg/torznab"
|
|
"polaris/pkg/transmission"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func (s *Server) searchTvWithTorznab(name string, season, episode int) []torznab.Result {
|
|
q := fmt.Sprintf("%s S%02dE%02d", name, season, episode)
|
|
|
|
var res []torznab.Result
|
|
allTorznab := s.db.GetAllTorznabInfo()
|
|
for _, tor := range allTorznab {
|
|
resp, err := torznab.Search(tor.URL, tor.ApiKey, q)
|
|
if err != nil {
|
|
log.Errorf("search %s error: %v", tor.Name, err)
|
|
continue
|
|
}
|
|
res = append(res, resp...)
|
|
}
|
|
return res
|
|
}
|
|
|
|
type addTorznabIn struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
ApiKey string `json:"api_key"`
|
|
}
|
|
|
|
func (s *Server) AddTorznabInfo(c *gin.Context) (interface{}, error) {
|
|
var in addTorznabIn
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
return nil, errors.Wrap(err, "bind json")
|
|
}
|
|
err := s.db.SaveTorznabInfo(in.Name, db.TorznabSetting{
|
|
URL: in.URL,
|
|
ApiKey: in.ApiKey,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "add ")
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *Server) DeleteTorznabInfo(c *gin.Context) (interface{}, error) {
|
|
var ids = c.Param("id")
|
|
id, err := strconv.Atoi(ids)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("id is not correct: %v", ids)
|
|
}
|
|
s.db.DeleteTorznab(id)
|
|
return "success", nil
|
|
}
|
|
|
|
func (s *Server) GetAllIndexers(c *gin.Context) (interface{}, error) {
|
|
indexers := s.db.GetAllTorznabInfo()
|
|
if len(indexers) == 0 {
|
|
return nil, nil
|
|
}
|
|
return indexers, nil
|
|
}
|
|
|
|
type searchAndDownloadIn struct {
|
|
ID int `json:"id"`
|
|
Season int `json:"season"`
|
|
Episode int `json:"episode"`
|
|
}
|
|
|
|
func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string, error) {
|
|
tr := s.db.GetTransmission()
|
|
trc, err := transmission.NewClient(transmission.Config{
|
|
URL: tr.URL,
|
|
User: tr.User,
|
|
Password: tr.Password,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "connect transmission")
|
|
}
|
|
series := s.db.GetSeriesDetails(seriesId)
|
|
if series == nil {
|
|
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
|
}
|
|
var ep *ent.Episode
|
|
for _, e := range series.Episodes {
|
|
if e.SeasonNumber == seasonNum && e.EpisodeNumber == episodeNum {
|
|
ep = e
|
|
}
|
|
}
|
|
if ep == nil {
|
|
return nil, errors.Errorf("no episode of season %d episode %d", seasonNum, episodeNum)
|
|
}
|
|
|
|
res := s.searchTvWithTorznab(series.OriginalName, seasonNum, episodeNum)
|
|
if len(res) == 0 {
|
|
return nil, fmt.Errorf("no resource found")
|
|
}
|
|
r1 := s.findBestMatch(res, seasonNum, episodeNum, series)
|
|
log.Infof("found resource to download: %v", r1)
|
|
torrent, err := trc.Download(r1.Magnet, s.db.GetDownloadDir())
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "downloading")
|
|
}
|
|
torrent.Start()
|
|
|
|
dir := fmt.Sprintf("%s/Season %02d", series.TargetDir, ep.SeasonNumber)
|
|
|
|
history, err :=s.db.SaveHistoryRecord(ent.History{
|
|
SeriesID: ep.SeriesID,
|
|
EpisodeID: ep.ID,
|
|
SourceTitle: r1.Name,
|
|
TargetDir: dir,
|
|
Status: history.StatusRunning,
|
|
Saved: torrent.Save(),
|
|
})
|
|
s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "save record")
|
|
}
|
|
s.tasks[history.ID] = &Task{Torrent: torrent}
|
|
|
|
log.Infof("success add %s to download task", r1.Name)
|
|
return &r1.Name, nil
|
|
}
|
|
|
|
func (s *Server) findBestMatch(resources []torznab.Result,season, episode int, series *db.SeriesDetails) torznab.Result {
|
|
var filtered []torznab.Result
|
|
for _, r := range resources {
|
|
if !(series.NameEn != "" && strings.Contains(r.Name,series.NameEn)) && !strings.Contains(r.Name, series.OriginalName) {
|
|
//name not match
|
|
continue
|
|
}
|
|
|
|
se := fmt.Sprintf("S%02dE%02d", season, episode)
|
|
if !strings.Contains(r.Name, se) {
|
|
//season or episode not match
|
|
continue
|
|
}
|
|
if !strings.Contains(strings.ToLower(r.Name), series.Resolution) {
|
|
//resolution not match
|
|
continue
|
|
}
|
|
filtered = append(filtered, r)
|
|
}
|
|
|
|
sort.Slice(filtered, func(i, j int) bool {
|
|
var s1 = filtered[i]
|
|
var s2 = filtered[2]
|
|
return s1.Seeders > s2.Seeders
|
|
})
|
|
|
|
return filtered[0]
|
|
}
|
|
|
|
func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) {
|
|
var in searchAndDownloadIn
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
return nil, errors.Wrap(err, "bind json")
|
|
}
|
|
log.Infof("search episode resources link: %v", in)
|
|
name, err := s.searchAndDownload(in.ID, in.Season, in.Episode)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "download")
|
|
}
|
|
|
|
return gin.H{
|
|
"name": *name,
|
|
}, nil
|
|
}
|
|
|
|
type downloadClientIn struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
User string `json:"user"`
|
|
Password string `json:"password"`
|
|
Implementation string `json:"implementation"`
|
|
}
|
|
|
|
func (s *Server) AddDownloadClient(c *gin.Context) (interface{}, error) {
|
|
var in downloadClientIn
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
return nil, errors.Wrap(err, "bind json")
|
|
}
|
|
if err := s.db.SaveTransmission(in.Name, in.URL, in.User, in.Password); err != nil {
|
|
return nil, errors.Wrap(err, "save transmission")
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *Server) GetAllDonloadClients(c *gin.Context) (interface{}, error) {
|
|
res := s.db.GetAllDonloadClients()
|
|
if len(res) == 0 {
|
|
return nil, nil
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func (s *Server) DeleteDownloadCLient(c *gin.Context) (interface{}, error) {
|
|
var ids = c.Param("id")
|
|
id, err := strconv.Atoi(ids)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("id is not correct: %v", ids)
|
|
}
|
|
s.db.DeleteDownloadCLient(id)
|
|
return "success", nil
|
|
} |