implement download feature

This commit is contained in:
Simon Ding
2024-07-10 17:35:16 +08:00
parent d7d5c72518
commit e500aaed1e
43 changed files with 4903 additions and 227 deletions

View File

@@ -3,10 +3,12 @@ package server
import (
"fmt"
"polaris/db"
"polaris/ent"
"polaris/log"
"polaris/pkg/torznab"
"polaris/pkg/transmission"
"strconv"
"strings"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
@@ -88,6 +90,15 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) {
if series == nil {
return nil, fmt.Errorf("no tv series of id %v", in.ID)
}
var ep *ent.Episode
for _, e := range series.Episodes {
if e.SeasonNumber == in.Season && e.EpisodeNumber == in.Episode {
ep = e
}
}
if ep == nil {
return nil, errors.Errorf("no episode of season %d episode %d", in.Season, in.Episode)
}
res := s.searchTvWithTorznab(series.OriginalName, in.Season, in.Episode)
if len(res) == 0 {
@@ -95,11 +106,33 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) {
}
r1 := res[0]
log.Infof("found resource to download: %v", r1)
torrent, err := trc.Download(r1.Magnet)
torrent, err := trc.Download(r1.Magnet, s.db.GetDownloadDir())
if err != nil {
return nil, errors.Wrap(err, "downloading")
}
s.tasks[r1.Name] = torrent
torrent.Start()
var name = series.NameEn
if name == "" {
name = series.OriginalName
}
var year = strings.Split(series.AirDate, "-")[0]
dir := fmt.Sprintf("%s (%s)/Season %02d", name, year, ep.SeasonNumber)
history, err :=s.db.SaveHistoryRecord(ent.History{
SeriesID: ep.SeriesID,
EpisodeID: ep.ID,
SourceTitle: r1.Name,
TargetDir: dir,
Completed: false,
Saved: torrent.Save(),
})
if err != nil {
return nil, errors.Wrap(err, "save record")
}
s.tasks[history.ID] = torrent
// t, err := downloader.DownloadByMagnet(r1.Magnet, "~")
// if err != nil {
// return nil, errors.Wrap(err, "download torrent")

49
server/scheduler.go Normal file
View File

@@ -0,0 +1,49 @@
package server
import (
"path/filepath"
"polaris/db"
"polaris/log"
"polaris/pkg/storage"
"github.com/pkg/errors"
)
func (s *Server) scheduler() {
s.cron.AddFunc("@every 1m", s.checkTasks)
}
func (s *Server) checkTasks() {
for id, t := range s.tasks {
log.Infof("task %s percentage done: %d%%", t.Name(), t.Progress())
if t.Progress() == 100 {
log.Infof("task is done: %v", t.Name())
s.moveCompletedTask(id)
}
}
}
func (s *Server) moveCompletedTask(id int) error {
torrent := s.tasks[id]
r := s.db.GetHistory(id)
series := s.db.GetSeriesDetails(r.SeriesID)
st := s.db.GetStorage(series.StorageID)
if st.Implementation == db.ImplWebdav {
storageImpl, err := storage.NewWebdavStorage(st.Path, st.User, st.Password)
if err != nil {
return errors.Wrap(err, "new webdav")
}
if err := storageImpl.Move(filepath.Join(s.db.GetDownloadDir(), torrent.Name()), r.TargetDir); err != nil {
return errors.Wrap(err, "move webdav")
}
} else if st.Implementation == db.ImplLocal {
storageImpl := storage.NewLocalStorage(st.Path)
if err := storageImpl.Move(filepath.Join(s.db.GetDownloadDir(), torrent.Name()), r.TargetDir); err != nil {
return errors.Wrap(err, "move webdav")
}
}
log.Infof("move downloaded files to target dir success, file: %v, target dir: %v", torrent.Name(), r.TargetDir)
return nil
}

View File

@@ -3,11 +3,11 @@ package server
import (
"polaris/db"
"polaris/log"
"polaris/pkg"
"polaris/pkg/tmdb"
"polaris/ui"
"github.com/gin-contrib/static"
"github.com/hekmon/transmissionrpc"
"github.com/robfig/cron"
"github.com/gin-gonic/gin"
@@ -20,7 +20,7 @@ func NewServer(db *db.Client) *Server {
r: r,
db: db,
cron: cron.New(),
tasks: make(map[string]*transmissionrpc.Torrent),
tasks: make(map[int]pkg.Torrent),
}
}
@@ -29,18 +29,9 @@ type Server struct {
db *db.Client
cron *cron.Cron
language string
tasks map[string]*transmissionrpc.Torrent
tasks map[int]pkg.Torrent
}
func (s *Server) scheduler() {
s.cron.AddFunc("@every 1m", s.checkTasks)
}
func (s *Server) checkTasks() {
for name, t := range s.tasks {
log.Infof("task %s percentage done: %f", name, *t.PercentDone)
}
}
func (s *Server) Serve() error {
s.scheduler()
@@ -76,6 +67,12 @@ func (s *Server) Serve() error {
downloader.POST("/add", HttpHandler(s.AddDownloadClient))
downloader.DELETE("/del/:id", HttpHandler(s.DeleteDownloadCLient))
}
storage := api.Group("/storage")
{
storage.GET("/", HttpHandler(s.GetAllStorage))
storage.POST("/", HttpHandler(s.AddStorage))
storage.DELETE("/:id", HttpHandler(s.DeleteStorage))
}
s.language = s.db.GetLanguage()
return s.r.Run(":8080")

37
server/storage.go Normal file
View File

@@ -0,0 +1,37 @@
package server
import (
"fmt"
"polaris/db"
"polaris/log"
"strconv"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
func (s *Server) GetAllStorage(c *gin.Context) (interface{}, error) {
data := s.db.GetAllStorage()
return data, nil
}
func (s *Server) AddStorage(c *gin.Context) (interface{}, error) {
var in db.StorageInfo
if err := c.ShouldBindJSON(&in); err != nil {
return nil, errors.Wrap(err, "bind json")
}
log.Infof("received add storage input: %v", in)
err := s.db.AddStorage(in)
return nil, err
}
func (s *Server) DeleteStorage(c *gin.Context) (interface{}, error) {
ids := c.Param("id")
id, err := strconv.Atoi(ids)
if err != nil {
return nil, fmt.Errorf("id is not int: %v", ids)
}
err = s.db.DeleteStorage(id)
return nil, err
}

View File

@@ -1,6 +1,7 @@
package server
import (
"polaris/db"
"polaris/ent"
"polaris/log"
"strconv"
@@ -27,8 +28,8 @@ func (s *Server) SearchTvSeries(c *gin.Context) (interface{}, error) {
}
type addWatchlistIn struct {
ID int `json:"id" binding:"required"`
RootFolder string `json:"folder" binding:"required"`
TmdbID int `json:"id" binding:"required"`
StorageID int `json:"folder"`
}
func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
@@ -36,11 +37,22 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
if err := c.ShouldBindJSON(&in); err != nil {
return nil, errors.Wrap(err, "bind query")
}
detail, err := s.MustTMDB().GetTvDetails(in.ID, s.language)
detail, err := s.MustTMDB().GetTvDetails(in.TmdbID, s.language)
if err != nil {
return nil, errors.Wrap(err, "get tv detail")
}
log.Infof("find detail for tv id %d: %v", in.ID, detail)
log.Infof("find detail for tv id %d: %v", in.TmdbID, detail)
var nameEn = detail.OriginalName
alterTitles, err := s.MustTMDB().GetTVAlternativeTitles(in.TmdbID, s.language)
if err == nil {
for _, r := range alterTitles.Results {
if r.Iso3166_1 == "US" {
log.Infof("found en name: %s", r.Title)
nameEn = r.Title
}
}
}
var epIds []int
@@ -66,7 +78,7 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
epIds = append(epIds, epid)
}
}
_, err = s.db.AddWatchlist(in.RootFolder, detail, epIds)
_, err = s.db.AddWatchlist(in.StorageID, nameEn, detail, epIds, db.R1080p)
if err != nil {
return nil, errors.Wrap(err, "add to list")
}