From c674e32046b7ea59eb115617e6bfb4ca0df9796e Mon Sep 17 00:00:00 2001 From: thsrite Date: Mon, 8 Jan 2024 13:05:09 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix=20=E9=A6=96=E9=A1=B5=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E8=A7=82=E7=9C=8B=E3=80=81=E6=9C=80=E8=BF=91=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=8E=92=E9=99=A4=E9=BB=91=E5=90=8D=E5=8D=95=E5=AA=92=E4=BD=93?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/chain/mediaserver.py | 24 ++++++++++++++++++++++-- app/modules/emby/emby.py | 1 + app/modules/jellyfin/jellyfin.py | 1 + app/modules/plex/plex.py | 1 + app/schemas/mediaserver.py | 1 + 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/chain/mediaserver.py b/app/chain/mediaserver.py index 68df03b9..64d1d621 100644 --- a/app/chain/mediaserver.py +++ b/app/chain/mediaserver.py @@ -48,13 +48,33 @@ class MediaServerChain(ChainBase): """ 获取媒体服务器正在播放信息 """ - return self.run_module("mediaserver_playing", count=count, server=server, username=username) + playing_items = self.run_module("mediaserver_playing", count=100, server=server, username=username) + # 判断是否在同步的媒体数据中 + exists_items = [] + for item in playing_items: + if self.dboper.exists(mtype=item.type, + title=item.title, + year=item.year): + exists_items.append(item) + if len(exists_items) == count: + break + return exists_items def latest(self, count: int = 20, server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器最新入库条目 """ - return self.run_module("mediaserver_latest", count=count, server=server, username=username) + latest_items = self.run_module("mediaserver_latest", count=100, server=server, username=username) + # 判断是否在同步的媒体数据中 + exists_items = [] + for item in latest_items: + if self.dboper.exists(mtype=item.type, + title=item.title, + year=item.subtitle): + exists_items.append(item) + if len(exists_items) == count: + break + return exists_items def get_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ diff --git a/app/modules/emby/emby.py b/app/modules/emby/emby.py index 1c603fbf..9306ae68 100644 --- a/app/modules/emby/emby.py +++ b/app/modules/emby/emby.py @@ -1002,6 +1002,7 @@ class Emby(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.get("Id"), title=title, + year=item.get("ProductionYear"), subtitle=subtitle, type=item_type, image=image, diff --git a/app/modules/jellyfin/jellyfin.py b/app/modules/jellyfin/jellyfin.py index 81d55e41..4b298a85 100644 --- a/app/modules/jellyfin/jellyfin.py +++ b/app/modules/jellyfin/jellyfin.py @@ -679,6 +679,7 @@ class Jellyfin(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.get("Id"), title=title, + year=item.get("ProductionYear"), subtitle=subtitle, type=item_type, image=image, diff --git a/app/modules/plex/plex.py b/app/modules/plex/plex.py index 7c52a975..bf89352b 100644 --- a/app/modules/plex/plex.py +++ b/app/modules/plex/plex.py @@ -626,6 +626,7 @@ class Plex(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.key, title=title, + year=item.year, subtitle=subtitle, type=item_type, image=image, diff --git a/app/schemas/mediaserver.py b/app/schemas/mediaserver.py index 582ad2d7..373efa58 100644 --- a/app/schemas/mediaserver.py +++ b/app/schemas/mediaserver.py @@ -151,6 +151,7 @@ class MediaServerPlayItem(BaseModel): """ id: Optional[Union[str, int]] = None title: Optional[str] = None + year: Optional[str] = None subtitle: Optional[str] = None type: Optional[str] = None image: Optional[str] = None From 4dcefb141a6d1958e36156155d0b1f8a89aafcc5 Mon Sep 17 00:00:00 2001 From: thsrite Date: Mon, 8 Jan 2024 13:05:48 +0800 Subject: [PATCH 2/5] fix #907 --- app/api/endpoints/dashboard.py | 13 +------------ app/chain/dashboard.py | 35 ++++++++++++++++++++++++++++++++-- app/db/mediaserver_oper.py | 6 ++++++ app/db/models/mediaserver.py | 8 ++++++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/app/api/endpoints/dashboard.py b/app/api/endpoints/dashboard.py index ce437d37..35f81317 100644 --- a/app/api/endpoints/dashboard.py +++ b/app/api/endpoints/dashboard.py @@ -20,18 +20,7 @@ def statistic(_: schemas.TokenPayload = Depends(verify_token)) -> Any: """ 查询媒体数量统计信息 """ - media_statistics: Optional[List[schemas.Statistic]] = DashboardChain().media_statistic() - if media_statistics: - # 汇总各媒体库统计信息 - ret_statistic = schemas.Statistic() - for media_statistic in media_statistics: - ret_statistic.movie_count += media_statistic.movie_count - ret_statistic.tv_count += media_statistic.tv_count - ret_statistic.episode_count += media_statistic.episode_count - ret_statistic.user_count += media_statistic.user_count - return ret_statistic - else: - return schemas.Statistic() + return DashboardChain().media_statistic() @router.get("/statistic2", summary="媒体数量统计(API_TOKEN)", response_model=schemas.Statistic) diff --git a/app/chain/dashboard.py b/app/chain/dashboard.py index 35258a90..0aff73f6 100644 --- a/app/chain/dashboard.py +++ b/app/chain/dashboard.py @@ -1,19 +1,50 @@ +import json from typing import Optional, List from app import schemas from app.chain import ChainBase +from app.db.mediaserver_oper import MediaServerOper from app.utils.singleton import Singleton class DashboardChain(ChainBase, metaclass=Singleton): + + def __init__(self): + super().__init__() + self.dboper = MediaServerOper() + """ 各类仪表板统计处理链 """ - def media_statistic(self) -> Optional[List[schemas.Statistic]]: + + def media_statistic(self) -> Optional[schemas.Statistic]: """ 媒体数量统计 """ - return self.run_module("media_statistic") + ret_statistic = schemas.Statistic() + media_statistics = self.run_module("media_statistic") + if media_statistics: + # 汇总各媒体库统计信息 + for media_statistic in media_statistics: + ret_statistic.user_count += media_statistic.user_count + # 电影数量 + movies = self.dboper.list_by_type(mtype="电影") or [] + ret_statistic.movie_count = len(movies) + # 电视剧数量 + series = self.dboper.list_by_type(mtype="电视剧") or [] + if series: + ret_statistic.tv_count = len(series) + # 剧集数量 + for tv in series: + seasoninfo = tv.seasoninfo + if seasoninfo: + if not isinstance(seasoninfo, dict): + seasoninfo = json.loads(seasoninfo) + if seasoninfo.keys(): + for season in seasoninfo.keys(): + episodes = seasoninfo.get(season) or [] + ret_statistic.episode_count += len(episodes) + return ret_statistic def downloader_info(self) -> schemas.DownloaderInfo: """ diff --git a/app/db/mediaserver_oper.py b/app/db/mediaserver_oper.py index d22e4504..f0a7eb41 100644 --- a/app/db/mediaserver_oper.py +++ b/app/db/mediaserver_oper.py @@ -65,3 +65,9 @@ class MediaServerOper(DbOper): if not item: return None return str(item.item_id) + + def list_by_type(self, mtype: str = None): + """ + 获取指定类型的媒体服务器数据 + """ + return MediaServerItem.list_by_type(self._db, mtype=mtype) diff --git a/app/db/models/mediaserver.py b/app/db/models/mediaserver.py index 1690bc04..f4fce7ac 100644 --- a/app/db/models/mediaserver.py +++ b/app/db/models/mediaserver.py @@ -66,3 +66,11 @@ class MediaServerItem(Base): return db.query(MediaServerItem).filter(MediaServerItem.title == title, MediaServerItem.item_type == mtype, MediaServerItem.year == str(year)).first() + + @staticmethod + @db_query + def list_by_type(db: Session, mtype: str = None): + if mtype: + return db.query(MediaServerItem).filter(MediaServerItem.item_type == mtype).all() + else: + return db.query(MediaServerItem).all() From 7587946d51fd00f9912d6ffb1e9b092061b6be99 Mon Sep 17 00:00:00 2001 From: thsrite Date: Wed, 10 Jan 2024 10:53:32 +0800 Subject: [PATCH 3/5] fix c674e320 --- app/chain/mediaserver.py | 24 ++---------------------- app/modules/emby/emby.py | 21 ++++++++++++++++++--- app/modules/jellyfin/jellyfin.py | 21 ++++++++++++++++++--- app/schemas/mediaserver.py | 1 - 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/app/chain/mediaserver.py b/app/chain/mediaserver.py index 64d1d621..68df03b9 100644 --- a/app/chain/mediaserver.py +++ b/app/chain/mediaserver.py @@ -48,33 +48,13 @@ class MediaServerChain(ChainBase): """ 获取媒体服务器正在播放信息 """ - playing_items = self.run_module("mediaserver_playing", count=100, server=server, username=username) - # 判断是否在同步的媒体数据中 - exists_items = [] - for item in playing_items: - if self.dboper.exists(mtype=item.type, - title=item.title, - year=item.year): - exists_items.append(item) - if len(exists_items) == count: - break - return exists_items + return self.run_module("mediaserver_playing", count=count, server=server, username=username) def latest(self, count: int = 20, server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器最新入库条目 """ - latest_items = self.run_module("mediaserver_latest", count=100, server=server, username=username) - # 判断是否在同步的媒体数据中 - exists_items = [] - for item in latest_items: - if self.dboper.exists(mtype=item.type, - title=item.title, - year=item.subtitle): - exists_items.append(item) - if len(exists_items) == count: - break - return exists_items + return self.run_module("mediaserver_latest", count=count, server=server, username=username) def get_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ diff --git a/app/modules/emby/emby.py b/app/modules/emby/emby.py index 9306ae68..d47ac440 100644 --- a/app/modules/emby/emby.py +++ b/app/modules/emby/emby.py @@ -971,15 +971,23 @@ class Emby(metaclass=Singleton): else: user = self.user req_url = (f"{self._host}Users/{user}/Items/Resume?" - f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") + f"Limit=100&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear,Path") try: res = RequestUtils().get_res(req_url) if res: result = res.json().get("Items") or [] ret_resume = [] + # 用户媒体库列表(排除黑名单) + user_librarys = self.get_librarys(username=user) for item in result: + if len(ret_resume) == num: + break if item.get("Type") not in ["Movie", "Episode"]: continue + item_path = item.get("Path") + if item_path and user_librarys and not any( + library.name in item_path for library in user_librarys): + continue item_type = MediaType.MOVIE.value if item.get("Type") == "Movie" else MediaType.TV.value link = self.get_play_url(item.get("Id")) if item_type == MediaType.MOVIE.value: @@ -1002,7 +1010,6 @@ class Emby(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.get("Id"), title=title, - year=item.get("ProductionYear"), subtitle=subtitle, type=item_type, image=image, @@ -1027,15 +1034,23 @@ class Emby(metaclass=Singleton): else: user = self.user req_url = (f"{self._host}Users/{user}/Items/Latest?" - f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") + f"Limit=100&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear,Path") try: res = RequestUtils().get_res(req_url) if res: result = res.json() or [] ret_latest = [] + # 用户媒体库列表(排除黑名单) + user_librarys = self.get_librarys(username=user) for item in result: + if len(ret_latest) == num: + break if item.get("Type") not in ["Movie", "Series"]: continue + item_path = item.get("Path") + if item_path and user_librarys and not any( + library.name in item_path for library in user_librarys): + continue item_type = MediaType.MOVIE.value if item.get("Type") == "Movie" else MediaType.TV.value link = self.get_play_url(item.get("Id")) image = self.__get_local_image_by_id(item_id=item.get("Id")) diff --git a/app/modules/jellyfin/jellyfin.py b/app/modules/jellyfin/jellyfin.py index 4b298a85..b68359f3 100644 --- a/app/modules/jellyfin/jellyfin.py +++ b/app/modules/jellyfin/jellyfin.py @@ -654,15 +654,23 @@ class Jellyfin(metaclass=Singleton): else: user = self.user req_url = (f"{self._host}Users/{user}/Items/Resume?" - f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") + f"Limit=100&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear,Path") try: res = RequestUtils().get_res(req_url) if res: result = res.json().get("Items") or [] ret_resume = [] + # 用户媒体库列表(排除黑名单) + user_librarys = self.get_librarys(username=user) for item in result: + if len(ret_resume) == num: + break if item.get("Type") not in ["Movie", "Episode"]: continue + item_path = item.get("Path") + if item_path and user_librarys and not any( + library.name in item_path for library in user_librarys): + continue item_type = MediaType.MOVIE.value if item.get("Type") == "Movie" else MediaType.TV.value link = self.get_play_url(item.get("Id")) if item.get("BackdropImageTags"): @@ -679,7 +687,6 @@ class Jellyfin(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.get("Id"), title=title, - year=item.get("ProductionYear"), subtitle=subtitle, type=item_type, image=image, @@ -704,15 +711,23 @@ class Jellyfin(metaclass=Singleton): else: user = self.user req_url = (f"{self._host}Users/{user}/Items/Latest?" - f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") + f"Limit=100&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear,Path") try: res = RequestUtils().get_res(req_url) if res: result = res.json() or [] ret_latest = [] + # 用户媒体库列表(排除黑名单) + user_librarys = self.get_librarys(username=user) for item in result: + if len(ret_latest) == num: + break if item.get("Type") not in ["Movie", "Series"]: continue + item_path = item.get("Path") + if item_path and user_librarys and not any( + library.name in item_path for library in user_librarys): + continue item_type = MediaType.MOVIE.value if item.get("Type") == "Movie" else MediaType.TV.value link = self.get_play_url(item.get("Id")) image = self.__get_local_image_by_id(item_id=item.get("Id")) diff --git a/app/schemas/mediaserver.py b/app/schemas/mediaserver.py index 373efa58..582ad2d7 100644 --- a/app/schemas/mediaserver.py +++ b/app/schemas/mediaserver.py @@ -151,7 +151,6 @@ class MediaServerPlayItem(BaseModel): """ id: Optional[Union[str, int]] = None title: Optional[str] = None - year: Optional[str] = None subtitle: Optional[str] = None type: Optional[str] = None image: Optional[str] = None From c1ecdfc61daa4288c7dbd670f6495da08b15ae02 Mon Sep 17 00:00:00 2001 From: thsrite Date: Wed, 10 Jan 2024 11:19:25 +0800 Subject: [PATCH 4/5] Revert "fix #907" This reverts commit 4dcefb141a6d1958e36156155d0b1f8a89aafcc5. --- app/api/endpoints/dashboard.py | 13 ++++++++++++- app/chain/dashboard.py | 35 ++-------------------------------- app/db/mediaserver_oper.py | 6 ------ app/db/models/mediaserver.py | 8 -------- 4 files changed, 14 insertions(+), 48 deletions(-) diff --git a/app/api/endpoints/dashboard.py b/app/api/endpoints/dashboard.py index 35f81317..ce437d37 100644 --- a/app/api/endpoints/dashboard.py +++ b/app/api/endpoints/dashboard.py @@ -20,7 +20,18 @@ def statistic(_: schemas.TokenPayload = Depends(verify_token)) -> Any: """ 查询媒体数量统计信息 """ - return DashboardChain().media_statistic() + media_statistics: Optional[List[schemas.Statistic]] = DashboardChain().media_statistic() + if media_statistics: + # 汇总各媒体库统计信息 + ret_statistic = schemas.Statistic() + for media_statistic in media_statistics: + ret_statistic.movie_count += media_statistic.movie_count + ret_statistic.tv_count += media_statistic.tv_count + ret_statistic.episode_count += media_statistic.episode_count + ret_statistic.user_count += media_statistic.user_count + return ret_statistic + else: + return schemas.Statistic() @router.get("/statistic2", summary="媒体数量统计(API_TOKEN)", response_model=schemas.Statistic) diff --git a/app/chain/dashboard.py b/app/chain/dashboard.py index 0aff73f6..35258a90 100644 --- a/app/chain/dashboard.py +++ b/app/chain/dashboard.py @@ -1,50 +1,19 @@ -import json from typing import Optional, List from app import schemas from app.chain import ChainBase -from app.db.mediaserver_oper import MediaServerOper from app.utils.singleton import Singleton class DashboardChain(ChainBase, metaclass=Singleton): - - def __init__(self): - super().__init__() - self.dboper = MediaServerOper() - """ 各类仪表板统计处理链 """ - - def media_statistic(self) -> Optional[schemas.Statistic]: + def media_statistic(self) -> Optional[List[schemas.Statistic]]: """ 媒体数量统计 """ - ret_statistic = schemas.Statistic() - media_statistics = self.run_module("media_statistic") - if media_statistics: - # 汇总各媒体库统计信息 - for media_statistic in media_statistics: - ret_statistic.user_count += media_statistic.user_count - # 电影数量 - movies = self.dboper.list_by_type(mtype="电影") or [] - ret_statistic.movie_count = len(movies) - # 电视剧数量 - series = self.dboper.list_by_type(mtype="电视剧") or [] - if series: - ret_statistic.tv_count = len(series) - # 剧集数量 - for tv in series: - seasoninfo = tv.seasoninfo - if seasoninfo: - if not isinstance(seasoninfo, dict): - seasoninfo = json.loads(seasoninfo) - if seasoninfo.keys(): - for season in seasoninfo.keys(): - episodes = seasoninfo.get(season) or [] - ret_statistic.episode_count += len(episodes) - return ret_statistic + return self.run_module("media_statistic") def downloader_info(self) -> schemas.DownloaderInfo: """ diff --git a/app/db/mediaserver_oper.py b/app/db/mediaserver_oper.py index f0a7eb41..d22e4504 100644 --- a/app/db/mediaserver_oper.py +++ b/app/db/mediaserver_oper.py @@ -65,9 +65,3 @@ class MediaServerOper(DbOper): if not item: return None return str(item.item_id) - - def list_by_type(self, mtype: str = None): - """ - 获取指定类型的媒体服务器数据 - """ - return MediaServerItem.list_by_type(self._db, mtype=mtype) diff --git a/app/db/models/mediaserver.py b/app/db/models/mediaserver.py index f4fce7ac..1690bc04 100644 --- a/app/db/models/mediaserver.py +++ b/app/db/models/mediaserver.py @@ -66,11 +66,3 @@ class MediaServerItem(Base): return db.query(MediaServerItem).filter(MediaServerItem.title == title, MediaServerItem.item_type == mtype, MediaServerItem.year == str(year)).first() - - @staticmethod - @db_query - def list_by_type(db: Session, mtype: str = None): - if mtype: - return db.query(MediaServerItem).filter(MediaServerItem.item_type == mtype).all() - else: - return db.query(MediaServerItem).all() From 3646540a7f5d66ddfdf6d5b1bac693b0ffc5c023 Mon Sep 17 00:00:00 2001 From: thsrite Date: Wed, 10 Jan 2024 11:21:03 +0800 Subject: [PATCH 5/5] fix --- app/modules/plex/plex.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/modules/plex/plex.py b/app/modules/plex/plex.py index bf89352b..7c52a975 100644 --- a/app/modules/plex/plex.py +++ b/app/modules/plex/plex.py @@ -626,7 +626,6 @@ class Plex(metaclass=Singleton): ret_resume.append(schemas.MediaServerPlayItem( id=item.key, title=title, - year=item.year, subtitle=subtitle, type=item_type, image=image,