mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-25 13:10:46 +08:00
Compare commits
9 Commits
dependabot
...
v0.24.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12c3b0c69b | ||
|
|
4825cda458 | ||
|
|
6a12c380f1 | ||
|
|
d8944168d2 | ||
|
|
0a48657999 | ||
|
|
717b098d2f | ||
|
|
1f6b704405 | ||
|
|
e2ec07aaa2 | ||
|
|
3aa72cd6f8 |
10
db/db.go
10
db/db.go
@@ -31,7 +31,6 @@ import (
|
||||
"modernc.org/sqlite"
|
||||
)
|
||||
|
||||
|
||||
// https://github.com/ent/ent/discussions/1667#discussioncomment-1132296
|
||||
type sqliteDriver struct {
|
||||
*sqlite.Driver
|
||||
@@ -232,6 +231,15 @@ func (c *client) GetMediaWatchlist(mediaType media.MediaType) []*ent.Media {
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *client) GetAllEpisodes() (ent.Episodes, error) {
|
||||
ep, err := c.ent.Episode.Query().All(context.TODO())
|
||||
return ep, err
|
||||
}
|
||||
|
||||
func (c *client) DeleteEpisode(ids ...int) error {
|
||||
_, err := c.ent.Episode.Delete().Where(episode.IDIn(ids...)).Exec(context.TODO())
|
||||
return err
|
||||
}
|
||||
func (c *client) GetEpisode(seriesId, seasonNum, episodeNum int) (*ent.Episode, error) {
|
||||
return c.ent.Episode.Query().Where(episode.MediaID(seriesId), episode.SeasonNumber(seasonNum),
|
||||
episode.EpisodeNumber(episodeNum)).First(context.TODO())
|
||||
|
||||
@@ -59,7 +59,6 @@ type Settings interface {
|
||||
GetAcceptedSubtitleFormats() ([]string, error)
|
||||
SetAcceptedSubtitleFormats(key string, v []string) error
|
||||
GetTmdbApiKey() string
|
||||
|
||||
}
|
||||
|
||||
type MediaApis interface {
|
||||
@@ -75,6 +74,8 @@ type MediaApis interface {
|
||||
}
|
||||
|
||||
type EpisodeApis interface {
|
||||
GetAllEpisodes() (ent.Episodes, error)
|
||||
DeleteEpisode(ids ...int) error
|
||||
GetEpisode(seriesId, seasonNum, episodeNum int) (*ent.Episode, error)
|
||||
GetEpisodeByID(epID int) (*ent.Episode, error)
|
||||
UpdateEpiode(episodeId int, name, overview string) error
|
||||
@@ -89,7 +90,6 @@ type EpisodeApis interface {
|
||||
UpdateEpisodeTargetFile(id int, filename string) error
|
||||
GetSeasonEpisodes(mediaId, seasonNum int) ([]*ent.Episode, error)
|
||||
CleanAllDanglingEpisodes() error
|
||||
|
||||
}
|
||||
|
||||
type IndexerApis interface {
|
||||
@@ -97,7 +97,6 @@ type IndexerApis interface {
|
||||
DeleteIndexer(id int)
|
||||
GetIndexer(id int) (*ent.Indexers, error)
|
||||
GetAllIndexers() []*ent.Indexers
|
||||
|
||||
}
|
||||
|
||||
type HistoryApis interface {
|
||||
@@ -108,5 +107,5 @@ type HistoryApis interface {
|
||||
GetHistories() ent.Histories
|
||||
DeleteHistory(id int) error
|
||||
GetDownloadHistory(mediaID int) ([]*ent.History, error)
|
||||
GetMovieDummyEpisode(movieId int) (*ent.Episode, error)
|
||||
}
|
||||
GetMovieDummyEpisode(movieId int) (*ent.Episode, error)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,65 @@
|
||||
package engine
|
||||
|
||||
import "polaris/log"
|
||||
import (
|
||||
"polaris/ent/media"
|
||||
"polaris/log"
|
||||
)
|
||||
|
||||
func (c *Engine) housekeeping() error {
|
||||
func (c *Engine) housekeeping() (err error) {
|
||||
log.Infof("start housekeeping tasks...")
|
||||
|
||||
defer func() {
|
||||
log.Infof("housekeeping tasks completed. err: %v", err)
|
||||
}()
|
||||
|
||||
if err := c.checkDbScraps(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.checkImageFilesInterity(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Engine) checkDbScraps() error {
|
||||
//TODO: remove episodes that are not associated with any series
|
||||
|
||||
tvs := c.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
movies := c.db.GetMediaWatchlist(media.MediaTypeMovie)
|
||||
|
||||
validMediaIDs := make(map[int]bool, len(tvs)+len(movies))
|
||||
for _, tv := range tvs {
|
||||
validMediaIDs[tv.ID] = true
|
||||
}
|
||||
for _, movie := range movies {
|
||||
validMediaIDs[movie.ID] = true
|
||||
}
|
||||
|
||||
allEpisodes, err := c.db.GetAllEpisodes()
|
||||
if err != nil {
|
||||
log.Debugf("get all episodes error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("check db scraps, total episodes: %v, total media: %v", len(allEpisodes), len(validMediaIDs))
|
||||
toDeleteIds := make([]int, 0)
|
||||
for _, ep := range allEpisodes {
|
||||
if _, ok := validMediaIDs[ep.MediaID]; !ok {
|
||||
//log.Infof("remove scrap episode record: %v S%vE%v", ep.MediaID, ep.SeasonNumber, ep.EpisodeNumber)
|
||||
toDeleteIds = append(toDeleteIds, ep.ID)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("%v scrap episode records will be removed...", len(toDeleteIds))
|
||||
|
||||
if err := c.db.DeleteEpisode(toDeleteIds...); err != nil {
|
||||
log.Errorf("delete scrap episode records error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Engine) checkImageFilesInterity() error {
|
||||
//TODO: download missing image files, remove unused image files
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ func (c *Engine) addSysCron() {
|
||||
})
|
||||
c.registerCronJob("check_series_new_release", "0 0 */12 * * *", c.checkAllSeriesNewSeason)
|
||||
c.registerCronJob("update_import_lists", "0 */20 * * * *", c.periodicallyUpdateImportlist)
|
||||
c.registerCronJob("housekeeping", "0 0 * * * *", c.housekeeping)
|
||||
c.registerCronJob("housekeeping", "0 0 2 * * *", c.housekeeping)
|
||||
go c.housekeeping() //run once on startup
|
||||
|
||||
c.schedulers.Range(func(key string, value scheduler) bool {
|
||||
log.Debugf("add cron job: %v", key)
|
||||
|
||||
@@ -26,10 +26,10 @@ import (
|
||||
func NewServer(db db.Database) *Server {
|
||||
s := &Server{
|
||||
db: db,
|
||||
srv: &http.Server{},
|
||||
srv: &http.Server{},
|
||||
language: db.GetLanguage(),
|
||||
monitorNumCache: cache.NewCache[int, int](10 * time.Minute),
|
||||
downloadNumCache: cache.NewCache[int, int](10 * time.Minute),
|
||||
monitorNumCache: cache.NewCache[int, int](30 * time.Minute),
|
||||
downloadNumCache: cache.NewCache[int, int](30 * time.Minute),
|
||||
}
|
||||
s.core = engine.NewEngine(db, s.language)
|
||||
s.setupRoutes()
|
||||
@@ -58,7 +58,7 @@ func (s *Server) setupRoutes() {
|
||||
} else {
|
||||
log.Warnf("serve web static files error: %v", err)
|
||||
}
|
||||
|
||||
|
||||
//s.r.Use(ginzap.Ginzap(log.Logger().Desugar(), time.RFC3339, false))
|
||||
r.Use(ginzap.RecoveryWithZap(log.Logger().Desugar(), true))
|
||||
|
||||
@@ -179,6 +179,14 @@ func (s *Server) Start(addr string) (int, error) {
|
||||
|
||||
log.Infof("----------- Polaris Server Successfully Started on Port %d------------", p)
|
||||
|
||||
ticker := time.NewTicker(10 * time.Minute)
|
||||
go func() {
|
||||
for {
|
||||
s.cacheDownloadedStatus()
|
||||
<-ticker.C
|
||||
}
|
||||
}()
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,60 @@ type MediaWithStatus struct {
|
||||
DownloadedNum int `json:"downloaded_num"`
|
||||
}
|
||||
|
||||
func (s *Server) cacheDownloadedStatus() {
|
||||
log.Info("cache watchlist downloaded/monitored status")
|
||||
list := s.db.GetMediaWatchlist(media.MediaTypeTv)
|
||||
for _, item := range list {
|
||||
var ms = MediaWithStatus{
|
||||
Media: item,
|
||||
MonitoredNum: 0,
|
||||
DownloadedNum: 0,
|
||||
}
|
||||
mon, ok1 := s.monitorNumCache.Get(item.ID)
|
||||
dow, ok2 := s.downloadNumCache.Get(item.ID)
|
||||
if ok1 && ok2 {
|
||||
ms.MonitoredNum = mon
|
||||
ms.DownloadedNum = dow
|
||||
} else {
|
||||
details, err := s.db.GetMediaDetails(item.ID)
|
||||
if err != nil {
|
||||
log.Warnf("get media details: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, ep := range details.Episodes {
|
||||
if ep.Monitored {
|
||||
ms.MonitoredNum++
|
||||
if ep.Status == episode.StatusDownloaded {
|
||||
ms.DownloadedNum++
|
||||
}
|
||||
}
|
||||
}
|
||||
s.monitorNumCache.Set(item.ID, ms.MonitoredNum)
|
||||
s.downloadNumCache.Set(item.ID, ms.DownloadedNum)
|
||||
}
|
||||
}
|
||||
|
||||
list = s.db.GetMediaWatchlist(media.MediaTypeMovie)
|
||||
for _, item := range list {
|
||||
_, ok2 := s.downloadNumCache.Get(item.ID)
|
||||
if ok2 {
|
||||
continue
|
||||
}
|
||||
|
||||
dummyEp, err := s.db.GetMovieDummyEpisode(item.ID)
|
||||
if err != nil {
|
||||
log.Errorf("get dummy episode: %v", err)
|
||||
} else {
|
||||
|
||||
if dummyEp.Status == episode.StatusDownloaded {
|
||||
s.downloadNumCache.Set(item.ID, 1)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//missing: episode aired missing
|
||||
//downloaded: all monitored episode downloaded
|
||||
//monitoring: episode aired downloaded, but still has not aired episode
|
||||
@@ -109,20 +163,7 @@ func (s *Server) GetTvWatchlist(c *gin.Context) (interface{}, error) {
|
||||
ms.MonitoredNum = mon
|
||||
ms.DownloadedNum = dow
|
||||
} else {
|
||||
details, err := s.db.GetMediaDetails(item.ID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get details")
|
||||
}
|
||||
for _, ep := range details.Episodes {
|
||||
if ep.Monitored {
|
||||
ms.MonitoredNum++
|
||||
if ep.Status == episode.StatusDownloaded {
|
||||
ms.DownloadedNum++
|
||||
}
|
||||
}
|
||||
}
|
||||
s.monitorNumCache.Set(item.ID, ms.MonitoredNum)
|
||||
s.downloadNumCache.Set(item.ID, ms.DownloadedNum)
|
||||
continue
|
||||
}
|
||||
|
||||
res[i] = ms
|
||||
@@ -139,14 +180,10 @@ func (s *Server) GetMovieWatchlist(c *gin.Context) (interface{}, error) {
|
||||
MonitoredNum: 1,
|
||||
DownloadedNum: 0,
|
||||
}
|
||||
dummyEp, err := s.db.GetMovieDummyEpisode(item.ID)
|
||||
if err != nil {
|
||||
log.Errorf("get dummy episode: %v", err)
|
||||
} else {
|
||||
if dummyEp.Status == episode.StatusDownloaded {
|
||||
ms.DownloadedNum++
|
||||
}
|
||||
}
|
||||
dow, ok2 := s.downloadNumCache.Get(item.ID)
|
||||
if ok2 {
|
||||
ms.DownloadedNum = dow
|
||||
}
|
||||
res[i] = ms
|
||||
}
|
||||
return res, nil
|
||||
|
||||
Reference in New Issue
Block a user