mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-30 20:05:42 +08:00
143 lines
4.6 KiB
Python
143 lines
4.6 KiB
Python
"""
|
|
企业微信豆瓣图片代理的签名、取图和消息载荷测试。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock
|
|
from urllib.parse import parse_qs, urlparse
|
|
|
|
import pytest
|
|
from fastapi import HTTPException, Response
|
|
|
|
from app.api.endpoints import system as system_endpoint
|
|
from app.application.messaging import image as image_urls
|
|
from app.modules.wechat.wechat import WeChat
|
|
|
|
|
|
def _settings_with_domain(key: str) -> Any:
|
|
"""
|
|
提供企业微信图片 URL 构造所需的最小运行配置。
|
|
"""
|
|
return {
|
|
"APP_DOMAIN": "https://moviepilot.example",
|
|
"API_V1_STR": "/api/v1",
|
|
}[key]
|
|
|
|
|
|
def test_build_wechat_image_url_signs_only_douban_images(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""
|
|
只为豆瓣图片生成公开代理地址,其他图片保持原始 URL。
|
|
"""
|
|
monkeypatch.setattr(image_urls, "get_runtime_setting", _settings_with_domain)
|
|
source_url = "https://img9.doubanio.com/view/photo/l/public/p2932615136.webp"
|
|
|
|
proxy_url = image_urls.build_wechat_image_url(source_url)
|
|
parsed = urlparse(proxy_url or "")
|
|
signed_source = parse_qs(parsed.query)["url"][0]
|
|
|
|
assert parsed.scheme == "https"
|
|
assert parsed.netloc == "moviepilot.example"
|
|
assert parsed.path == "/api/v1/system/notification-image"
|
|
assert image_urls.verify_wechat_image_url(signed_source) == source_url
|
|
assert image_urls.build_wechat_image_url("https://image.tmdb.org/poster.jpg") == (
|
|
"https://image.tmdb.org/poster.jpg"
|
|
)
|
|
|
|
|
|
def test_build_wechat_image_url_keeps_original_without_public_domain(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""
|
|
未配置对外域名时不生成微信无法访问的本地地址。
|
|
"""
|
|
monkeypatch.setattr(
|
|
image_urls,
|
|
"get_runtime_setting",
|
|
lambda key: "" if key == "APP_DOMAIN" else "/api/v1",
|
|
)
|
|
source_url = "https://img9.doubanio.com/view/photo/l/public/p2932615136.webp"
|
|
|
|
assert image_urls.build_wechat_image_url(source_url) == source_url
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_notification_image_rejects_wrong_signature_and_domain() -> None:
|
|
"""
|
|
公开入口拒绝错误用途签名及非豆瓣来源,避免退化为通用代理。
|
|
"""
|
|
from app.application.security.url import SecurityUtils
|
|
|
|
signed_tmdb_url = SecurityUtils.sign_url(
|
|
"https://image.tmdb.org/poster.jpg",
|
|
purpose=image_urls.WECHAT_IMAGE_SIGNATURE_PURPOSE,
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as error:
|
|
await system_endpoint.notification_image(url=signed_tmdb_url)
|
|
|
|
assert error.value.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_notification_image_fetches_verified_source(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""
|
|
验证通过后复用统一图片代理,并保留全局缓存和 ETag 参数。
|
|
"""
|
|
from app.application.security.url import SecurityUtils
|
|
|
|
source_url = "https://img9.doubanio.com/view/photo/l/public/p2932615136.webp"
|
|
signed_url = SecurityUtils.sign_url(
|
|
source_url,
|
|
purpose=image_urls.WECHAT_IMAGE_SIGNATURE_PURPOSE,
|
|
)
|
|
response = Response(content=b"image", media_type="image/webp")
|
|
fetch_image = AsyncMock(return_value=response)
|
|
monkeypatch.setattr(system_endpoint, "fetch_image", fetch_image)
|
|
monkeypatch.setattr(
|
|
system_endpoint,
|
|
"get_runtime_settings",
|
|
lambda: {"GLOBAL_IMAGE_CACHE": True},
|
|
)
|
|
|
|
result = await system_endpoint.notification_image(
|
|
url=signed_url,
|
|
if_none_match="etag",
|
|
)
|
|
|
|
assert result is response
|
|
fetch_image.assert_awaited_once_with(
|
|
url=source_url,
|
|
use_cache=True,
|
|
if_none_match="etag",
|
|
)
|
|
|
|
|
|
def test_wechat_news_payload_uses_signed_douban_proxy(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""
|
|
企业微信图文载荷应把豆瓣图片替换为可公开取图的地址。
|
|
"""
|
|
monkeypatch.setattr(image_urls, "get_runtime_setting", _settings_with_domain)
|
|
captured: dict[str, Any] = {}
|
|
client = WeChat.__new__(WeChat)
|
|
client._appid = "1"
|
|
monkeypatch.setattr(
|
|
client,
|
|
"_WeChat__post_request",
|
|
lambda url, payload: captured.update(payload) or True,
|
|
)
|
|
source_url = "https://img9.doubanio.com/view/photo/l/public/p2932615136.webp"
|
|
|
|
assert client._WeChat__send_image_message(
|
|
title="奥德赛",
|
|
text="已添加订阅",
|
|
image_url=source_url,
|
|
) is True
|
|
|
|
image_url = captured["news"]["articles"][0]["picurl"]
|
|
signed_source = parse_qs(urlparse(image_url).query)["url"][0]
|
|
assert image_urls.verify_wechat_image_url(signed_source) == source_url
|