fix:优化emby、jellyfin用户匹配

This commit is contained in:
jxxghp
2024-01-07 11:46:29 +08:00
parent 87111c8736
commit bf8a75b201
10 changed files with 90 additions and 47 deletions

View File

@@ -56,7 +56,9 @@ async def login_access_token(
logger.info(f"用户 {user.name} 登录成功!") logger.info(f"用户 {user.name} 登录成功!")
return schemas.Token( return schemas.Token(
access_token=security.create_access_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) expires_delta=timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
), ),
token_type="bearer", token_type="bearer",

View File

@@ -8,7 +8,6 @@ from app.chain.download import DownloadChain
from app.chain.media import MediaChain from app.chain.media import MediaChain
from app.chain.mediaserver import MediaServerChain from app.chain.mediaserver import MediaServerChain
from app.core.config import settings from app.core.config import settings
from app.core.context import MediaInfo
from app.core.metainfo import MetaInfo from app.core.metainfo import MetaInfo
from app.core.security import verify_token from app.core.security import verify_token
from app.db import get_db 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]) @router.get("/latest", summary="最新入库条目", response_model=List[schemas.MediaServerPlayItem])
def latest(count: int = 18, 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]) @router.get("/playing", summary="正在播放条目", response_model=List[schemas.MediaServerPlayItem])
def playing(count: int = 12, 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]) @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 []

View File

@@ -20,11 +20,11 @@ class MediaServerChain(ChainBase):
super().__init__() super().__init__()
self.dboper = MediaServerOper() 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]: 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) 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]: def get_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]:
""" """

View File

@@ -26,7 +26,8 @@ reusable_oauth2 = OAuth2PasswordBearer(
def create_access_token( 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: ) -> str:
if expires_delta: if expires_delta:
expire = datetime.utcnow() + expires_delta expire = datetime.utcnow() + expires_delta
@@ -34,7 +35,12 @@ def create_access_token(
expire = datetime.utcnow() + timedelta( expire = datetime.utcnow() + timedelta(
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES 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) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt return encoded_jwt

View File

@@ -103,13 +103,13 @@ class EmbyModule(_ModuleBase):
media_statistic.user_count = self.emby.get_user_count() media_statistic.user_count = self.emby.get_user_count()
return [media_statistic] 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": if server and server != "emby":
return None return None
return self.emby.get_librarys() return self.emby.get_librarys(username)
def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]: def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]:
""" """
@@ -142,13 +142,14 @@ class EmbyModule(_ModuleBase):
episodes=episodes episodes=episodes
) for season, episodes in seasoninfo.items()] ) 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": if server and server != "emby":
return [] 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]: def mediaserver_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]:
""" """
@@ -158,10 +159,11 @@ class EmbyModule(_ModuleBase):
return None return None
return self.emby.get_play_url(item_id) 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": if server and server != "emby":
return [] return []
return self.emby.get_latest(count) return self.emby.get_latest(num=count, username=username)

View File

@@ -66,13 +66,17 @@ class Emby(metaclass=Singleton):
logger.error(f"连接Library/SelectableMediaFolders 出错:" + str(e)) logger.error(f"连接Library/SelectableMediaFolders 出错:" + str(e))
return [] return []
def __get_emby_librarys(self) -> List[dict]: def __get_emby_librarys(self, username: str = None) -> List[dict]:
""" """
获取Emby媒体库列表 获取Emby媒体库列表
""" """
if not self._host or not self._apikey: if not self._host or not self._apikey:
return [] 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:
@@ -84,7 +88,7 @@ class Emby(metaclass=Singleton):
logger.error(f"连接User/Views 出错:" + str(e)) logger.error(f"连接User/Views 出错:" + str(e))
return [] 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 [] return []
libraries = [] libraries = []
black_list = (settings.MEDIASERVER_SYNC_BLACKLIST or '').split(",") 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: if library.get("Name") in black_list:
continue continue
match library.get("CollectionType"): match library.get("CollectionType"):
@@ -956,13 +960,18 @@ class Emby(metaclass=Singleton):
return "" return ""
return "%sItems/%s/Images/Primary" % (self._host, item_id) 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: if not self._host or not self._apikey:
return None 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:
@@ -1006,13 +1015,18 @@ class Emby(metaclass=Singleton):
logger.error(f"连接Users/Items/Resume出错" + str(e)) logger.error(f"连接Users/Items/Resume出错" + str(e))
return [] 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: if not self._host or not self._apikey:
return None 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:

