mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-03-20 12:08:09 +08:00
Merge pull request #5096 from cddjr/fix_trimemedia_cookies
This commit is contained in:
@@ -16,6 +16,7 @@ from fastapi import APIRouter, Body, Depends, HTTPException, Header, Request, Re
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from app import schemas
|
||||
from app.chain.mediaserver import MediaServerChain
|
||||
from app.chain.search import SearchChain
|
||||
from app.chain.system import SystemChain
|
||||
from app.core.cache import AsyncFileCache
|
||||
@@ -52,6 +53,7 @@ async def fetch_image(
|
||||
proxy: bool = False,
|
||||
use_cache: bool = False,
|
||||
if_none_match: Optional[str] = None,
|
||||
cookies: Optional[str | dict] = None,
|
||||
allowed_domains: Optional[set[str]] = None) -> Optional[Response]:
|
||||
"""
|
||||
处理图片缓存逻辑,支持HTTP缓存和磁盘缓存
|
||||
@@ -96,8 +98,13 @@ async def fetch_image(
|
||||
# 请求远程图片
|
||||
referer = "https://movie.douban.com/" if "doubanio.com" in url else None
|
||||
proxies = settings.PROXY if proxy else None
|
||||
response = await AsyncRequestUtils(ua=settings.NORMAL_USER_AGENT, proxies=proxies, referer=referer,
|
||||
accept_type="image/avif,image/webp,image/apng,*/*").get_res(url=url)
|
||||
response = await AsyncRequestUtils(
|
||||
ua=settings.NORMAL_USER_AGENT,
|
||||
proxies=proxies,
|
||||
referer=referer,
|
||||
cookies=cookies,
|
||||
accept_type="image/avif,image/webp,image/apng,*/*",
|
||||
).get_res(url=url)
|
||||
if not response:
|
||||
logger.warn(f"Failed to fetch image from URL: {url}")
|
||||
return None
|
||||
@@ -140,6 +147,7 @@ async def proxy_img(
|
||||
imgurl: str,
|
||||
proxy: bool = False,
|
||||
cache: bool = False,
|
||||
use_cookies: bool = False,
|
||||
if_none_match: Annotated[str | None, Header()] = None,
|
||||
_: schemas.TokenPayload = Depends(verify_resource_token)
|
||||
) -> Response:
|
||||
@@ -150,7 +158,12 @@ async def proxy_img(
|
||||
hosts = [config.config.get("host") for config in MediaServerHelper().get_configs().values() if
|
||||
config and config.config and config.config.get("host")]
|
||||
allowed_domains = set(settings.SECURITY_IMAGE_DOMAINS) | set(hosts)
|
||||
return await fetch_image(url=imgurl, proxy=proxy, use_cache=cache,
|
||||
cookies = (
|
||||
MediaServerChain().get_image_cookies(server=None, image_url=imgurl)
|
||||
if use_cookies
|
||||
else None
|
||||
)
|
||||
return await fetch_image(url=imgurl, proxy=proxy, use_cache=cache, cookies=cookies,
|
||||
if_none_match=if_none_match, allowed_domains=allowed_domains)
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,16 @@ class MediaServerChain(ChainBase):
|
||||
"""
|
||||
return self.run_module("mediaserver_play_url", server=server, item_id=item_id)
|
||||
|
||||
def get_image_cookies(
|
||||
self, server: Optional[str], image_url: str
|
||||
) -> Optional[str | dict]:
|
||||
"""
|
||||
获取图片的Cookies
|
||||
"""
|
||||
return self.run_module(
|
||||
"mediaserver_image_cookies", server=server, image_url=image_url
|
||||
)
|
||||
|
||||
def sync(self):
|
||||
"""
|
||||
同步媒体库所有数据到本地数据库
|
||||
|
||||
@@ -382,3 +382,27 @@ class TrimeMediaModule(_ModuleBase, _MediaServerBase[TrimeMedia]):
|
||||
if not server_obj:
|
||||
return []
|
||||
return server_obj.get_latest_backdrops(num=count, remote=remote) or []
|
||||
|
||||
def mediaserver_image_cookies(
|
||||
self,
|
||||
server: Optional[str] = None,
|
||||
image_url: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> Optional[str | dict]:
|
||||
"""
|
||||
获取飞牛影视服务器的图片Cookies
|
||||
|
||||
:param server: 媒体服务器名称
|
||||
:param image_url: 图片网址
|
||||
"""
|
||||
if not image_url:
|
||||
return None
|
||||
if server:
|
||||
server_obj = self.get_instance(server)
|
||||
if not server_obj:
|
||||
return None
|
||||
return server_obj.get_image_cookies(image_url)
|
||||
else:
|
||||
for server_obj in self.get_instances().values():
|
||||
if cookies := server_obj.get_image_cookies(image_url):
|
||||
return cookies
|
||||
|
||||
@@ -190,7 +190,7 @@ class Api:
|
||||
"""
|
||||
用户列表(仅管理员有权访问)
|
||||
"""
|
||||
if (res := self.request("/memory/user/list")) and res.success:
|
||||
if (res := self.request("/manager/user/list")) and res.success:
|
||||
if not res.data:
|
||||
return []
|
||||
return [
|
||||
|
||||
@@ -5,6 +5,7 @@ import app.modules.trimemedia.api as fnapi
|
||||
from app import schemas
|
||||
from app.log import logger
|
||||
from app.schemas import MediaType
|
||||
from app.utils.security import SecurityUtils
|
||||
from app.utils.url import UrlUtils
|
||||
|
||||
|
||||
@@ -20,6 +21,7 @@ class TrimeMedia:
|
||||
_sync_libraries: List[str] = []
|
||||
|
||||
_api: Optional[fnapi.Api] = None
|
||||
_version: Optional[fnapi.Version] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -55,6 +57,13 @@ class TrimeMedia:
|
||||
"""
|
||||
return self._api
|
||||
|
||||
@property
|
||||
def version(self) -> Optional[fnapi.Version]:
|
||||
"""
|
||||
获得飞牛API的版本
|
||||
"""
|
||||
return self._version
|
||||
|
||||
class _ApiCreateResult:
|
||||
api: fnapi.Api
|
||||
version: fnapi.Version
|
||||
@@ -123,7 +132,9 @@ class TrimeMedia:
|
||||
self.disconnect()
|
||||
if result := self.__create_api(self._host):
|
||||
self._api = result.api
|
||||
self._version = result.version
|
||||
# 版本号:0.8.53, 服务版本:0.8.23
|
||||
# 版本号:0.8.56, 服务版本:0.8.23 接口/memory/user/list改为/manager/user/list
|
||||
logger.debug(
|
||||
f"版本号:{result.version.frontend}, 服务版本:{result.version.backend}"
|
||||
)
|
||||
@@ -189,6 +200,7 @@ class TrimeMedia:
|
||||
],
|
||||
link=f"{self._playhost or self._api.host}/library/{library.guid}",
|
||||
server_type="trimemedia",
|
||||
use_cookies=True,
|
||||
)
|
||||
)
|
||||
return libraries
|
||||
@@ -487,6 +499,7 @@ class TrimeMedia:
|
||||
else 0
|
||||
),
|
||||
server_type="trimemedia",
|
||||
use_cookies=True,
|
||||
)
|
||||
|
||||
def get_items(
|
||||
@@ -603,6 +616,7 @@ class TrimeMedia:
|
||||
if (item_details := self._api.item(item.guid)) is None:
|
||||
continue
|
||||
if remote:
|
||||
# FIXME 新版飞牛的壁纸无法直接在浏览器中访问
|
||||
img_host = self._playhost or self._api.host
|
||||
else:
|
||||
img_host = self._api.host
|
||||
@@ -631,3 +645,15 @@ class TrimeMedia:
|
||||
)
|
||||
else False
|
||||
)
|
||||
|
||||
def get_image_cookies(self, image_url: str):
|
||||
"""
|
||||
获得指定图片的Cookies
|
||||
"""
|
||||
if not self.is_authenticated():
|
||||
return None
|
||||
if not image_url or not SecurityUtils.is_safe_url(
|
||||
image_url, [self._api.host], strict=True
|
||||
):
|
||||
return None
|
||||
return {"Trim-MC-token": self._api.token}
|
||||
|
||||
@@ -74,6 +74,8 @@ class MediaServerLibrary(BaseModel):
|
||||
link: Optional[str] = None
|
||||
# 服务器类型
|
||||
server_type: Optional[str] = None
|
||||
# 飞牛的图片需要Cookies
|
||||
use_cookies: Optional[bool] = None
|
||||
|
||||
|
||||
class MediaServerItemUserState(BaseModel):
|
||||
@@ -177,3 +179,5 @@ class MediaServerPlayItem(BaseModel):
|
||||
percent: Optional[float] = None
|
||||
BackdropImageTags: Optional[list] = Field(default_factory=list)
|
||||
server_type: Optional[str] = None
|
||||
# 飞牛的图片需要Cookies
|
||||
use_cookies: Optional[bool] = None
|
||||
|
||||
Reference in New Issue
Block a user