From bf8a75b201a956cd50dddca698b9b8c11a371165 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 7 Jan 2024 11:46:29 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BC=98=E5=8C=96emby=E3=80=81jell?= =?UTF-8?q?yfin=E7=94=A8=E6=88=B7=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/login.py | 4 +++- app/api/endpoints/mediaserver.py | 13 ++++++------- app/chain/mediaserver.py | 12 ++++++------ app/core/security.py | 10 ++++++++-- app/modules/emby/__init__.py | 14 ++++++++------ app/modules/emby/emby.py | 30 ++++++++++++++++++++++-------- app/modules/jellyfin/__init__.py | 14 ++++++++------ app/modules/jellyfin/jellyfin.py | 30 ++++++++++++++++++++++-------- app/modules/plex/__init__.py | 6 +++--- app/schemas/token.py | 4 ++++ 10 files changed, 90 insertions(+), 47 deletions(-) diff --git a/app/api/endpoints/login.py b/app/api/endpoints/login.py index 5b013ca0..b70c39e0 100644 --- a/app/api/endpoints/login.py +++ b/app/api/endpoints/login.py @@ -56,7 +56,9 @@ async def login_access_token( logger.info(f"用户 {user.name} 登录成功!") return schemas.Token( access_token=security.create_access_token( - user.id, + userid=user.id, + username=user.name, + super_user=user.is_superuser, expires_delta=timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) ), token_type="bearer", diff --git a/app/api/endpoints/mediaserver.py b/app/api/endpoints/mediaserver.py index a1184313..4e914730 100644 --- a/app/api/endpoints/mediaserver.py +++ b/app/api/endpoints/mediaserver.py @@ -8,7 +8,6 @@ from app.chain.download import DownloadChain from app.chain.media import MediaChain from app.chain.mediaserver import MediaServerChain from app.core.config import settings -from app.core.context import MediaInfo from app.core.metainfo import MetaInfo from app.core.security import verify_token from app.db import get_db @@ -123,25 +122,25 @@ def not_exists(media_in: schemas.MediaInfo, @router.get("/latest", summary="最新入库条目", response_model=List[schemas.MediaServerPlayItem]) def latest(count: int = 18, - _: schemas.TokenPayload = Depends(verify_token)) -> Any: + userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any: """ 获取媒体服务器最新入库条目 """ - return MediaServerChain().latest(count=count) or [] + return MediaServerChain().latest(count=count, username=userinfo.username) or [] @router.get("/playing", summary="正在播放条目", response_model=List[schemas.MediaServerPlayItem]) def playing(count: int = 12, - _: schemas.TokenPayload = Depends(verify_token)) -> Any: + userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any: """ 获取媒体服务器正在播放条目 """ - return MediaServerChain().playing(count=count) or [] + return MediaServerChain().playing(count=count, username=userinfo.username) or [] @router.get("/library", summary="媒体库列表", response_model=List[schemas.MediaServerLibrary]) -def library(_: schemas.TokenPayload = Depends(verify_token)) -> Any: +def library(userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any: """ 获取媒体服务器媒体库列表 """ - return MediaServerChain().librarys() or [] + return MediaServerChain().librarys(userinfo.username) or [] diff --git a/app/chain/mediaserver.py b/app/chain/mediaserver.py index 23b988d0..68df03b9 100644 --- a/app/chain/mediaserver.py +++ b/app/chain/mediaserver.py @@ -20,11 +20,11 @@ class MediaServerChain(ChainBase): super().__init__() self.dboper = MediaServerOper() - def librarys(self, server: str = None) -> List[schemas.MediaServerLibrary]: + def librarys(self, server: str = None, username: str = None) -> List[schemas.MediaServerLibrary]: """ 获取媒体服务器所有媒体库 """ - return self.run_module("mediaserver_librarys", server=server) + return self.run_module("mediaserver_librarys", server=server, username=username) def items(self, server: str, library_id: Union[str, int]) -> List[schemas.MediaServerItem]: """ @@ -44,17 +44,17 @@ class MediaServerChain(ChainBase): """ return self.run_module("mediaserver_tv_episodes", server=server, item_id=item_id) - def playing(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def playing(self, count: int = 20, server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器正在播放信息 """ - return self.run_module("mediaserver_playing", count=count, server=server) + return self.run_module("mediaserver_playing", count=count, server=server, username=username) - def latest(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + 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) + 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/core/security.py b/app/core/security.py index e99e6112..a4855e8b 100644 --- a/app/core/security.py +++ b/app/core/security.py @@ -26,7 +26,8 @@ reusable_oauth2 = OAuth2PasswordBearer( def create_access_token( - subject: Union[str, Any], expires_delta: timedelta = None + userid: Union[str, Any], username: str, super_user: bool = False, + expires_delta: timedelta = None ) -> str: if expires_delta: expire = datetime.utcnow() + expires_delta @@ -34,7 +35,12 @@ def create_access_token( expire = datetime.utcnow() + timedelta( minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES ) - to_encode = {"exp": expire, "sub": str(subject)} + to_encode = { + "exp": expire, + "sub": str(userid), + "username": username, + "super_user": super_user + } encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt diff --git a/app/modules/emby/__init__.py b/app/modules/emby/__init__.py index 0e77a676..22241e53 100644 --- a/app/modules/emby/__init__.py +++ b/app/modules/emby/__init__.py @@ -103,13 +103,13 @@ class EmbyModule(_ModuleBase): media_statistic.user_count = self.emby.get_user_count() return [media_statistic] - def mediaserver_librarys(self, server: str = None) -> Optional[List[schemas.MediaServerLibrary]]: + def mediaserver_librarys(self, server: str = None, username: str = None) -> Optional[List[schemas.MediaServerLibrary]]: """ 媒体库列表 """ if server and server != "emby": return None - return self.emby.get_librarys() + return self.emby.get_librarys(username) def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]: """ @@ -142,13 +142,14 @@ class EmbyModule(_ModuleBase): episodes=episodes ) for season, episodes in seasoninfo.items()] - def mediaserver_playing(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_playing(self, count: int = 20, + server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器正在播放信息 """ if server and server != "emby": return [] - return self.emby.get_resume(count) + return self.emby.get_resume(num=count, username=username) def mediaserver_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ @@ -158,10 +159,11 @@ class EmbyModule(_ModuleBase): return None return self.emby.get_play_url(item_id) - def mediaserver_latest(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_latest(self, count: int = 20, + server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器最新入库条目 """ if server and server != "emby": return [] - return self.emby.get_latest(count) + return self.emby.get_latest(num=count, username=username) diff --git a/app/modules/emby/emby.py b/app/modules/emby/emby.py index b7e4b1fe..1c603fbf 100644 --- a/app/modules/emby/emby.py +++ b/app/modules/emby/emby.py @@ -66,13 +66,17 @@ class Emby(metaclass=Singleton): logger.error(f"连接Library/SelectableMediaFolders 出错:" + str(e)) return [] - def __get_emby_librarys(self) -> List[dict]: + def __get_emby_librarys(self, username: str = None) -> List[dict]: """ 获取Emby媒体库列表 """ if not self._host or not self._apikey: return [] - req_url = f"{self._host}emby/Users/{self.user}/Views?api_key={self._apikey}" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = f"{self._host}emby/Users/{user}/Views?api_key={self._apikey}" try: res = RequestUtils().get_res(req_url) if res: @@ -84,7 +88,7 @@ class Emby(metaclass=Singleton): logger.error(f"连接User/Views 出错:" + str(e)) return [] - def get_librarys(self) -> List[schemas.MediaServerLibrary]: + def get_librarys(self, username: str = None) -> List[schemas.MediaServerLibrary]: """ 获取媒体服务器所有媒体库列表 """ @@ -92,7 +96,7 @@ class Emby(metaclass=Singleton): return [] libraries = [] black_list = (settings.MEDIASERVER_SYNC_BLACKLIST or '').split(",") - for library in self.__get_emby_librarys() or []: + for library in self.__get_emby_librarys(username) or []: if library.get("Name") in black_list: continue match library.get("CollectionType"): @@ -956,13 +960,18 @@ class Emby(metaclass=Singleton): return "" return "%sItems/%s/Images/Primary" % (self._host, item_id) - def get_resume(self, num: int = 12) -> Optional[List[schemas.MediaServerPlayItem]]: + def get_resume(self, num: int = 12, username: str = None) -> Optional[List[schemas.MediaServerPlayItem]]: """ 获得继续观看 """ if not self._host or not self._apikey: return None - req_url = f"{self._host}Users/{self.user}/Items/Resume?Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = (f"{self._host}Users/{user}/Items/Resume?" + f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") try: res = RequestUtils().get_res(req_url) if res: @@ -1006,13 +1015,18 @@ class Emby(metaclass=Singleton): logger.error(f"连接Users/Items/Resume出错:" + str(e)) return [] - def get_latest(self, num: int = 20) -> Optional[List[schemas.MediaServerPlayItem]]: + def get_latest(self, num: int = 20, username: str = None) -> Optional[List[schemas.MediaServerPlayItem]]: """ 获得最近更新 """ if not self._host or not self._apikey: return None - req_url = f"{self._host}Users/{self.user}/Items/Latest?Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = (f"{self._host}Users/{user}/Items/Latest?" + f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") try: res = RequestUtils().get_res(req_url) if res: diff --git a/app/modules/jellyfin/__init__.py b/app/modules/jellyfin/__init__.py index 494a72d4..e2b88279 100644 --- a/app/modules/jellyfin/__init__.py +++ b/app/modules/jellyfin/__init__.py @@ -101,13 +101,13 @@ class JellyfinModule(_ModuleBase): media_statistic.user_count = self.jellyfin.get_user_count() return [media_statistic] - def mediaserver_librarys(self, server: str = None) -> Optional[List[schemas.MediaServerLibrary]]: + def mediaserver_librarys(self, server: str = None, username: str = None) -> Optional[List[schemas.MediaServerLibrary]]: """ 媒体库列表 """ if server and server != "jellyfin": return None - return self.jellyfin.get_librarys() + return self.jellyfin.get_librarys(username) def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]: """ @@ -140,13 +140,14 @@ class JellyfinModule(_ModuleBase): episodes=episodes ) for season, episodes in seasoninfo.items()] - def mediaserver_playing(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_playing(self, count: int = 20, + server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器正在播放信息 """ if server and server != "jellyfin": return [] - return self.jellyfin.get_resume(count) + return self.jellyfin.get_resume(num=count, username=username) def mediaserver_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ @@ -156,10 +157,11 @@ class JellyfinModule(_ModuleBase): return None return self.jellyfin.get_play_url(item_id) - def mediaserver_latest(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_latest(self, count: int = 20, + server: str = None, username: str = None) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器最新入库条目 """ if server and server != "jellyfin": return [] - return self.jellyfin.get_latest(count) + return self.jellyfin.get_latest(num=count, username=username) diff --git a/app/modules/jellyfin/jellyfin.py b/app/modules/jellyfin/jellyfin.py index 127dbd2a..81d55e41 100644 --- a/app/modules/jellyfin/jellyfin.py +++ b/app/modules/jellyfin/jellyfin.py @@ -45,13 +45,17 @@ class Jellyfin(metaclass=Singleton): self.user = self.get_user() self.serverid = self.get_server_id() - def __get_jellyfin_librarys(self) -> List[dict]: + def __get_jellyfin_librarys(self, username: str = None) -> List[dict]: """ 获取Jellyfin媒体库的信息 """ if not self._host or not self._apikey: return [] - req_url = f"{self._host}Users/{self.user}/Views?api_key={self._apikey}" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = f"{self._host}Users/{user}/Views?api_key={self._apikey}" try: res = RequestUtils().get_res(req_url) if res: @@ -63,7 +67,7 @@ class Jellyfin(metaclass=Singleton): logger.error(f"连接Users/Views 出错:" + str(e)) return [] - def get_librarys(self): + def get_librarys(self, username: str = None) -> List[schemas.MediaServerLibrary]: """ 获取媒体服务器所有媒体库列表 """ @@ -71,7 +75,7 @@ class Jellyfin(metaclass=Singleton): return [] libraries = [] black_list = (settings.MEDIASERVER_SYNC_BLACKLIST or '').split(",") - for library in self.__get_jellyfin_librarys() or []: + for library in self.__get_jellyfin_librarys(username) or []: if library.get("Name") in black_list: continue match library.get("CollectionType"): @@ -639,13 +643,18 @@ class Jellyfin(metaclass=Singleton): return f"{self._host}Items/{item_id}/" \ f"Images/Backdrop?tag={image_tag}&fillWidth=666&api_key={self._apikey}" - def get_resume(self, num: int = 12) -> Optional[List[schemas.MediaServerPlayItem]]: + def get_resume(self, num: int = 12, username: str = None) -> Optional[List[schemas.MediaServerPlayItem]]: """ 获得继续观看 """ if not self._host or not self._apikey: return None - req_url = f"{self._host}Users/{self.user}/Items/Resume?Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = (f"{self._host}Users/{user}/Items/Resume?" + f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") try: res = RequestUtils().get_res(req_url) if res: @@ -683,13 +692,18 @@ class Jellyfin(metaclass=Singleton): logger.error(f"连接Users/Items/Resume出错:" + str(e)) return [] - def get_latest(self, num=20) -> Optional[List[schemas.MediaServerPlayItem]]: + def get_latest(self, num=20, username: str = None) -> Optional[List[schemas.MediaServerPlayItem]]: """ 获得最近更新 """ if not self._host or not self._apikey: return None - req_url = f"{self._host}Users/{self.user}/Items/Latest?Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear" + if username: + user = self.get_user(username) + else: + user = self.user + req_url = (f"{self._host}Users/{user}/Items/Latest?" + f"Limit={num}&MediaTypes=Video&api_key={self._apikey}&Fields=ProductionYear") try: res = RequestUtils().get_res(req_url) if res: diff --git a/app/modules/plex/__init__.py b/app/modules/plex/__init__.py index e3d4b9ee..cd146a0a 100644 --- a/app/modules/plex/__init__.py +++ b/app/modules/plex/__init__.py @@ -95,7 +95,7 @@ class PlexModule(_ModuleBase): media_statistic.user_count = 1 return [media_statistic] - def mediaserver_librarys(self, server: str = None) -> Optional[List[schemas.MediaServerLibrary]]: + def mediaserver_librarys(self, server: str = None, **kwargs) -> Optional[List[schemas.MediaServerLibrary]]: """ 媒体库列表 """ @@ -134,7 +134,7 @@ class PlexModule(_ModuleBase): episodes=episodes ) for season, episodes in seasoninfo.items()] - def mediaserver_playing(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_playing(self, count: int = 20, server: str = None, **kwargs) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器正在播放信息 """ @@ -142,7 +142,7 @@ class PlexModule(_ModuleBase): return [] return self.plex.get_resume(count) - def mediaserver_latest(self, count: int = 20, server: str = None) -> List[schemas.MediaServerPlayItem]: + def mediaserver_latest(self, count: int = 20, server: str = None, **kwargs) -> List[schemas.MediaServerPlayItem]: """ 获取媒体服务器最新入库条目 """ diff --git a/app/schemas/token.py b/app/schemas/token.py index 488f73eb..95fe6dd1 100644 --- a/app/schemas/token.py +++ b/app/schemas/token.py @@ -14,3 +14,7 @@ class Token(BaseModel): class TokenPayload(BaseModel): # 用户ID sub: Optional[int] = None + # 用户名 + username: Optional[str] = None + # 超级用户 + super_user: Optional[bool] = None