mirror of
https://github.com/simon-ding/polaris.git
synced 2026-04-21 11:17:30 +08:00
feat: add movie tracking feature
This commit is contained in:
@@ -17,8 +17,7 @@ import (
|
||||
"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)
|
||||
func (s *Server) searchWithTorznab(q string) []torznab.Result {
|
||||
|
||||
var res []torznab.Result
|
||||
allTorznab := s.db.GetAllTorznabInfo()
|
||||
@@ -72,23 +71,25 @@ func (s *Server) GetAllIndexers(c *gin.Context) (interface{}, error) {
|
||||
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) {
|
||||
func (s *Server) getDownloadClient() (*transmission.Client, error) {
|
||||
tr := s.db.GetTransmission()
|
||||
trc, err := transmission.NewClient(transmission.Config{
|
||||
URL: tr.URL,
|
||||
User: tr.User,
|
||||
URL: tr.URL,
|
||||
User: tr.User,
|
||||
Password: tr.Password,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
series := s.db.GetSeriesDetails(seriesId)
|
||||
return trc, nil
|
||||
}
|
||||
func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
trc, 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)
|
||||
}
|
||||
@@ -102,11 +103,13 @@ func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string
|
||||
return nil, errors.Errorf("no episode of season %d episode %d", seasonNum, episodeNum)
|
||||
}
|
||||
|
||||
res := s.searchTvWithTorznab(series.OriginalName, seasonNum, episodeNum)
|
||||
q := fmt.Sprintf("%s S%02dE%02d", series.OriginalName, seasonNum, episodeNum)
|
||||
|
||||
res := s.searchWithTorznab(q)
|
||||
if len(res) == 0 {
|
||||
return nil, fmt.Errorf("no resource found")
|
||||
}
|
||||
r1 := s.findBestMatch(res, seasonNum, episodeNum, series)
|
||||
r1 := s.findBestMatchTv(res, seasonNum, episodeNum, series)
|
||||
log.Infof("found resource to download: %v", r1)
|
||||
torrent, err := trc.Download(r1.Magnet, s.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
@@ -116,14 +119,14 @@ func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string
|
||||
|
||||
dir := fmt.Sprintf("%s/Season %02d", series.TargetDir, ep.SeasonNumber)
|
||||
|
||||
history, err :=s.db.SaveHistoryRecord(ent.History{
|
||||
SeriesID: ep.SeriesID,
|
||||
EpisodeID: ep.ID,
|
||||
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(),
|
||||
TargetDir: dir,
|
||||
Status: history.StatusRunning,
|
||||
Size: r1.Size,
|
||||
Saved: torrent.Save(),
|
||||
})
|
||||
s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||
if err != nil {
|
||||
@@ -135,10 +138,10 @@ func (s *Server) searchAndDownload(seriesId, seasonNum, episodeNum int) (*string
|
||||
return &r1.Name, nil
|
||||
}
|
||||
|
||||
func (s *Server) findBestMatch(resources []torznab.Result,season, episode int, series *db.SeriesDetails) torznab.Result {
|
||||
func (s *Server) findBestMatchTv(resources []torznab.Result, season, episode int, series *db.MediaDetails) 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) {
|
||||
if !(series.NameEn != "" && strings.Contains(r.Name, series.NameEn)) && !strings.Contains(r.Name, series.OriginalName) {
|
||||
//name not match
|
||||
continue
|
||||
}
|
||||
@@ -164,7 +167,13 @@ func (s *Server) findBestMatch(resources []torznab.Result,season, episode int, s
|
||||
return filtered[0]
|
||||
}
|
||||
|
||||
func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) {
|
||||
type searchAndDownloadIn struct {
|
||||
ID int `json:"id" binding:"required"`
|
||||
Season int `json:"season"`
|
||||
Episode int `json:"episode"`
|
||||
}
|
||||
|
||||
func (s *Server) SearchTvAndDownload(c *gin.Context) (interface{}, error) {
|
||||
var in searchAndDownloadIn
|
||||
if err := c.ShouldBindJSON(&in); err != nil {
|
||||
return nil, errors.Wrap(err, "bind json")
|
||||
@@ -180,6 +189,105 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
type TorznabSearchResult struct {
|
||||
Name string `json:"name"`
|
||||
Size int `json:"size"`
|
||||
Link string `json:"link"`
|
||||
Seeders int `json:"seeders"`
|
||||
Peers int `json:"peers"`
|
||||
}
|
||||
|
||||
func (s *Server) SearchAvailableMovies(c *gin.Context) (interface{}, error) {
|
||||
ids := c.Param("id")
|
||||
id, err := strconv.Atoi(ids)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert")
|
||||
}
|
||||
|
||||
movieDetail := s.db.GetMediaDetails(id)
|
||||
if movieDetail == nil {
|
||||
return nil, errors.New("no media found of id " + ids)
|
||||
}
|
||||
|
||||
res := s.searchWithTorznab(movieDetail.NameEn)
|
||||
|
||||
res1 := s.searchWithTorznab(movieDetail.NameCn)
|
||||
res = append(res, res1...)
|
||||
|
||||
if len(res) == 0 {
|
||||
return nil, fmt.Errorf("no resource found")
|
||||
}
|
||||
|
||||
var searchResults []TorznabSearchResult
|
||||
for _, r := range res {
|
||||
|
||||
searchResults = append(searchResults, TorznabSearchResult{
|
||||
Name: r.Name,
|
||||
Size: r.Size,
|
||||
Seeders: r.Seeders,
|
||||
Peers: r.Peers,
|
||||
Link: r.Magnet,
|
||||
})
|
||||
}
|
||||
|
||||
return searchResults, nil
|
||||
|
||||
}
|
||||
|
||||
type downloadTorrentIn struct {
|
||||
MediaID int `json:"media_id" binding:"required"`
|
||||
Link string `json:"link" binding:"required"`
|
||||
}
|
||||
func (s *Server) DownloadMovieTorrent(c *gin.Context) (interface{}, error) {
|
||||
var in downloadTorrentIn
|
||||
if err := c.ShouldBindJSON(&in); err != nil {
|
||||
return nil, errors.Wrap(err, "bind json")
|
||||
}
|
||||
log.Infof("download torrent input: %+v", in)
|
||||
|
||||
trc, err := s.getDownloadClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "connect transmission")
|
||||
}
|
||||
media := s.db.GetMediaDetails(in.MediaID)
|
||||
if media == nil {
|
||||
return nil, fmt.Errorf("no tv series of id %v", in.MediaID)
|
||||
}
|
||||
|
||||
torrent, err := trc.Download(in.Link, s.db.GetDownloadDir())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "downloading")
|
||||
}
|
||||
torrent.Start()
|
||||
|
||||
go func () {
|
||||
for {
|
||||
if !torrent.Exists() {
|
||||
continue
|
||||
}
|
||||
history, err := s.db.SaveHistoryRecord(ent.History{
|
||||
MediaID: media.ID,
|
||||
SourceTitle: torrent.Name(),
|
||||
TargetDir: "./",
|
||||
Status: history.StatusRunning,
|
||||
Size: torrent.Size(),
|
||||
Saved: torrent.Save(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("save history error: %v", err)
|
||||
}
|
||||
|
||||
s.tasks[history.ID] = &Task{Torrent: torrent}
|
||||
|
||||
break
|
||||
}
|
||||
}()
|
||||
|
||||
log.Infof("success add %s to download task", media.NameEn)
|
||||
return media.NameEn, nil
|
||||
|
||||
}
|
||||
|
||||
type downloadClientIn struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
@@ -215,4 +323,4 @@ func (s *Server) DeleteDownloadCLient(c *gin.Context) (interface{}, error) {
|
||||
}
|
||||
s.db.DeleteDownloadCLient(id)
|
||||
return "success", nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"polaris/ent"
|
||||
"polaris/ent/episode"
|
||||
"polaris/ent/history"
|
||||
"polaris/ent/media"
|
||||
storage1 "polaris/ent/storage"
|
||||
"polaris/log"
|
||||
"polaris/pkg"
|
||||
@@ -70,7 +71,7 @@ func (s *Server) moveCompletedTask(id int) (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
series := s.db.GetSeriesDetails(r.SeriesID)
|
||||
series := s.db.GetMediaDetails(r.MediaID)
|
||||
if series == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -107,7 +108,7 @@ func (s *Server) updateSeriesEpisodes(seriesId int) {
|
||||
}
|
||||
|
||||
func (s *Server) checkAllFiles() {
|
||||
var tvs = s.db.GetWatchlist()
|
||||
var tvs = s.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
for _, se := range tvs {
|
||||
if err := s.checkFileExists(se); err != nil {
|
||||
log.Errorf("check files for %s error: %v", se.NameCn, err)
|
||||
@@ -115,7 +116,7 @@ func (s *Server) checkAllFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) checkFileExists(series *ent.Series) error {
|
||||
func (s *Server) checkFileExists(series *ent.Media) error {
|
||||
log.Infof("check files in directory: %s", series.TargetDir)
|
||||
st := s.db.GetStorage(series.StorageID)
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"polaris/db"
|
||||
"polaris/log"
|
||||
"polaris/pkg/tmdb"
|
||||
@@ -26,11 +29,11 @@ func NewServer(db *db.Client) *Server {
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
r *gin.Engine
|
||||
db *db.Client
|
||||
cron *cron.Cron
|
||||
language string
|
||||
tasks map[int]*Task
|
||||
r *gin.Engine
|
||||
db *db.Client
|
||||
cron *cron.Cron
|
||||
language string
|
||||
tasks map[int]*Task
|
||||
jwtSerect string
|
||||
}
|
||||
|
||||
@@ -46,6 +49,7 @@ func (s *Server) Serve() error {
|
||||
api := s.r.Group("/api/v1")
|
||||
api.Use(s.authModdleware)
|
||||
api.StaticFS("/img", http.Dir(db.ImgPath))
|
||||
api.Any("/posters/*proxyPath", s.proxyPosters)
|
||||
|
||||
setting := api.Group("/setting")
|
||||
{
|
||||
@@ -60,20 +64,24 @@ func (s *Server) Serve() error {
|
||||
activity.DELETE("/:id", HttpHandler(s.RemoveActivity))
|
||||
}
|
||||
|
||||
tv := api.Group("/tv")
|
||||
tv := api.Group("/media")
|
||||
{
|
||||
tv.GET("/search", HttpHandler(s.SearchTvSeries))
|
||||
tv.POST("/watchlist", HttpHandler(s.AddWatchlist))
|
||||
tv.GET("/watchlist", HttpHandler(s.GetWatchlist))
|
||||
tv.GET("/series/:id", HttpHandler(s.GetTvDetails))
|
||||
tv.DELETE("/series/:id", HttpHandler(s.DeleteFromWatchlist))
|
||||
tv.GET("/search", HttpHandler(s.SearchMedia))
|
||||
tv.POST("/tv/watchlist", HttpHandler(s.AddTv2Watchlist))
|
||||
tv.GET("/tv/watchlist", HttpHandler(s.GetTvWatchlist))
|
||||
tv.POST("/movie/watchlist", HttpHandler(s.AddMovie2Watchlist))
|
||||
tv.GET("/movie/watchlist", HttpHandler(s.GetMovieWatchlist))
|
||||
tv.GET("/movie/resources/:id", HttpHandler(s.SearchAvailableMovies))
|
||||
tv.POST("/movie/resources/", HttpHandler(s.DownloadMovieTorrent))
|
||||
tv.GET("/record/:id", HttpHandler(s.GetMediaDetails))
|
||||
tv.DELETE("/record/:id", HttpHandler(s.DeleteFromWatchlist))
|
||||
tv.GET("/resolutions", HttpHandler(s.GetAvailableResolutions))
|
||||
}
|
||||
indexer := api.Group("/indexer")
|
||||
{
|
||||
indexer.GET("/", HttpHandler(s.GetAllIndexers))
|
||||
indexer.POST("/add", HttpHandler(s.AddTorznabInfo))
|
||||
indexer.POST("/download", HttpHandler(s.SearchAndDownload))
|
||||
indexer.POST("/download", HttpHandler(s.SearchTvAndDownload))
|
||||
indexer.DELETE("/del/:id", HttpHandler(s.DeleteTorznabInfo))
|
||||
}
|
||||
|
||||
@@ -125,3 +133,17 @@ func (s *Server) reloadTasks() {
|
||||
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)
|
||||
|
||||
proxy.Director = func(req *http.Request) {
|
||||
req.Header = c.Request.Header
|
||||
req.Host = remote.Host
|
||||
req.URL.Scheme = remote.Scheme
|
||||
req.URL.Host = remote.Host
|
||||
req.URL.Path = fmt.Sprintf("/t/p/w500/%v", c.Param("proxyPath"))
|
||||
}
|
||||
proxy.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"polaris/db"
|
||||
"polaris/ent"
|
||||
"polaris/ent/media"
|
||||
"polaris/log"
|
||||
"strconv"
|
||||
|
||||
@@ -33,13 +34,27 @@ func (s *Server) SearchTvSeries(c *gin.Context) (interface{}, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type addWatchlistIn struct {
|
||||
TmdbID int `json:"tmdb_id" binding:"required"`
|
||||
StorageID int `json:"storage_id" `
|
||||
Resolution db.ResolutionType `json:"resolution" binding:"required"`
|
||||
func(s *Server) SearchMedia(c *gin.Context) (interface{}, error) {
|
||||
var q searchTvParam
|
||||
if err := c.ShouldBindQuery(&q); err != nil {
|
||||
return nil, errors.Wrap(err, "bind query")
|
||||
}
|
||||
log.Infof("search media with keyword: %v", q.Query)
|
||||
r, err := s.MustTMDB().SearchMedia(q.Query, s.language, 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "search tv")
|
||||
}
|
||||
return r, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
|
||||
type addWatchlistIn struct {
|
||||
TmdbID int `json:"tmdb_id" binding:"required"`
|
||||
StorageID int `json:"storage_id" `
|
||||
Resolution string `json:"resolution" binding:"required"`
|
||||
}
|
||||
|
||||
func (s *Server) AddTv2Watchlist(c *gin.Context) (interface{}, error) {
|
||||
var in addWatchlistIn
|
||||
if err := c.ShouldBindJSON(&in); err != nil {
|
||||
return nil, errors.Wrap(err, "bind query")
|
||||
@@ -53,7 +68,7 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
|
||||
detailEn, _ := s.MustTMDB().GetTvDetails(in.TmdbID, db.LanguageEN)
|
||||
var nameEn = detailEn.Name
|
||||
var detail *tmdb.TVDetails
|
||||
if s.language == "" || s.language ==db.LanguageCN {
|
||||
if s.language == "" || s.language == db.LanguageCN {
|
||||
detail = detailCn
|
||||
} else {
|
||||
detail = detailEn
|
||||
@@ -83,21 +98,80 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) {
|
||||
epIds = append(epIds, epid)
|
||||
}
|
||||
}
|
||||
r, err := s.db.AddWatchlist(in.StorageID, nameCn, nameEn, detail, epIds, db.R1080p)
|
||||
r, err := s.db.AddMediaWatchlist(&ent.Media{
|
||||
TmdbID: int(detail.ID),
|
||||
MediaType: media.MediaTypeTv,
|
||||
NameCn: nameCn,
|
||||
NameEn: nameEn,
|
||||
OriginalName: detail.OriginalName,
|
||||
Overview: detail.Overview,
|
||||
AirDate: detail.FirstAirDate,
|
||||
Resolution: string(in.Resolution),
|
||||
StorageID: in.StorageID,
|
||||
|
||||
}, epIds)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "add to list")
|
||||
}
|
||||
go func () {
|
||||
go func() {
|
||||
if err := s.downloadPoster(detail.PosterPath, r.ID); err != nil {
|
||||
log.Errorf("download poster error: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
log.Infof("add tv %s to watchlist success", detail.Name)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *Server) downloadPoster(path string, seriesId int) error{
|
||||
func (s *Server) AddMovie2Watchlist(c *gin.Context) (interface{}, error) {
|
||||
var in addWatchlistIn
|
||||
if err := c.ShouldBindJSON(&in); err != nil {
|
||||
return nil, errors.Wrap(err, "bind query")
|
||||
}
|
||||
detailCn, err := s.MustTMDB().GetMovieDetails(in.TmdbID, db.LanguageCN)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get movie detail")
|
||||
}
|
||||
var nameCn = detailCn.Title
|
||||
|
||||
detailEn, _ := s.MustTMDB().GetMovieDetails(in.TmdbID, db.LanguageEN)
|
||||
var nameEn = detailEn.Title
|
||||
var detail *tmdb.MovieDetails
|
||||
if s.language == "" || s.language == db.LanguageCN {
|
||||
detail = detailCn
|
||||
} else {
|
||||
detail = detailEn
|
||||
}
|
||||
log.Infof("find detail for movie id %d: %v", in.TmdbID, detail)
|
||||
|
||||
|
||||
r, err := s.db.AddMediaWatchlist(&ent.Media{
|
||||
TmdbID: int(detail.ID),
|
||||
MediaType: media.MediaTypeMovie,
|
||||
NameCn: nameCn,
|
||||
NameEn: nameEn,
|
||||
OriginalName: detail.OriginalTitle,
|
||||
Overview: detail.Overview,
|
||||
AirDate: detail.ReleaseDate,
|
||||
Resolution: string(in.Resolution),
|
||||
StorageID: in.StorageID,
|
||||
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "add to list")
|
||||
}
|
||||
go func() {
|
||||
if err := s.downloadPoster(detail.PosterPath, r.ID); err != nil {
|
||||
log.Errorf("download poster error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Infof("add movie %s to watchlist success", detail.Title)
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) downloadPoster(path string, mediaID int) error {
|
||||
var tmdbImgBaseUrl = "https://image.tmdb.org/t/p/w500/"
|
||||
url := tmdbImgBaseUrl + path
|
||||
log.Infof("try to download poster: %v", url)
|
||||
@@ -105,10 +179,10 @@ func (s *Server) downloadPoster(path string, seriesId int) error{
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "http get")
|
||||
}
|
||||
targetDir := fmt.Sprintf("%v/%d", db.ImgPath, seriesId)
|
||||
targetDir := fmt.Sprintf("%v/%d", db.ImgPath, mediaID)
|
||||
os.MkdirAll(targetDir, 0777)
|
||||
ext := filepath.Ext(path)
|
||||
targetFile := filepath.Join(targetDir, "poster"+ ext)
|
||||
targetFile := filepath.Join(targetDir, "poster"+ext)
|
||||
f, err := os.Create(targetFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "new file")
|
||||
@@ -122,18 +196,24 @@ func (s *Server) downloadPoster(path string, seriesId int) error{
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) GetWatchlist(c *gin.Context) (interface{}, error) {
|
||||
list := s.db.GetWatchlist()
|
||||
func (s *Server) GetTvWatchlist(c *gin.Context) (interface{}, error) {
|
||||
list := s.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetTvDetails(c *gin.Context) (interface{}, error) {
|
||||
func (s *Server) GetMovieWatchlist(c *gin.Context) (interface{}, error) {
|
||||
list := s.db.GetMediaWatchlist(media.MediaTypeMovie)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
|
||||
func (s *Server) GetMediaDetails(c *gin.Context) (interface{}, error) {
|
||||
ids := c.Param("id")
|
||||
id, err := strconv.Atoi(ids)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert")
|
||||
}
|
||||
detail := s.db.GetSeriesDetails(id)
|
||||
detail := s.db.GetMediaDetails(id)
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
@@ -151,9 +231,9 @@ func (s *Server) DeleteFromWatchlist(c *gin.Context) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert")
|
||||
}
|
||||
if err := s.db.DeleteSeries(id); err != nil {
|
||||
if err := s.db.DeleteMedia(id); err != nil {
|
||||
return nil, errors.Wrap(err, "delete db")
|
||||
}
|
||||
os.RemoveAll(filepath.Join(db.ImgPath, ids)) //delete image related
|
||||
return "success", nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user