View File

@@ -101,13 +101,13 @@ class JellyfinModule(_ModuleBase):
media_statistic.user_count = self.jellyfin.get_user_count() media_statistic.user_count = self.jellyfin.get_user_count()
return [media_statistic] 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": if server and server != "jellyfin":
return None return None
return self.jellyfin.get_librarys() return self.jellyfin.get_librarys(username)
def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]: def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]:
""" """
@@ -140,13 +140,14 @@ class JellyfinModule(_ModuleBase):
episodes=episodes episodes=episodes
) for season, episodes in seasoninfo.items()] ) 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": if server and server != "jellyfin":
return [] 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]: def mediaserver_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]:
""" """
@@ -156,10 +157,11 @@ class JellyfinModule(_ModuleBase):
return None return None
return self.jellyfin.get_play_url(item_id) 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": if server and server != "jellyfin":
return [] return []
return self.jellyfin.get_latest(count) return self.jellyfin.get_latest(num=count, username=username)

View File

@@ -45,13 +45,17 @@ class Jellyfin(metaclass=Singleton):
self.user = self.get_user() self.user = self.get_user()
self.serverid = self.get_server_id() self.serverid = self.get_server_id()
def __get_jellyfin_librarys(self) -> List[dict]: def __get_jellyfin_librarys(self, username: str = None) -> List[dict]:
""" """
获取Jellyfin媒体库的信息 获取Jellyfin媒体库的信息
""" """
if not self._host or not self._apikey: if not self._host or not self._apikey:
return [] 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:
@@ -63,7 +67,7 @@ class Jellyfin(metaclass=Singleton):
logger.error(f"连接Users/Views 出错:" + str(e)) logger.error(f"连接Users/Views 出错:" + str(e))
return [] return []
def get_librarys(self): def get_librarys(self, username: str = None) -> List[schemas.MediaServerLibrary]:
""" """
获取媒体服务器所有媒体库列表 获取媒体服务器所有媒体库列表
""" """
@@ -71,7 +75,7 @@ class Jellyfin(metaclass=Singleton):
return [] return []
libraries = [] libraries = []
black_list = (settings.MEDIASERVER_SYNC_BLACKLIST or '').split(",") 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: if library.get("Name") in black_list:
continue continue
match library.get("CollectionType"): match library.get("CollectionType"):
@@ -639,13 +643,18 @@ class Jellyfin(metaclass=Singleton):
return f"{self._host}Items/{item_id}/" \ return f"{self._host}Items/{item_id}/" \
f"Images/Backdrop?tag={image_tag}&fillWidth=666&api_key={self._apikey}" 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: if not self._host or not self._apikey:
return None 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:
@@ -683,13 +692,18 @@ class Jellyfin(metaclass=Singleton):
logger.error(f"连接Users/Items/Resume出错" + str(e)) logger.error(f"连接Users/Items/Resume出错" + str(e))
return [] 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: if not self._host or not self._apikey:
return None 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: try:
res = RequestUtils().get_res(req_url) res = RequestUtils().get_res(req_url)
if res: if res:

View File

@@ -95,7 +95,7 @@ class PlexModule(_ModuleBase):
media_statistic.user_count = 1 media_statistic.user_count = 1
return [media_statistic] 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 episodes=episodes
) for season, episodes in seasoninfo.items()] ) 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 []
return self.plex.get_resume(count) 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]:
""" """
获取媒体服务器最新入库条目 获取媒体服务器最新入库条目
""" """

View File

@@ -14,3 +14,7 @@ class Token(BaseModel):
class TokenPayload(BaseModel): class TokenPayload(BaseModel):
# 用户ID # 用户ID
sub: Optional[int] = None sub: Optional[int] = None
# 用户名
username: Optional[str] = None
# 超级用户
super_user: Optional[bool] = None