From 6ef4bedebeae55cc952570e2d61ca63b56093db4 Mon Sep 17 00:00:00 2001 From: Simon Ding Date: Tue, 30 Jul 2024 15:51:54 +0800 Subject: [PATCH] feat: support generate .plexmatch --- db/const.go | 1 + pkg/storage/local.go | 11 +++++++++ pkg/storage/webdav.go | 10 ++++++++ server/integration.go | 42 ++++++++++++++++++++++++++++++++++ server/scheduler.go | 28 ++++++----------------- server/setting.go | 26 ++++++++++++++------- server/storage.go | 34 +++++++++++++++++++++++++++ ui/lib/providers/settings.dart | 11 +++++++-- ui/lib/settings/general.dart | 11 ++++++++- 9 files changed, 142 insertions(+), 32 deletions(-) create mode 100644 server/integration.go diff --git a/db/const.go b/db/const.go index f10af8a..deb14f1 100644 --- a/db/const.go +++ b/db/const.go @@ -10,6 +10,7 @@ const ( SettingDownloadDir = "download_dir" SettingLogLevel = "log_level" SettingProxy = "proxy" + SettingPlexMatchEnabled = "plexmatch_enabled" ) const ( diff --git a/pkg/storage/local.go b/pkg/storage/local.go index 4118b11..340a3e6 100644 --- a/pkg/storage/local.go +++ b/pkg/storage/local.go @@ -14,6 +14,8 @@ import ( type Storage interface { Move(src, dest string) error ReadDir(dir string) ([]fs.FileInfo, error) + ReadFile(string)([]byte, error) + WriteFile(string, []byte) error } func NewLocalStorage(dir string) (*LocalStorage, error) { @@ -81,3 +83,12 @@ func (l *LocalStorage) Move(src, destDir string) error { func (l *LocalStorage) ReadDir(dir string) ([]fs.FileInfo, error) { return ioutil.ReadDir(filepath.Join(l.dir, dir)) } + +func (l *LocalStorage) ReadFile(name string) ([]byte, error) { + return os.ReadFile(name) +} + + +func (l *LocalStorage) WriteFile(name string, data []byte) error { + return os.WriteFile(name, data, os.ModePerm) +} \ No newline at end of file diff --git a/pkg/storage/webdav.go b/pkg/storage/webdav.go index 6abb790..63fb4c8 100644 --- a/pkg/storage/webdav.go +++ b/pkg/storage/webdav.go @@ -98,3 +98,13 @@ func (w *WebdavStorage) Move(local, remoteDir string) error { func (w *WebdavStorage) ReadDir(dir string) ([]fs.FileInfo, error) { return w.fs.ReadDir(filepath.Join(w.dir, dir)) } + + +func (w *WebdavStorage) ReadFile(name string) ([]byte, error) { + return w.fs.Read(filepath.Join(w.dir, name)) +} + + +func (w *WebdavStorage) WriteFile(name string, data []byte) error { + return w.fs.Write(filepath.Join(w.dir, name), data, os.ModePerm) +} \ No newline at end of file diff --git a/server/integration.go b/server/integration.go new file mode 100644 index 0000000..de66bbd --- /dev/null +++ b/server/integration.go @@ -0,0 +1,42 @@ +package server + +import ( + "fmt" + "path/filepath" + "polaris/db" + "polaris/ent/media" + "polaris/log" + + "github.com/pkg/errors" +) + +func (s *Server) createPlexmatchIfNotExists(seriesId int) 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") + } + + _, 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) + st.WriteFile(filepath.Join(series.TargetDir, ".plexmatch"), []byte(fmt.Sprintf("tmdbid=%d\n",series.TmdbID))) + return nil + } + return nil +} + +func (s *Server) plexmatchEnabled() bool { + return s.db.GetSetting(db.SettingPlexMatchEnabled) == "true" +} diff --git a/server/scheduler.go b/server/scheduler.go index 77745d5..480f690 100644 --- a/server/scheduler.go +++ b/server/scheduler.go @@ -71,6 +71,9 @@ func (s *Server) moveCompletedTask(id int) (err1 error) { log.Errorf("no season id: %v", r.TargetDir) seasonNum = -1 } + if err := s.createPlexmatchIfNotExists(r.MediaID); err != nil { + log.Errorf("create .plexmatch file error: %v", err) + } if err1 != nil { s.db.SetHistoryStatus(r.ID, history.StatusFail) @@ -143,29 +146,12 @@ func (s *Server) checkDownloadedSeriesFiles(m *ent.Media) error { return nil } log.Infof("check files in directory: %s", m.TargetDir) - st := s.db.GetStorage(m.StorageID) - var storageImpl storage.Storage - - switch st.Implementation { - case storage1.ImplementationLocal: - ls := st.ToLocalSetting() - targetPath := ls.TvPath - storageImpl1, err := storage.NewLocalStorage(targetPath) - if err != nil { - return errors.Wrap(err, "new local") - } - storageImpl = storageImpl1 - - case storage1.ImplementationWebdav: - ws := st.ToWebDavSetting() - targetPath := ws.TvPath - storageImpl1, err := storage.NewWebdavStorage(ws.URL, ws.User, ws.Password, targetPath, ws.ChangeFileHash == "true") - if err != nil { - return errors.Wrap(err, "new webdav") - } - storageImpl = storageImpl1 + var storageImpl, err = s.getStorage(m.StorageID, media.MediaTypeTv) + if err != nil { + return err } + files, err := storageImpl.ReadDir(m.TargetDir) if err != nil { return errors.Wrapf(err, "read dir %s", m.TargetDir) diff --git a/server/setting.go b/server/setting.go index a832031..c34848d 100644 --- a/server/setting.go +++ b/server/setting.go @@ -14,10 +14,11 @@ import ( ) type GeneralSettings struct { - TmdbApiKey string `json:"tmdb_api_key"` - DownloadDir string `json:"download_dir"` - LogLevel string `json:"log_level"` - Proxy string `json:"proxy"` + TmdbApiKey string `json:"tmdb_api_key"` + DownloadDir string `json:"download_dir"` + LogLevel string `json:"log_level"` + Proxy string `json:"proxy"` + EnablePlexmatch bool `json:"enable_plexmatch"` } func (s *Server) SetSetting(c *gin.Context) (interface{}, error) { @@ -45,6 +46,13 @@ func (s *Server) SetSetting(c *gin.Context) (interface{}, error) { } + plexmatchEnabled := s.db.GetSetting(db.SettingPlexMatchEnabled) + if in.EnablePlexmatch && plexmatchEnabled != "true" { + s.db.SetSetting(db.SettingPlexMatchEnabled, "true") + } else if !in.EnablePlexmatch && plexmatchEnabled != "false" { + s.db.SetSetting(db.SettingPlexMatchEnabled, "false") + } + s.setProxy(in.Proxy) return nil, nil } @@ -72,11 +80,13 @@ func (s *Server) GetSetting(c *gin.Context) (interface{}, error) { tmdb := s.db.GetSetting(db.SettingTmdbApiKey) downloadDir := s.db.GetSetting(db.SettingDownloadDir) logLevel := s.db.GetSetting(db.SettingLogLevel) + plexmatchEnabled := s.db.GetSetting(db.SettingPlexMatchEnabled) return &GeneralSettings{ - TmdbApiKey: tmdb, - DownloadDir: downloadDir, - LogLevel: logLevel, - Proxy: s.db.GetSetting(db.SettingProxy), + TmdbApiKey: tmdb, + DownloadDir: downloadDir, + LogLevel: logLevel, + Proxy: s.db.GetSetting(db.SettingProxy), + EnablePlexmatch: plexmatchEnabled == "true", }, nil } diff --git a/server/storage.go b/server/storage.go index de30a0c..7b50f21 100644 --- a/server/storage.go +++ b/server/storage.go @@ -3,6 +3,8 @@ package server import ( "fmt" "polaris/db" + "polaris/ent/media" + storage1 "polaris/ent/storage" "polaris/log" "polaris/pkg/storage" "polaris/pkg/utils" @@ -106,3 +108,35 @@ 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) + switch st.Implementation { + case storage1.ImplementationLocal: + ls := st.ToLocalSetting() + targetPath := ls.TvPath + if mediaType == media.MediaTypeMovie { + targetPath = ls.MoviePath + } + storageImpl1, err := storage.NewLocalStorage(targetPath) + if err != nil { + return nil, errors.Wrap(err, "new local") + } + return storageImpl1, nil + + case storage1.ImplementationWebdav: + ws := st.ToWebDavSetting() + targetPath := ws.TvPath + if mediaType == media.MediaTypeMovie { + targetPath = ws.MoviePath + } + + 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") +} diff --git a/ui/lib/providers/settings.dart b/ui/lib/providers/settings.dart index 1aebd82..df3cd85 100644 --- a/ui/lib/providers/settings.dart +++ b/ui/lib/providers/settings.dart @@ -51,16 +51,22 @@ class GeneralSetting { String? downloadDIr; String? logLevel; String? proxy; + bool? enablePlexmatch; GeneralSetting( - {this.tmdbApiKey, this.downloadDIr, this.logLevel, this.proxy}); + {this.tmdbApiKey, + this.downloadDIr, + this.logLevel, + this.proxy, + this.enablePlexmatch}); factory GeneralSetting.fromJson(Map json) { return GeneralSetting( tmdbApiKey: json["tmdb_api_key"], downloadDIr: json["download_dir"], logLevel: json["log_level"], - proxy: json["proxy"]); + proxy: json["proxy"], + enablePlexmatch: json["enable_plexmatch"] ?? false); } Map toJson() { @@ -69,6 +75,7 @@ class GeneralSetting { data['download_dir'] = downloadDIr; data["log_level"] = logLevel; data["proxy"] = proxy; + data["enable_plexmatch"] = enablePlexmatch; return data; } } diff --git a/ui/lib/settings/general.dart b/ui/lib/settings/general.dart index dd5bd30..f646546 100644 --- a/ui/lib/settings/general.dart +++ b/ui/lib/settings/general.dart @@ -34,6 +34,7 @@ class _GeneralState extends ConsumerState { "download_dir": v.downloadDIr, "log_level": v.logLevel, "proxy": v.proxy, + "enable_plexmatch": v.enablePlexmatch }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -78,6 +79,11 @@ class _GeneralState extends ConsumerState { validator: FormBuilderValidators.required(), ), ), + SizedBox( + width: 300, + child: FormBuilderSwitch( + name: "enable_plexmatch", title: const Text("Plex 刮削支持")), + ), Center( child: Padding( padding: const EdgeInsets.only(top: 28.0), @@ -95,7 +101,10 @@ class _GeneralState extends ConsumerState { tmdbApiKey: values["tmdb_api"], downloadDIr: values["download_dir"], logLevel: values["log_level"], - proxy: values["proxy"])).then((v) => showSnakeBar("更新成功")); + proxy: values["proxy"], + enablePlexmatch: + values["enable_plexmatch"])) + .then((v) => showSnakeBar("更新成功")); showLoadingWithFuture(f); } }),