mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-30 20:05:42 +08:00
fix(douban): normalize person search image URLs
This commit is contained in:
@@ -1695,6 +1695,10 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
|
||||
) -> List[MediaPerson]:
|
||||
"""
|
||||
把豆瓣人物搜索响应过滤并投影为统一人物列表。
|
||||
|
||||
:param name: 用于筛选人物标题的查询文本
|
||||
:param result: 豆瓣人物搜索响应
|
||||
:return: 图片尺寸已转换为 URL 的匹配人物列表
|
||||
"""
|
||||
persons = []
|
||||
for item in (result or {}).get("items") or []:
|
||||
@@ -1702,11 +1706,16 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
|
||||
title = target.get("title") or ""
|
||||
if name not in title:
|
||||
continue
|
||||
# 豆瓣尺寸图片可能包含宽高信息,统一模型只接收 URL;兼容已有字符串格式
|
||||
images = {
|
||||
size: image.get("url") if isinstance(image, dict) else image
|
||||
for size, image in (target.get("cover") or {}).items()
|
||||
}
|
||||
persons.append(MediaPerson(source="douban", **{
|
||||
"id": item.get("target_id"),
|
||||
"name": title,
|
||||
"url": target.get("url"),
|
||||
"images": target.get("cover", {}),
|
||||
"images": images,
|
||||
"avatar": (target.get("cover_img", {}).get("url") or "").replace(
|
||||
"/l/public/", "/s/public/"
|
||||
),
|
||||
|
||||
70
tests/test_douban_person_search.py
Normal file
70
tests/test_douban_person_search.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
豆瓣人物搜索图片投影的离线回归测试。
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from copy import deepcopy
|
||||
from typing import Optional
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from app.modules.douban import DoubanModule
|
||||
from app.schemas.types import MediaSource
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("cover", "expected"),
|
||||
[
|
||||
(
|
||||
{"large": {"url": "https://example.com/large.webp", "width": 0, "height": 0},
|
||||
"normal": {"url": "https://example.com/normal.jpg", "width": 0, "height": 0}},
|
||||
{"large": "https://example.com/large.webp", "normal": "https://example.com/normal.jpg"},
|
||||
),
|
||||
({"large": "https://example.com/large.jpg"}, {"large": "https://example.com/large.jpg"}),
|
||||
(
|
||||
{"large": {"url": "https://example.com/large.jpg"}, "normal": "https://example.com/normal.jpg"},
|
||||
{"large": "https://example.com/large.jpg", "normal": "https://example.com/normal.jpg"},
|
||||
),
|
||||
({"large": {}, "normal": {"url": None}, "small": None}, {}),
|
||||
({}, {}),
|
||||
(None, {}),
|
||||
],
|
||||
)
|
||||
def test_person_search_normalizes_images_in_sync_and_async_entries(
|
||||
cover: Optional[dict[str, object]], expected: dict[str, str],
|
||||
) -> None:
|
||||
"""
|
||||
两个入口均应保留匹配人物及头像,并兼容嵌套、字符串和空图片。
|
||||
|
||||
:param cover: 豆瓣返回的尺寸图片数据
|
||||
:param expected: 标准人物模型中应保留的有效尺寸 URL
|
||||
"""
|
||||
response = {"items": [
|
||||
{"target_id": "100", "target": {
|
||||
"title": "赵露思", "url": "https://example.com/person/100",
|
||||
"cover": cover, "cover_img": {"url": "https://example.com/l/public/avatar.jpg"},
|
||||
}},
|
||||
{"target_id": "101", "target": {"title": "赵露思(演员)"}},
|
||||
{"target_id": "102", "target": {"title": "其他人物"}},
|
||||
]}
|
||||
original = deepcopy(response)
|
||||
module = object.__new__(DoubanModule)
|
||||
module.doubanapi = Mock()
|
||||
module.doubanapi.person_search.return_value = response
|
||||
module.doubanapi.async_person_search = AsyncMock(return_value=response)
|
||||
|
||||
sync_result = module.search_persons("赵露思", media_source=MediaSource.Douban)
|
||||
async_result = asyncio.run(module.async_search_persons("赵露思", media_source=MediaSource.Douban))
|
||||
|
||||
assert sync_result == async_result
|
||||
assert [person.id for person in sync_result] == ["100", "101"]
|
||||
assert sync_result[0].source == "douban"
|
||||
assert sync_result[0].name == "赵露思"
|
||||
assert sync_result[0].url == "https://example.com/person/100"
|
||||
assert sync_result[0].avatar == "https://example.com/s/public/avatar.jpg"
|
||||
assert sync_result[0].images.model_dump(exclude_none=True) == expected
|
||||
assert sync_result[1].images.model_dump(exclude_none=True) == {}
|
||||
assert response == original
|
||||
module.doubanapi.person_search.assert_called_once_with(keyword="赵露思")
|
||||
module.doubanapi.async_person_search.assert_awaited_once_with(keyword="赵露思")
|
||||
Reference in New Issue
Block a user