diff --git a/app/api/endpoints/login.py b/app/api/endpoints/login.py index ac4d7061..76220ea6 100644 --- a/app/api/endpoints/login.py +++ b/app/api/endpoints/login.py @@ -7,6 +7,7 @@ from fastapi.security import OAuth2PasswordRequestForm from app import schemas from app.chain.tmdb import TmdbChain from app.chain.user import UserChain +from app.chain.mediaserver import MediaServerChain from app.core import security from app.core.config import settings from app.helper.sites import SitesHelper @@ -53,10 +54,12 @@ def wallpaper() -> Any: """ 获取登录页面电影海报 """ - if settings.WALLPAPER == "tmdb": - url = TmdbChain().get_random_wallpager() - else: + if settings.WALLPAPER == "bing": url = WebUtils.get_bing_wallpaper() + elif settings.WALLPAPER == "mediaserver": + url = MediaServerChain().get_latest_wallpaper() + else: + url = TmdbChain().get_random_wallpager() if url: return schemas.Response( success=True, @@ -70,7 +73,9 @@ def wallpapers() -> Any: """ 获取登录页面电影海报 """ - if settings.WALLPAPER == "tmdb": - return TmdbChain().get_trending_wallpapers() - else: + if settings.WALLPAPER == "bing": return WebUtils.get_bing_wallpapers() + elif settings.WALLPAPER == "mediaserver": + url = MediaServerChain().get_latest_wallpapers() + else: + url = TmdbChain().get_trending_wallpapers() \ No newline at end of file diff --git a/app/chain/mediaserver.py b/app/chain/mediaserver.py index 8b9a5186..4f2eeef4 100644 --- a/app/chain/mediaserver.py +++ b/app/chain/mediaserver.py @@ -1,6 +1,8 @@ import threading from typing import List, Union, Optional, Generator +from cachetools import cached, TTLCache + from app import schemas from app.chain import ChainBase from app.core.config import global_vars @@ -91,6 +93,19 @@ class MediaServerChain(ChainBase): 获取媒体服务器最新入库条目 """ return self.run_module("mediaserver_latest", count=count, server=server, username=username) + + @cached(cache=TTLCache(maxsize=1, ttl=3600)) + def get_latest_wallpapers(self, server:str, count=20) -> List[str]: + """ + 获取最新最新入库条目海报作为壁纸,缓存1小时 + """ + return self.run_module("mediaserver_latest_images", server=server, count=count) + + def get_latest_wallpaper(self, server:str) -> Optional[str]: + """ + 获取最新最新入库条目海报作为壁纸,缓存1小时 + """ + return self.get_latest_wallpapers(server=server, count=20)[0] def get_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ diff --git a/app/core/config.py b/app/core/config.py index cd6af6be..eca5c9c3 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -79,7 +79,7 @@ class ConfigModel(BaseModel): API_TOKEN: Optional[str] = None # 网络代理 IP:PORT PROXY_HOST: Optional[str] = None - # 登录页面电影海报,tmdb/bing + # 登录页面电影海报,tmdb/bing/mediaserver WALLPAPER: str = "tmdb" # 媒体搜索来源 themoviedb/douban/bangumi,多个用,分隔 SEARCH_SOURCE: str = "themoviedb,douban,bangumi" diff --git a/app/modules/emby/__init__.py b/app/modules/emby/__init__.py index 5e7e9ed3..a2061152 100644 --- a/app/modules/emby/__init__.py +++ b/app/modules/emby/__init__.py @@ -280,3 +280,35 @@ class EmbyModule(_ModuleBase, _MediaServerBase[Emby]): if not server: return [] return server.get_latest(num=count, username=username) + + def mediaserver_latest_images(self, + server: str, + count: int = 20, + username: str = None, + host_type: bool = True, + ) -> List[str]: + """ + 获取媒体服务器最新入库条目的图片 + + :param server: 媒体服务器名称 + :param count: 获取数量 + :param username: 用户名 + :param host_type: True为外网链接, False为内网链接 + :return: 图片链接列表 + """ + server: Emby = self.get_instance(server) + if not server: + return [] + + links = [] + items: List[schemas.MediaServerPlayItem] = self.mediaserver_latest(num=count, username=username) + for item in items: + if host_type and item.id: + _link = server.generate_external_image_link(id=item.id, image_type="Backdrop") + if _link: + links.append(_link) + elif item.image: + links.append(item.image) + + return links + diff --git a/app/modules/jellyfin/__init__.py b/app/modules/jellyfin/__init__.py index 8afe61e8..563870c6 100644 --- a/app/modules/jellyfin/__init__.py +++ b/app/modules/jellyfin/__init__.py @@ -278,3 +278,31 @@ class JellyfinModule(_ModuleBase, _MediaServerBase[Jellyfin]): if not server: return [] return server.get_latest(num=count, username=username) + + def mediaserver_latest_images(self, + server: str, + count: int = 20, + username: str = None, + host_type: bool = True, + ) -> List[str]: + """ + 获取媒体服务器最新入库条目的图片 + + :param server: 媒体服务器名称 + :param count: 获取数量 + :param username: 用户名 + :param host_type: True为外网链接, False为内网链接 + :return: 图片链接列表 + """ + server: Jellyfin = self.get_instance(server) + if not server: + return [] + + links = [] + items: List[schemas.MediaServerPlayItem] = self.mediaserver_latest(num=count, username=username) + for item in items: + link = server.generate_image_link(item_id=item.id, image_type="Backdrop",host_type=host_type) + if link: + links.append(link) + + return links diff --git a/app/modules/plex/__init__.py b/app/modules/plex/__init__.py index 29a44f0c..e265779e 100644 --- a/app/modules/plex/__init__.py +++ b/app/modules/plex/__init__.py @@ -274,6 +274,34 @@ class PlexModule(_ModuleBase, _MediaServerBase[Plex]): return [] return server.get_latest(num=count) + def mediaserver_latest_images(self, + server: str, + count: int = 20, + username: str = None, + ) -> List[str]: + """ + 获取媒体服务器最新入库条目的图片 + + :param server: 媒体服务器名称 + :param count: 获取数量 + :param username: 用户名 + :return: 图片链接列表 + """ + server: Plex = self.get_instance(server) + if not server: + return [] + + links = [] + items: List[schemas.MediaServerPlayItem] = self.mediaserver_latest(num=count, username=username) + for item in items: + link = server.get_remote_image_by_id(item_id=item.id, + image_type="Backdrop", + plex_url=False) + if link: + links.append(link) + + return links + def mediaserver_play_url(self, server: str, item_id: Union[str, int]) -> Optional[str]: """ 获取媒体库播放地址 diff --git a/app/modules/plex/plex.py b/app/modules/plex/plex.py index e6f51030..2e7f4da3 100644 --- a/app/modules/plex/plex.py +++ b/app/modules/plex/plex.py @@ -293,13 +293,18 @@ class Plex: season_episodes[episode.seasonNumber].append(episode.index) return videos.key, season_episodes - def get_remote_image_by_id(self, item_id: str, image_type: str, depth: int = 0) -> Optional[str]: + def get_remote_image_by_id(self, + item_id: str, + image_type: str, + depth: int = 0, + plex_url: bool = True) -> Optional[str]: """ 根据ItemId从Plex查询图片地址 :param item_id: 在Plex中的ID :param image_type: 图片的类型,Poster或者Backdrop等 :param depth: 当前递归深度,默认为0 - :return: 图片对应在TMDB中的URL + :param plex_url: 是否返回Plex的URL,默认为True(仅在配置了外网地址和Token时有效) + :return: 图片对应在plex服务器或TMDB中的URL """ if not self._plex or depth > 2 or not item_id: return None @@ -310,7 +315,7 @@ class Plex: if not item: return None # 如果配置了外网播放地址以及Token,则默认从Plex媒体服务器获取图片,否则返回有外网地址的图片资源 - if self._playhost and self._token: + if self._playhost and self._token and plex_url: query = {"X-Plex-Token": self._token} if image_type == "Poster": if item.thumb: diff --git a/config/app.env b/config/app.env index 9c48016e..417a987b 100644 --- a/config/app.env +++ b/config/app.env @@ -33,7 +33,7 @@ META_CACHE_EXPIRE=0 AUTO_UPDATE_RESOURCE=true # 【*】API密钥,未设置时系统将随机生成,建议使用复杂字符串,用于Jellyseerr/Overseerr、媒体服务器Webhook等配置以及部分支持API_TOKEN的API请求 API_TOKEN='' -# 登录页面电影海报,tmdb/bing,tmdb要求能正常连接api.themoviedb.org +# 登录页面电影海报,tmdb/bing/mediaserver,tmdb要求能正常连接api.themoviedb.org WALLPAPER=tmdb # TMDB图片地址,无需修改需保留默认值,如果默认地址连通性不好可以尝试修改为:`static-mdb.v.geilijiasu.com` TMDB_IMAGE_DOMAIN=image.tmdb.org