mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-30 20:05:42 +08:00
fix(douban): map source languages for classification (#6860)
This commit is contained in:
@@ -6,10 +6,25 @@ import re
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
from app.domain.classification.vocabulary import LANGUAGE_NAMES
|
||||
from app.domain.metainfo import MetaInfo
|
||||
from app.domain.projection.mapping import ProjectionBuilder
|
||||
from app.schemas.types import MediaSource, MediaType
|
||||
|
||||
_DOUBAN_LANGUAGE_CODES: dict[str, str] = {
|
||||
**{name.casefold(): code for code, name in LANGUAGE_NAMES.items()},
|
||||
"汉语": "zh",
|
||||
"汉语普通话": "zh",
|
||||
"普通话": "zh",
|
||||
"国语": "zh",
|
||||
"简体中文": "zh",
|
||||
"繁体中文": "zh",
|
||||
"粤语": "cn",
|
||||
"广东话": "cn",
|
||||
"藏文": "bo",
|
||||
"壮文": "za",
|
||||
}
|
||||
|
||||
|
||||
def _media_type(info: Mapping[str, Any]) -> MediaType | None:
|
||||
"""从豆瓣多种详情形态解析标准媒体类型。"""
|
||||
@@ -67,6 +82,28 @@ def _aliases(info: Mapping[str, Any]) -> list[str]:
|
||||
return [re.sub(r"\([港台豆友译名]+\)", "", str(alias)) for alias in info.get("aka") or []]
|
||||
|
||||
|
||||
def _original_language(info: Mapping[str, Any]) -> str | None:
|
||||
"""将豆瓣返回的首个语言名称转换为分类规则使用的代码。"""
|
||||
languages = info.get("languages")
|
||||
if isinstance(languages, str):
|
||||
language_values: list[Any] = [languages]
|
||||
elif isinstance(languages, (list, tuple)):
|
||||
language_values = list(languages)
|
||||
else:
|
||||
return None
|
||||
for language in language_values:
|
||||
if not isinstance(language, str):
|
||||
continue
|
||||
value = language.strip()
|
||||
if not value:
|
||||
continue
|
||||
normalized = value.casefold()
|
||||
if re.fullmatch(r"[a-z]{2}(?:[-_]\w+)?", normalized):
|
||||
return normalized.split("-", 1)[0].split("_", 1)[0]
|
||||
return _DOUBAN_LANGUAGE_CODES.get(normalized, value)
|
||||
return None
|
||||
|
||||
|
||||
def project(
|
||||
current: Mapping[str, Any],
|
||||
info: Mapping[str, Any],
|
||||
@@ -87,6 +124,7 @@ def project(
|
||||
builder.set_missing("title", info.get("title"))
|
||||
builder.set_missing("en_title", info.get("original_title"))
|
||||
builder.set_missing("original_title", info.get("original_title"))
|
||||
builder.set_missing("original_language", _original_language(info))
|
||||
|
||||
if not builder.get("year"):
|
||||
year = str(info.get("year"))[:4] if info.get("year") else None
|
||||
|
||||
@@ -117,6 +117,7 @@ def test_douban_projection_is_complete_and_does_not_mutate_source() -> None:
|
||||
"genres": ["剧情"],
|
||||
"durations": ["45分钟"],
|
||||
"countries": ["中国大陆"],
|
||||
"languages": ["汉语普通话"],
|
||||
}
|
||||
original = deepcopy(source)
|
||||
|
||||
@@ -139,6 +140,25 @@ def test_douban_projection_is_complete_and_does_not_mutate_source() -> None:
|
||||
assert media.genres == [{"id": "剧情", "name": "剧情"}]
|
||||
assert media.runtime == 45
|
||||
assert media.production_countries == [{"id": "中国大陆", "name": "中国大陆"}]
|
||||
assert media.original_language == "zh"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("language", "expected"),
|
||||
[("汉语普通话", "zh"), ("粤语", "cn"), ("英语", "en"), ("ja", "ja")],
|
||||
)
|
||||
def test_douban_projection_maps_language_names_to_codes(language: str, expected: str) -> None:
|
||||
"""豆瓣常见语言名称应转换为稳定的分类语言代码。"""
|
||||
media = MediaInfo(
|
||||
douban_info={
|
||||
"id": "1292052",
|
||||
"title": "示例电影",
|
||||
"type": "movie",
|
||||
"languages": [language],
|
||||
}
|
||||
)
|
||||
|
||||
assert media.original_language == expected
|
||||
|
||||
|
||||
def test_bangumi_projection_is_complete_and_does_not_mutate_source() -> None:
|
||||
|
||||
Reference in New Issue
Block a user