mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-28 14:40:46 +08:00
code refactor
This commit is contained in:
@@ -21,6 +21,7 @@ func (Episode) Fields() []ent.Field {
|
||||
field.String("overview"),
|
||||
field.String("air_date"),
|
||||
field.Enum("status").Values("missing", "downloading", "downloaded").Default("missing"),
|
||||
field.Bool("monitored").Default(true).StructTag("json:\"monitored\""), //whether this episode is monitored
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ func (s *Server) GetAllActivities(c *gin.Context) (interface{}, error) {
|
||||
a := Activity{
|
||||
History: h,
|
||||
}
|
||||
for id, task := range s.tasks {
|
||||
for id, task := range s.core.GetTasks() {
|
||||
if h.ID == id && task.Exists() {
|
||||
a.Progress = task.Progress()
|
||||
}
|
||||
@@ -54,13 +54,11 @@ func (s *Server) RemoveActivity(c *gin.Context) (interface{}, error) {
|
||||
log.Errorf("no record of id: %d", id)
|
||||
return nil, nil
|
||||
}
|
||||
torrent := s.tasks[his.ID]
|
||||
if torrent != nil {
|
||||
if err := torrent.Remove(); err != nil {
|
||||
return nil, errors.Wrap(err, "remove torrent")
|
||||
}
|
||||
delete(s.tasks, his.ID)
|
||||
|
||||
if err := s.core.RemoveTaskAndTorrent(his.ID); err != nil {
|
||||
return nil, errors.Wrap(err, "remove torrent")
|
||||
}
|
||||
|
||||
if his.EpisodeID != 0 {
|
||||
s.db.SetEpisodeStatus(his.EpisodeID, episode.StatusMissing)
|
||||
|
||||
@@ -96,7 +94,7 @@ func (s *Server) GetMediaDownloadHistory(c *gin.Context) (interface{}, error) {
|
||||
|
||||
type TorrentInfo struct {
|
||||
Name string `json:"name"`
|
||||
ID int64 `json:"id"`
|
||||
ID int64 `json:"id"`
|
||||
SeedRatio float32 `json:"seed_ratio"`
|
||||
Progress int `json:"progress"`
|
||||
}
|
||||
@@ -116,8 +114,8 @@ func (s *Server) GetAllTorrents(c *gin.Context) (interface{}, error) {
|
||||
continue
|
||||
}
|
||||
infos = append(infos, TorrentInfo{
|
||||
Name: t.Name(),
|
||||
ID: t.ID,
|
||||
Name: t.Name(),
|
||||
ID: t.ID,
|
||||
Progress: t.Progress(),
|
||||
})
|
||||
}
|
||||
|
||||
94
server/core/client.go
Normal file
94
server/core/client.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"polaris/db"
|
||||
"polaris/ent"
|
||||
"polaris/log"
|
||||
"polaris/pkg/tmdb"
|
||||
"polaris/pkg/transmission"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/robfig/cron"
|
||||
)
|
||||
|
||||
func NewClient(db *db.Client, language string) *Client {
|
||||
return &Client{
|
||||
db: db,
|
||||
cron: cron.New(),
|
||||
tasks: make(map[int]*Task, 0),
|
||||
language: language,
|
||||
}
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
db *db.Client
|
||||
cron *cron.Cron
|
||||
tasks map[int]*Task
|
||||
language string
|
||||
}
|
||||
|
||||
func (c *Client) Init() {
|
||||
c.reloadTasks()
|
||||
c.addSysCron()
|
||||
}
|
||||
|
||||
func (c *Client) reloadTasks() {
|
||||
allTasks := c.db.GetHistories()
|
||||
for _, t := range allTasks {
|
||||
torrent, err := transmission.ReloadTorrent(t.Saved)
|
||||
if err != nil {
|
||||
log.Errorf("relaod task %s failed: %v", t.SourceTitle, err)
|
||||
continue
|
||||
}
|
||||
if !torrent.Exists() { //只要种子还存在于客户端中,就重新加载,有可能是还在做种中
|
||||
continue
|
||||
}
|
||||
log.Infof("reloading task: %d %s", t.ID, t.SourceTitle)
|
||||
c.tasks[t.ID] = &Task{Torrent: torrent}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) getDownloadClient() (*transmission.Client, *ent.DownloadClients, error) {
|
||||
tr := c.db.GetTransmission()
|
||||
trc, err := transmission.NewClient(transmission.Config{
|
||||
URL: tr.URL,
|
||||
User: tr.User,
|
||||
Password: tr.Password,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
return trc, tr, nil
|
||||
}
|
||||
|
||||
func (c *Client) TMDB() (*tmdb.Client, error) {
|
||||
api := c.db.GetSetting(db.SettingTmdbApiKey)
|
||||
if api == "" {
|
||||
return nil, errors.New("TMDB apiKey not set")
|
||||
}
|
||||
return tmdb.NewClient(api)
|
||||
}
|
||||
|
||||
func (c *Client) MustTMDB() *tmdb.Client {
|
||||
t, err := c.TMDB()
|
||||
if err != nil {
|
||||
log.Panicf("get tmdb: %v", err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
func (c *Client) RemoveTaskAndTorrent(id int)error {
|
||||
torrent := c.tasks[id]
|
||||
if torrent != nil {
|
||||
if err := torrent.Remove(); err != nil {
|
||||
return errors.Wrap(err, "remove torrent")
|
||||
}
|
||||
delete(c.tasks, id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) GetTasks() map[int]*Task {
|
||||
return c.tasks
|
||||
}
|
||||
121
server/core/integration.go
Normal file
121
server/core/integration.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"polaris/db"
|
||||
"polaris/ent/media"
|
||||
storage1 "polaris/ent/storage"
|
||||
"polaris/log"
|
||||
"polaris/pkg/notifier"
|
||||
"polaris/pkg/storage"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) writePlexmatch(seriesId int, episodeId int, targetDir, name string) error {
|
||||
|
||||
if !c.plexmatchEnabled() {
|
||||
return nil
|
||||
}
|
||||
series, err := c.db.GetMedia(seriesId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if series.MediaType != media.MediaTypeTv {
|
||||
return nil
|
||||
}
|
||||
st, err := c.getStorage(series.StorageID, media.MediaTypeTv)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get storage")
|
||||
}
|
||||
|
||||
//series plexmatch file
|
||||
_, err = st.ReadFile(filepath.Join(series.TargetDir, ".plexmatch"))
|
||||
if err != nil {
|
||||
//create new
|
||||
log.Warnf(".plexmatch file not found, create new one: %s", series.NameEn)
|
||||
if err := st.WriteFile(filepath.Join(series.TargetDir, ".plexmatch"),
|
||||
[]byte(fmt.Sprintf("tmdbid: %d\n", series.TmdbID))); err != nil {
|
||||
return errors.Wrap(err, "series plexmatch")
|
||||
}
|
||||
}
|
||||
|
||||
//season plexmatch file
|
||||
ep, err := c.db.GetEpisodeByID(episodeId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "query episode")
|
||||
}
|
||||
buff := bytes.Buffer{}
|
||||
seasonPlex := filepath.Join(targetDir, ".plexmatch")
|
||||
data, err := st.ReadFile(seasonPlex)
|
||||
if err != nil {
|
||||
log.Infof("read season plexmatch: %v", err)
|
||||
} else {
|
||||
buff.Write(data)
|
||||
}
|
||||
buff.WriteString(fmt.Sprintf("\nep: %d: %s\n", ep.EpisodeNumber, name))
|
||||
log.Infof("write season plexmatch file content: %s", buff.String())
|
||||
return st.WriteFile(seasonPlex, buff.Bytes())
|
||||
}
|
||||
|
||||
func (c *Client) plexmatchEnabled() bool {
|
||||
return c.db.GetSetting(db.SettingPlexMatchEnabled) == "true"
|
||||
}
|
||||
|
||||
func (c *Client) getStorage(storageId int, mediaType media.MediaType) (storage.Storage, error) {
|
||||
st := c.db.GetStorage(storageId)
|
||||
targetPath := st.TvPath
|
||||
if mediaType == media.MediaTypeMovie {
|
||||
targetPath = st.MoviePath
|
||||
}
|
||||
|
||||
switch st.Implementation {
|
||||
case storage1.ImplementationLocal:
|
||||
|
||||
storageImpl1, err := storage.NewLocalStorage(targetPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new local")
|
||||
}
|
||||
return storageImpl1, nil
|
||||
|
||||
case storage1.ImplementationWebdav:
|
||||
ws := st.ToWebDavSetting()
|
||||
storageImpl1, err := storage.NewWebdavStorage(ws.URL, ws.User, ws.Password, targetPath, ws.ChangeFileHash == "true")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new webdav")
|
||||
}
|
||||
return storageImpl1, nil
|
||||
}
|
||||
return nil, errors.New("no storage found")
|
||||
}
|
||||
|
||||
func (c *Client) sendMsg(msg string) {
|
||||
clients, err := c.db.GetAllNotificationClients2()
|
||||
if err != nil {
|
||||
log.Errorf("query notification clients: %v", err)
|
||||
return
|
||||
}
|
||||
for _, cl := range clients {
|
||||
if !cl.Enabled {
|
||||
continue
|
||||
}
|
||||
handler, ok := notifier.Gethandler(cl.Service)
|
||||
if !ok {
|
||||
log.Errorf("no notification implementation of service %s", cl.Service)
|
||||
continue
|
||||
}
|
||||
noCl, err := handler(cl.Settings)
|
||||
if err != nil {
|
||||
log.Errorf("handle setting for name %s error: %v", cl.Name, err)
|
||||
continue
|
||||
}
|
||||
err = noCl.SendMsg(msg)
|
||||
if err != nil {
|
||||
log.Errorf("send message error: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("send message to %s success, msg is %s", cl.Name, msg)
|
||||
}
|
||||
}
|
||||
165
server/core/resources.go
Normal file
165
server/core/resources.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"polaris/ent"
|
||||
"polaris/ent/episode"
|
||||
"polaris/ent/history"
|
||||
"polaris/log"
|
||||
"polaris/pkg/notifier/message"
|
||||
"polaris/pkg/torznab"
|
||||
"polaris/pkg/utils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) DownloadSeasonPackage(r1 torznab.Result, seriesId, seasonNum int) (*string, error) {
|
||||
trc, dlClient, err := c.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
downloadDir := c.db.GetDownloadDir()
|
||||
size := utils.AvailableSpace(downloadDir)
|
||||
if size < uint64(r1.Size) {
|
||||
log.Errorf("space available %v, space needed %v", size, r1.Size)
|
||||
return nil, errors.New("no enough space")
|
||||
}
|
||||
|
||||
torrent, err := trc.Download(r1.Link, c.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
series := c.db.GetMediaDetails(seriesId)
|
||||
if series == nil {
|
||||
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
||||
}
|
||||
dir := fmt.Sprintf("%s/Season %02d/", series.TargetDir, seasonNum)
|
||||
|
||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: seriesId,
|
||||
EpisodeID: 0,
|
||||
SourceTitle: r1.Name,
|
||||
TargetDir: dir,
|
||||
Status: history.StatusRunning,
|
||||
Size: r1.Size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlClient.ID,
|
||||
IndexerID: r1.IndexerId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "save record")
|
||||
}
|
||||
c.db.SetSeasonAllEpisodeStatus(seriesId, seasonNum, episode.StatusDownloading)
|
||||
|
||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
c.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name))
|
||||
return &r1.Name, nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (c *Client) DownloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
trc, dlc, err := c.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
series := c.db.GetMediaDetails(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)
|
||||
}
|
||||
torrent, err := trc.Download(r1.Link, c.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
dir := fmt.Sprintf("%s/Season %02d/", series.TargetDir, seasonNum)
|
||||
|
||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: ep.MediaID,
|
||||
EpisodeID: ep.ID,
|
||||
SourceTitle: r1.Name,
|
||||
TargetDir: dir,
|
||||
Status: history.StatusRunning,
|
||||
Size: r1.Size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlc.ID,
|
||||
IndexerID: r1.IndexerId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "save record")
|
||||
}
|
||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
|
||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
c.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name))
|
||||
|
||||
log.Infof("success add %s to download task", r1.Name)
|
||||
return &r1.Name, nil
|
||||
|
||||
}
|
||||
func (c *Client) SearchAndDownload(seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
|
||||
res, err := SearchEpisode(c.db, seriesId, seasonNum, episodeNum, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r1 := res[0]
|
||||
log.Infof("found resource to download: %+v", r1)
|
||||
return c.DownloadEpisodeTorrent(r1, seriesId, seasonNum, episodeNum)
|
||||
}
|
||||
|
||||
func (c *Client) DownloadMovie(m *ent.Media,link, name string, size int, indexerID int) (*string, error) {
|
||||
trc, dlc, err := c.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
|
||||
torrent, err := trc.Download(link, c.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
if name == "" {
|
||||
name = m.OriginalName
|
||||
}
|
||||
go func() {
|
||||
ep, _ := c.db.GetMovieDummyEpisode(m.ID)
|
||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: m.ID,
|
||||
EpisodeID: ep.ID,
|
||||
SourceTitle: name,
|
||||
TargetDir: m.TargetDir,
|
||||
Status: history.StatusRunning,
|
||||
Size: size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlc.ID,
|
||||
IndexerID: indexerID,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("save history error: %v", err)
|
||||
}
|
||||
|
||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
}()
|
||||
|
||||
c.sendMsg(fmt.Sprintf(message.BeginDownload, name))
|
||||
log.Infof("success add %s to download task", name)
|
||||
return &name, nil
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package server
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -11,44 +11,43 @@ import (
|
||||
"polaris/pkg"
|
||||
"polaris/pkg/notifier/message"
|
||||
"polaris/pkg/utils"
|
||||
"polaris/server/core"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (s *Server) scheduler() {
|
||||
s.mustAddCron("@every 1m", s.checkTasks)
|
||||
s.mustAddCron("0 0 * * * *", func() {
|
||||
s.downloadTvSeries()
|
||||
s.downloadMovie()
|
||||
func (c *Client) addSysCron() {
|
||||
c.mustAddCron("@every 1m", c.checkTasks)
|
||||
c.mustAddCron("0 0 * * * *", func() {
|
||||
c.downloadTvSeries()
|
||||
c.downloadMovie()
|
||||
})
|
||||
s.mustAddCron("0 0 */12 * * *", s.checkAllSeriesNewSeason)
|
||||
s.cron.Start()
|
||||
c.mustAddCron("0 0 */12 * * *", c.checkAllSeriesNewSeason)
|
||||
c.cron.Start()
|
||||
}
|
||||
|
||||
func (s *Server) mustAddCron(spec string, cmd func()) {
|
||||
if err := s.cron.AddFunc(spec, cmd); err != nil {
|
||||
func (c *Client) mustAddCron(spec string, cmd func()) {
|
||||
if err := c.cron.AddFunc(spec, cmd); err != nil {
|
||||
log.Errorf("add func error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) checkTasks() {
|
||||
func (c *Client) checkTasks() {
|
||||
log.Debug("begin check tasks...")
|
||||
for id, t := range s.tasks {
|
||||
for id, t := range c.tasks {
|
||||
if !t.Exists() {
|
||||
log.Infof("task no longer exists: %v", id)
|
||||
delete(s.tasks, id)
|
||||
delete(c.tasks, id)
|
||||
continue
|
||||
}
|
||||
log.Infof("task (%s) percentage done: %d%%", t.Name(), t.Progress())
|
||||
if t.Progress() == 100 {
|
||||
r := s.db.GetHistory(id)
|
||||
r := c.db.GetHistory(id)
|
||||
if r.Status == history.StatusSuccess {
|
||||
//task already success, check seed ratio
|
||||
torrent := s.tasks[id]
|
||||
ok, err := s.isSeedRatioLimitReached(r.IndexerID, torrent)
|
||||
torrent := c.tasks[id]
|
||||
ok, err := c.isSeedRatioLimitReached(r.IndexerID, torrent)
|
||||
if err != nil {
|
||||
log.Warnf("getting torrent seed ratio : %v", err)
|
||||
ok = false
|
||||
@@ -56,16 +55,16 @@ func (s *Server) checkTasks() {
|
||||
if ok {
|
||||
log.Infof("torrent file seed ratio reached, remove: %v", torrent.Name())
|
||||
torrent.Remove()
|
||||
delete(s.tasks, id)
|
||||
delete(c.tasks, id)
|
||||
} else {
|
||||
log.Infof("torrent file still sedding: %v", torrent.Name())
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.Infof("task is done: %v", t.Name())
|
||||
s.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name()))
|
||||
c.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name()))
|
||||
go func() {
|
||||
if err := s.moveCompletedTask(id); err != nil {
|
||||
if err := c.moveCompletedTask(id); err != nil {
|
||||
log.Infof("post tasks for id %v fail: %v", id, err)
|
||||
}
|
||||
}()
|
||||
@@ -73,20 +72,20 @@ func (s *Server) checkTasks() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) moveCompletedTask(id int) (err1 error) {
|
||||
torrent := s.tasks[id]
|
||||
r := s.db.GetHistory(id)
|
||||
func (c *Client) moveCompletedTask(id int) (err1 error) {
|
||||
torrent := c.tasks[id]
|
||||
r := c.db.GetHistory(id)
|
||||
if r.Status == history.StatusUploading {
|
||||
log.Infof("task %d is already uploading, skip", id)
|
||||
return nil
|
||||
}
|
||||
s.db.SetHistoryStatus(r.ID, history.StatusUploading)
|
||||
c.db.SetHistoryStatus(r.ID, history.StatusUploading)
|
||||
seasonNum, err := utils.SeasonId(r.TargetDir)
|
||||
if err != nil {
|
||||
log.Errorf("no season id: %v", r.TargetDir)
|
||||
seasonNum = -1
|
||||
}
|
||||
downloadclient, err := s.db.GetDownloadClient(r.DownloadClientID)
|
||||
downloadclient, err := c.db.GetDownloadClient(r.DownloadClientID)
|
||||
if err != nil {
|
||||
log.Errorf("get task download client error: %v, use default one", err)
|
||||
downloadclient = &ent.DownloadClients{RemoveCompletedDownloads: true, RemoveFailedDownloads: true}
|
||||
@@ -96,59 +95,59 @@ func (s *Server) moveCompletedTask(id int) (err1 error) {
|
||||
defer func() {
|
||||
|
||||
if err1 != nil {
|
||||
s.db.SetHistoryStatus(r.ID, history.StatusFail)
|
||||
c.db.SetHistoryStatus(r.ID, history.StatusFail)
|
||||
if r.EpisodeID != 0 {
|
||||
s.db.SetEpisodeStatus(r.EpisodeID, episode.StatusMissing)
|
||||
c.db.SetEpisodeStatus(r.EpisodeID, episode.StatusMissing)
|
||||
} else {
|
||||
s.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusMissing)
|
||||
c.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusMissing)
|
||||
}
|
||||
s.sendMsg(fmt.Sprintf(message.ProcessingFailed, err))
|
||||
c.sendMsg(fmt.Sprintf(message.ProcessingFailed, err))
|
||||
if downloadclient.RemoveFailedDownloads {
|
||||
log.Debugf("task failed, remove failed torrent and files related")
|
||||
delete(s.tasks, r.ID)
|
||||
delete(c.tasks, r.ID)
|
||||
torrent.Remove()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
series := s.db.GetMediaDetails(r.MediaID)
|
||||
series := c.db.GetMediaDetails(r.MediaID)
|
||||
if series == nil {
|
||||
return nil
|
||||
}
|
||||
st := s.db.GetStorage(series.StorageID)
|
||||
st := c.db.GetStorage(series.StorageID)
|
||||
log.Infof("move task files to target dir: %v", r.TargetDir)
|
||||
stImpl, err := s.getStorage(st.ID, series.MediaType)
|
||||
stImpl, err := c.getStorage(st.ID, series.MediaType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//如果种子是路径,则会把路径展开,只移动文件,类似 move dir/* dir2/, 如果种子是文件,则会直接移动文件,类似 move file dir/
|
||||
if err := stImpl.Copy(filepath.Join(s.db.GetDownloadDir(), torrentName), r.TargetDir); err != nil {
|
||||
if err := stImpl.Copy(filepath.Join(c.db.GetDownloadDir(), torrentName), r.TargetDir); err != nil {
|
||||
return errors.Wrap(err, "move file")
|
||||
}
|
||||
|
||||
// .plexmatch file
|
||||
if err := s.writePlexmatch(r.MediaID, r.EpisodeID, r.TargetDir, torrentName); err != nil {
|
||||
if err := c.writePlexmatch(r.MediaID, r.EpisodeID, r.TargetDir, torrentName); err != nil {
|
||||
log.Errorf("create .plexmatch file error: %v", err)
|
||||
}
|
||||
|
||||
s.db.SetHistoryStatus(r.ID, history.StatusSuccess)
|
||||
c.db.SetHistoryStatus(r.ID, history.StatusSuccess)
|
||||
if r.EpisodeID != 0 {
|
||||
s.db.SetEpisodeStatus(r.EpisodeID, episode.StatusDownloaded)
|
||||
c.db.SetEpisodeStatus(r.EpisodeID, episode.StatusDownloaded)
|
||||
} else {
|
||||
s.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusDownloaded)
|
||||
c.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusDownloaded)
|
||||
}
|
||||
s.sendMsg(fmt.Sprintf(message.ProcessingComplete, torrentName))
|
||||
c.sendMsg(fmt.Sprintf(message.ProcessingComplete, torrentName))
|
||||
|
||||
//判断是否需要删除本地文件
|
||||
ok, err := s.isSeedRatioLimitReached(r.IndexerID, torrent)
|
||||
ok, err := c.isSeedRatioLimitReached(r.IndexerID, torrent)
|
||||
if err != nil {
|
||||
log.Warnf("getting torrent seed ratio %s: %v", torrent.Name(), err)
|
||||
ok = false
|
||||
}
|
||||
if downloadclient.RemoveCompletedDownloads && ok {
|
||||
log.Debugf("download complete,remove torrent and files related")
|
||||
delete(s.tasks, r.ID)
|
||||
delete(c.tasks, r.ID)
|
||||
torrent.Remove()
|
||||
}
|
||||
|
||||
@@ -156,13 +155,13 @@ func (s *Server) moveCompletedTask(id int) (err1 error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) checkDownloadedSeriesFiles(m *ent.Media) error {
|
||||
func (c *Client) CheckDownloadedSeriesFiles(m *ent.Media) error {
|
||||
if m.MediaType != media.MediaTypeTv {
|
||||
return nil
|
||||
}
|
||||
log.Infof("check files in directory: %s", m.TargetDir)
|
||||
|
||||
var storageImpl, err = s.getStorage(m.StorageID, media.MediaTypeTv)
|
||||
var storageImpl, err = c.getStorage(m.StorageID, media.MediaTypeTv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -190,12 +189,12 @@ func (s *Server) checkDownloadedSeriesFiles(m *ent.Media) error {
|
||||
continue
|
||||
}
|
||||
log.Infof("found match, season num %d, episode num %d", seNum, epNum)
|
||||
ep, err := s.db.GetEpisode(m.ID, seNum, epNum)
|
||||
ep, err := c.db.GetEpisode(m.ID, seNum, epNum)
|
||||
if err != nil {
|
||||
log.Error("update episode: %v", err)
|
||||
continue
|
||||
}
|
||||
err = s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloaded)
|
||||
err = c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloaded)
|
||||
if err != nil {
|
||||
log.Error("update episode: %v", err)
|
||||
continue
|
||||
@@ -212,11 +211,11 @@ type Task struct {
|
||||
pkg.Torrent
|
||||
}
|
||||
|
||||
func (s *Server) downloadTvSeries() {
|
||||
func (c *Client) downloadTvSeries() {
|
||||
log.Infof("begin check all tv series resources")
|
||||
allSeries := s.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
allSeries := c.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
for _, series := range allSeries {
|
||||
tvDetail := s.db.GetMediaDetails(series.ID)
|
||||
tvDetail := c.db.GetMediaDetails(series.ID)
|
||||
for _, ep := range tvDetail.Episodes {
|
||||
if !series.DownloadHistoryEpisodes { //设置不下载历史已播出剧集,只下载将来剧集
|
||||
t, err := time.Parse("2006-01-02", ep.AirDate)
|
||||
@@ -232,7 +231,7 @@ func (s *Server) downloadTvSeries() {
|
||||
if ep.Status != episode.StatusMissing { //已经下载的不去下载
|
||||
continue
|
||||
}
|
||||
name, err := s.searchAndDownload(series.ID, ep.SeasonNumber, ep.EpisodeNumber)
|
||||
name, err := c.SearchAndDownload(series.ID, ep.SeasonNumber, ep.EpisodeNumber)
|
||||
if err != nil {
|
||||
log.Infof("cannot find resource to download for %s: %v", ep.Title, err)
|
||||
} else {
|
||||
@@ -244,12 +243,12 @@ func (s *Server) downloadTvSeries() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) downloadMovie() {
|
||||
func (c *Client) downloadMovie() {
|
||||
log.Infof("begin check all movie resources")
|
||||
allSeries := s.db.GetMediaWatchlist(media.MediaTypeMovie)
|
||||
allSeries := c.db.GetMediaWatchlist(media.MediaTypeMovie)
|
||||
|
||||
for _, series := range allSeries {
|
||||
detail := s.db.GetMediaDetails(series.ID)
|
||||
detail := c.db.GetMediaDetails(series.ID)
|
||||
if len(detail.Episodes) == 0 {
|
||||
log.Errorf("no related dummy episode: %v", detail.NameEn)
|
||||
continue
|
||||
@@ -259,32 +258,32 @@ func (s *Server) downloadMovie() {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.downloadMovieSingleEpisode(ep); err != nil {
|
||||
if err := c.downloadMovieSingleEpisode(ep); err != nil {
|
||||
log.Errorf("download movie error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) downloadMovieSingleEpisode(ep *ent.Episode) error {
|
||||
trc, dlc, err := s.getDownloadClient()
|
||||
func (c *Client) downloadMovieSingleEpisode(ep *ent.Episode) error {
|
||||
trc, dlc, err := c.getDownloadClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
|
||||
res, err := core.SearchMovie(s.db, ep.MediaID, true)
|
||||
res, err := SearchMovie(c.db, ep.MediaID, true)
|
||||
if err != nil {
|
||||
|
||||
return errors.Wrap(err, "search movie")
|
||||
}
|
||||
r1 := res[0]
|
||||
log.Infof("begin download torrent resource: %v", r1.Name)
|
||||
torrent, err := trc.Download(r1.Link, s.db.GetDownloadDir())
|
||||
torrent, err := trc.Download(r1.Link, c.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
history, err := s.db.SaveHistoryRecord(ent.History{
|
||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: ep.MediaID,
|
||||
EpisodeID: ep.ID,
|
||||
SourceTitle: r1.Name,
|
||||
@@ -298,36 +297,36 @@ func (s *Server) downloadMovieSingleEpisode(ep *ent.Episode) error {
|
||||
log.Errorf("save history error: %v", err)
|
||||
}
|
||||
|
||||
s.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) checkAllSeriesNewSeason() {
|
||||
func (c *Client) checkAllSeriesNewSeason() {
|
||||
log.Infof("begin checking series all new season")
|
||||
allSeries := s.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
allSeries := c.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
for _, series := range allSeries {
|
||||
err := s.checkSeiesNewSeason(series)
|
||||
err := c.checkSeiesNewSeason(series)
|
||||
if err != nil {
|
||||
log.Errorf("check series new season error: series name %v, error: %v", series.NameEn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) checkSeiesNewSeason(media *ent.Media) error {
|
||||
d, err := s.MustTMDB().GetTvDetails(media.TmdbID, s.language)
|
||||
func (c *Client) checkSeiesNewSeason(media *ent.Media) error {
|
||||
d, err := c.MustTMDB().GetTvDetails(media.TmdbID, c.language)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tmdb")
|
||||
}
|
||||
lastsSason := d.NumberOfSeasons
|
||||
seasonDetail, err := s.MustTMDB().GetSeasonDetails(media.TmdbID, lastsSason, s.language)
|
||||
seasonDetail, err := c.MustTMDB().GetSeasonDetails(media.TmdbID, lastsSason, c.language)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tmdb season")
|
||||
}
|
||||
|
||||
for _, ep := range seasonDetail.Episodes {
|
||||
epDb, err := s.db.GetEpisode(media.ID, ep.SeasonNumber, ep.EpisodeNumber)
|
||||
epDb, err := c.db.GetEpisode(media.ID, ep.SeasonNumber, ep.EpisodeNumber)
|
||||
if err != nil {
|
||||
if ent.IsNotFound(err) {
|
||||
log.Infof("add new episode: %+v", ep)
|
||||
@@ -340,20 +339,20 @@ func (s *Server) checkSeiesNewSeason(media *ent.Media) error {
|
||||
AirDate: ep.AirDate,
|
||||
Status: episode.StatusMissing,
|
||||
}
|
||||
s.db.SaveEposideDetail2(episode)
|
||||
c.db.SaveEposideDetail2(episode)
|
||||
}
|
||||
} else { //update episode
|
||||
if ep.Name != epDb.Title || ep.Overview != epDb.Overview || ep.AirDate != epDb.AirDate {
|
||||
log.Infof("update new episode: %+v", ep)
|
||||
s.db.UpdateEpiode2(epDb.ID, ep.Name, ep.Overview, ep.AirDate)
|
||||
c.db.UpdateEpiode2(epDb.ID, ep.Name, ep.Overview, ep.AirDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) isSeedRatioLimitReached(indexId int, t pkg.Torrent) (bool, error) {
|
||||
indexer, err := s.db.GetIndexer(indexId)
|
||||
func (c *Client) isSeedRatioLimitReached(indexId int, t pkg.Torrent) (bool, error) {
|
||||
indexer, err := c.db.GetIndexer(indexId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"polaris/db"
|
||||
"polaris/ent/media"
|
||||
"polaris/log"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (s *Server) writePlexmatch(seriesId int, episodeId int, targetDir, name string) error {
|
||||
|
||||
if !s.plexmatchEnabled() {
|
||||
return nil
|
||||
}
|
||||
series, err := s.db.GetMedia(seriesId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if series.MediaType != media.MediaTypeTv {
|
||||
return nil
|
||||
}
|
||||
st, err := s.getStorage(series.StorageID, media.MediaTypeTv)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get storage")
|
||||
}
|
||||
|
||||
//series plexmatch file
|
||||
_, err = st.ReadFile(filepath.Join(series.TargetDir, ".plexmatch"))
|
||||
if err != nil {
|
||||
//create new
|
||||
log.Warnf(".plexmatch file not found, create new one: %s", series.NameEn)
|
||||
if err := st.WriteFile(filepath.Join(series.TargetDir, ".plexmatch"),
|
||||
[]byte(fmt.Sprintf("tmdbid: %d\n",series.TmdbID))); err != nil {
|
||||
return errors.Wrap(err, "series plexmatch")
|
||||
}
|
||||
}
|
||||
|
||||
//season plexmatch file
|
||||
ep, err := s.db.GetEpisodeByID(episodeId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "query episode")
|
||||
}
|
||||
buff := bytes.Buffer{}
|
||||
seasonPlex := filepath.Join(targetDir, ".plexmatch")
|
||||
data, err := st.ReadFile(seasonPlex)
|
||||
if err != nil {
|
||||
log.Infof("read season plexmatch: %v", err)
|
||||
} else {
|
||||
buff.Write(data)
|
||||
}
|
||||
buff.WriteString(fmt.Sprintf("\nep: %d: %s\n", ep.EpisodeNumber, name))
|
||||
log.Infof("write season plexmatch file content: %s", buff.String())
|
||||
return st.WriteFile(seasonPlex, buff.Bytes())
|
||||
}
|
||||
|
||||
func (s *Server) plexmatchEnabled() bool {
|
||||
return s.db.GetSetting(db.SettingPlexMatchEnabled) == "true"
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package server
|
||||
|
||||
import (
|
||||
"polaris/ent"
|
||||
"polaris/log"
|
||||
"polaris/pkg/notifier"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -44,32 +42,3 @@ func (s *Server) AddNotificationClient(c *gin.Context) (interface{}, error) {
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *Server) sendMsg(msg string) {
|
||||
clients, err := s.db.GetAllNotificationClients2()
|
||||
if err != nil {
|
||||
log.Errorf("query notification clients: %v", err)
|
||||
return
|
||||
}
|
||||
for _, cl := range clients {
|
||||
if !cl.Enabled {
|
||||
continue
|
||||
}
|
||||
handler, ok := notifier.Gethandler(cl.Service)
|
||||
if !ok {
|
||||
log.Errorf("no notification implementation of service %s", cl.Service)
|
||||
continue
|
||||
}
|
||||
noCl, err := handler(cl.Settings)
|
||||
if err != nil {
|
||||
log.Errorf("handle setting for name %s error: %v", cl.Name, err)
|
||||
continue
|
||||
}
|
||||
err = noCl.SendMsg(msg)
|
||||
if err != nil {
|
||||
log.Errorf("send message error: %v", err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("send message to %s success, msg is %s", cl.Name, msg)
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,9 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"polaris/ent"
|
||||
"polaris/ent/episode"
|
||||
"polaris/ent/history"
|
||||
"polaris/ent/media"
|
||||
"polaris/log"
|
||||
"polaris/pkg/notifier/message"
|
||||
"polaris/pkg/torznab"
|
||||
"polaris/pkg/utils"
|
||||
"polaris/server/core"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -25,117 +20,10 @@ func (s *Server) searchAndDownloadSeasonPackage(seriesId, seasonNum int) (*strin
|
||||
|
||||
r1 := res[0]
|
||||
log.Infof("found resource to download: %+v", r1)
|
||||
return s.downloadSeasonPackage(r1, seriesId, seasonNum)
|
||||
return s.core.DownloadSeasonPackage(r1, seriesId, seasonNum)
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) downloadSeasonPackage(r1 torznab.Result, seriesId, seasonNum int) (*string, error) {
|
||||
trc, dlClient, err := s.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
downloadDir := s.db.GetDownloadDir()
|
||||
size := utils.AvailableSpace(downloadDir)
|
||||
if size < uint64(r1.Size) {
|
||||
log.Errorf("space available %v, space needed %v", size, r1.Size)
|
||||
return nil, errors.New("no enough space")
|
||||
}
|
||||
|
||||
torrent, err := trc.Download(r1.Link, s.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
series := s.db.GetMediaDetails(seriesId)
|
||||
if series == nil {
|
||||
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
||||
}
|
||||
dir := fmt.Sprintf("%s/Season %02d/", series.TargetDir, seasonNum)
|
||||
|
||||
history, err := s.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: seriesId,
|
||||
EpisodeID: 0,
|
||||
SourceTitle: r1.Name,
|
||||
TargetDir: dir,
|
||||
Status: history.StatusRunning,
|
||||
Size: r1.Size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlClient.ID,
|
||||
IndexerID: r1.IndexerId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "save record")
|
||||
}
|
||||
s.db.SetSeasonAllEpisodeStatus(seriesId, seasonNum, episode.StatusDownloading)
|
||||
|
||||
s.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
s.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name))
|
||||
return &r1.Name, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) downloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
trc, dlc, err := s.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
series := s.db.GetMediaDetails(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)
|
||||
}
|
||||
torrent, err := trc.Download(r1.Link, s.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
dir := fmt.Sprintf("%s/Season %02d/", series.TargetDir, seasonNum)
|
||||
|
||||
history, err := s.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: ep.MediaID,
|
||||
EpisodeID: ep.ID,
|
||||
SourceTitle: r1.Name,
|
||||
TargetDir: dir,
|
||||
Status: history.StatusRunning,
|
||||
Size: r1.Size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlc.ID,
|
||||
IndexerID: r1.IndexerId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "save record")
|
||||
}
|
||||
s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
|
||||
s.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
s.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name))
|
||||
|
||||
log.Infof("success add %s to download task", r1.Name)
|
||||
return &r1.Name, nil
|
||||
|
||||
}
|
||||
func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
|
||||
res, err := core.SearchEpisode(s.db, seriesId, seasonNum, episodeNum, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r1 := res[0]
|
||||
log.Infof("found resource to download: %+v", r1)
|
||||
return s.downloadEpisodeTorrent(r1, seriesId, seasonNum, episodeNum)
|
||||
}
|
||||
|
||||
type searchAndDownloadIn struct {
|
||||
ID int `json:"id" binding:"required"`
|
||||
Season int `json:"season"`
|
||||
@@ -203,7 +91,7 @@ func (s *Server) SearchTvAndDownload(c *gin.Context) (interface{}, error) {
|
||||
name = *name1
|
||||
} else {
|
||||
log.Infof("season episode search")
|
||||
name1, err := s.searchAndDownload(in.ID, in.Season, in.Episode)
|
||||
name1, err := s.core.SearchAndDownload(in.ID, in.Season, in.Episode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "download")
|
||||
}
|
||||
@@ -241,55 +129,17 @@ func (s *Server) DownloadTorrent(c *gin.Context) (interface{}, error) {
|
||||
name = fmt.Sprintf("%v S%02d", m.OriginalName, in.Season)
|
||||
}
|
||||
res := torznab.Result{Name: name, Link: in.Link, Size: in.Size}
|
||||
return s.downloadSeasonPackage(res, in.MediaID, in.Season)
|
||||
return s.core.DownloadSeasonPackage(res, in.MediaID, in.Season)
|
||||
}
|
||||
name := in.Name
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("%v S%02dE%02d", m.OriginalName, in.Season, in.Episode)
|
||||
}
|
||||
res := torznab.Result{Name: name, Link: in.Link, Size: in.Size, IndexerId: in.IndexerId}
|
||||
return s.downloadEpisodeTorrent(res, in.MediaID, in.Season, in.Episode)
|
||||
return s.core.DownloadEpisodeTorrent(res, in.MediaID, in.Season, in.Episode)
|
||||
} else {
|
||||
//movie
|
||||
trc, dlc, err := s.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
|
||||
torrent, err := trc.Download(in.Link, s.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
name := in.Name
|
||||
if name == "" {
|
||||
name = m.OriginalName
|
||||
}
|
||||
go func() {
|
||||
ep, _ := s.db.GetMovieDummyEpisode(m.ID)
|
||||
history, err := s.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: m.ID,
|
||||
EpisodeID: ep.ID,
|
||||
SourceTitle: name,
|
||||
TargetDir: m.TargetDir,
|
||||
Status: history.StatusRunning,
|
||||
Size: in.Size,
|
||||
Saved: torrent.Save(),
|
||||
DownloadClientID: dlc.ID,
|
||||
IndexerID: in.IndexerId,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("save history error: %v", err)
|
||||
}
|
||||
|
||||
s.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
}()
|
||||
|
||||
s.sendMsg(fmt.Sprintf(message.BeginDownload, in.Name))
|
||||
log.Infof("success add %s to download task", in.Name)
|
||||
return in.Name, nil
|
||||
return s.core.DownloadMovie(m, in.Link, in.Name, in.Size, in.IndexerId)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,13 +8,12 @@ import (
|
||||
"polaris/db"
|
||||
"polaris/log"
|
||||
"polaris/pkg/tmdb"
|
||||
"polaris/pkg/transmission"
|
||||
"polaris/server/core"
|
||||
"polaris/ui"
|
||||
|
||||
ginzap "github.com/gin-contrib/zap"
|
||||
|
||||
"github.com/gin-contrib/static"
|
||||
"github.com/robfig/cron"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
@@ -22,26 +21,25 @@ import (
|
||||
|
||||
func NewServer(db *db.Client) *Server {
|
||||
r := gin.Default()
|
||||
return &Server{
|
||||
r: r,
|
||||
db: db,
|
||||
cron: cron.New(),
|
||||
tasks: make(map[int]*Task),
|
||||
s := &Server{
|
||||
r: r,
|
||||
db: db,
|
||||
}
|
||||
s.core = core.NewClient(db, s.language)
|
||||
return s
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
r *gin.Engine
|
||||
db *db.Client
|
||||
cron *cron.Cron
|
||||
core *core.Client
|
||||
language string
|
||||
tasks map[int]*Task
|
||||
jwtSerect string
|
||||
}
|
||||
|
||||
func (s *Server) Serve() error {
|
||||
s.scheduler()
|
||||
s.reloadTasks()
|
||||
s.core.Init()
|
||||
|
||||
s.restoreProxy()
|
||||
|
||||
s.jwtSerect = s.db.GetSetting(db.JwtSerectKey)
|
||||
@@ -142,22 +140,6 @@ func (s *Server) MustTMDB() *tmdb.Client {
|
||||
return t
|
||||
}
|
||||
|
||||
func (s *Server) reloadTasks() {
|
||||
allTasks := s.db.GetHistories()
|
||||
for _, t := range allTasks {
|
||||
torrent, err := transmission.ReloadTorrent(t.Saved)
|
||||
if err != nil {
|
||||
log.Errorf("relaod task %s failed: %v", t.SourceTitle, err)
|
||||
continue
|
||||
}
|
||||
if !torrent.Exists() { //只要种子还存在于客户端中,就重新加载,有可能是还在做种中
|
||||
continue
|
||||
}
|
||||
log.Infof("reloading task: %d %s", t.ID, t.SourceTitle)
|
||||
s.tasks[t.ID] = &Task{Torrent: torrent}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) proxyPosters(c *gin.Context) {
|
||||
remote, _ := url.Parse("https://image.tmdb.org")
|
||||
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||
|
||||
@@ -3,8 +3,7 @@ package server
|
||||
import (
|
||||
"fmt"
|
||||
"polaris/db"
|
||||
"polaris/ent/media"
|
||||
storage1 "polaris/ent/storage"
|
||||
|
||||
"polaris/log"
|
||||
"polaris/pkg/storage"
|
||||
"strconv"
|
||||
@@ -113,30 +112,3 @@ func (s *Server) SuggestedMovieFolderName(c *gin.Context) (interface{}, error) {
|
||||
log.Infof("tv series of tmdb id %v suggestting name is %v", id, name)
|
||||
return gin.H{"name": name}, nil
|
||||
}
|
||||
|
||||
func (s *Server) getStorage(storageId int, mediaType media.MediaType) (storage.Storage, error) {
|
||||
st := s.db.GetStorage(storageId)
|
||||
targetPath := st.TvPath
|
||||
if mediaType == media.MediaTypeMovie {
|
||||
targetPath = st.MoviePath
|
||||
}
|
||||
|
||||
switch st.Implementation {
|
||||
case storage1.ImplementationLocal:
|
||||
|
||||
storageImpl1, err := storage.NewLocalStorage(targetPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new local")
|
||||
}
|
||||
return storageImpl1, nil
|
||||
|
||||
case storage1.ImplementationWebdav:
|
||||
ws := st.ToWebDavSetting()
|
||||
storageImpl1, err := storage.NewWebdavStorage(ws.URL, ws.User, ws.Password, targetPath, ws.ChangeFileHash == "true")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new webdav")
|
||||
}
|
||||
return storageImpl1, nil
|
||||
}
|
||||
return nil, errors.New("no storage found")
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ func (s *Server) AddTv2Watchlist(c *gin.Context) (interface{}, error) {
|
||||
if err := s.downloadBackdrop(detail.BackdropPath, r.ID); err != nil {
|
||||
log.Errorf("download poster error: %v", err)
|
||||
}
|
||||
if err := s.checkDownloadedSeriesFiles(r); err != nil {
|
||||
if err := s.core.CheckDownloadedSeriesFiles(r); err != nil {
|
||||
log.Errorf("check downloaded files error: %v", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user