mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-23 12:10:48 +08:00
Compare commits
13 Commits
dependabot
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72ec84e236 | ||
|
|
30e8d4f024 | ||
|
|
4341e31251 | ||
|
|
53dda90c0f | ||
|
|
12c3b0c69b | ||
|
|
4825cda458 | ||
|
|
6a12c380f1 | ||
|
|
d8944168d2 | ||
|
|
0a48657999 | ||
|
|
717b098d2f | ||
|
|
1f6b704405 | ||
|
|
e2ec07aaa2 | ||
|
|
3aa72cd6f8 |
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
run: |
|
||||
cd ui
|
||||
flutter pub get
|
||||
flutter build web --no-web-resources-cdn
|
||||
flutter build web --no-web-resources-cdn --wasm --release
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
run: |
|
||||
cd ui
|
||||
flutter pub get
|
||||
flutter build web --no-web-resources-cdn
|
||||
flutter build web --no-web-resources-cdn --wasm --release
|
||||
|
||||
- name: Build and push
|
||||
id: push
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
context: .
|
||||
file: ./docker/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/s390x,linux/ppc64le
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
|
||||
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))
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ type MediaWithStatus struct {
|
||||
DownloadedNum int `json:"downloaded_num"`
|
||||
}
|
||||
|
||||
|
||||
//missing: episode aired missing
|
||||
//downloaded: all monitored episode downloaded
|
||||
//monitoring: episode aired downloaded, but still has not aired episode
|
||||
@@ -111,7 +112,8 @@ func (s *Server) GetTvWatchlist(c *gin.Context) (interface{}, error) {
|
||||
} else {
|
||||
details, err := s.db.GetMediaDetails(item.ID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get details")
|
||||
log.Warnf("get media details: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, ep := range details.Episodes {
|
||||
if ep.Monitored {
|
||||
@@ -139,13 +141,21 @@ 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)
|
||||
dow, ok2 := s.downloadNumCache.Get(item.ID)
|
||||
if ok2 {
|
||||
ms.DownloadedNum = dow
|
||||
} else {
|
||||
if dummyEp.Status == episode.StatusDownloaded {
|
||||
dummyEp, err := s.db.GetMovieDummyEpisode(item.ID)
|
||||
if err != nil {
|
||||
log.Errorf("get dummy episode: %v", err)
|
||||
} else {
|
||||
ms.DownloadedNum++
|
||||
if dummyEp.Status == episode.StatusDownloaded {
|
||||
s.downloadNumCache.Set(item.ID, 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
res[i] = ms
|
||||
}
|
||||
|
||||
@@ -149,7 +149,13 @@ class _MyAppState extends ConsumerState<MyApp> {
|
||||
return MaterialApp.router(
|
||||
title: 'Polaris 影视追踪下载',
|
||||
theme: ThemeData(
|
||||
fontFamily: "NotoSansSC",
|
||||
//fontFamily: "NotoSansSC",
|
||||
fontFamilyFallback: [
|
||||
'PingFang SC',
|
||||
'Microsoft YaHei',
|
||||
'Noto Sans SC',
|
||||
'NotoSansSC', // buildin font
|
||||
],
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.blueAccent,
|
||||
brightness: Brightness.dark,
|
||||
|
||||
@@ -57,6 +57,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
country_pickers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: country_pickers
|
||||
sha256: b10f6618fa64fbba02ffc4ad1b84dc0ca071cc206e5376de1698bddd980b355a
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -81,14 +89,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.7"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -143,10 +143,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_login
|
||||
sha256: "73ab879fa40cc04778cf4b6342b43586818c7e7a90df23c59a4a1d4a1dd36091"
|
||||
sha256: "13351d09de94741e0920235132318445ff2122a6fa693eeb9f590f49aa5b80f9"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "6.0.0"
|
||||
flutter_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -173,6 +173,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "10.10.0"
|
||||
form_builder_phone_field:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: form_builder_phone_field
|
||||
sha256: "1d02d6cf0dbd7313860f48903ff00f4e519aad989dbf44dde767771d4585a4dd"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
form_builder_validators:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -205,22 +213,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
intl_phone_number_input:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl_phone_number_input
|
||||
sha256: "1c4328713a9503ab26a1fdbb6b00b4cada68c18aac922b35bedbc72eff1297c3"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -245,30 +237,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
libphonenumber_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: libphonenumber_platform_interface
|
||||
sha256: f801f6c65523f56504b83f0890e6dad584ab3a7507dca65fec0eed640afea40f
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
libphonenumber_plugin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: libphonenumber_plugin
|
||||
sha256: c615021d9816fbda2b2587881019ed595ecdf54d999652d7e4cce0e1f026368c
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.3"
|
||||
libphonenumber_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: libphonenumber_web
|
||||
sha256: "8186f420dbe97c3132283e52819daff1e55d60d6db46f7ea5ac42f42a28cc2ef"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.2"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -305,10 +273,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
version: "1.17.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -454,10 +422,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
version: "0.7.7"
|
||||
timeago:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@@ -40,7 +40,7 @@ dependencies:
|
||||
go_router: ^16.2.1
|
||||
flutter_riverpod: ^2.6.1
|
||||
quiver: ^3.2.2
|
||||
flutter_login: ^5.0.0
|
||||
flutter_login: ^6.0.0
|
||||
intl: ^0.20.2
|
||||
flutter_adaptive_scaffold: ^0.3.1
|
||||
flutter_form_builder: ^10.0.1
|
||||
|
||||
Reference in New Issue
Block a user