fix(agent): preserve episode lock on unchanged totals (#6271)

This commit is contained in:
InfinityPacer
2026-08-11 23:17:21 +08:00
committed by GitHub
parent d7cf853bc8
commit 1197ece12b
4 changed files with 154 additions and 2 deletions

View File

@@ -0,0 +1,35 @@
import asyncio
import json
from unittest.mock import patch
from app.agent.tools.impl.query_subscribes import QuerySubscribesTool
from app.db.models.subscribe import Subscribe
from app.schemas.types import MediaType
def test_agent_query_subscribes_returns_manual_total_episode():
"""订阅查询应返回手动总集数标记,供 Agent 判断元数据是否可自动刷新。"""
subscribe = Subscribe(
id=160,
name="测试剧集",
type=MediaType.TV.value,
tmdbid=224839,
season=1,
total_episode=175,
manual_total_episode=1,
state="P",
)
with patch(
"app.agent.tools.impl.query_subscribes.SubscribeOper.async_list",
return_value=[subscribe],
):
result = asyncio.run(
QuerySubscribesTool(session_id="session-1", user_id="10001").run(
tmdb_id=224839,
)
)
_, result_json = result.split("\n\n", maxsplit=1)
payload = json.loads(result_json)
assert payload[0]["manual_total_episode"] == 1

View File

@@ -3,7 +3,7 @@ import json
from unittest.mock import AsyncMock, patch
from app.agent.tools.impl.update_subscribe import UpdateSubscribeTool
from app.schemas.types import EventType
from app.schemas.types import EventType, MediaType
def test_agent_update_subscribe_sends_modified_event_payload_with_agent_scene():
@@ -41,6 +41,120 @@ def test_agent_update_subscribe_sends_modified_event_payload_with_agent_scene():
assert event_payload["subscribe_info"]["name"] == "新标题"
def test_agent_update_subscribe_ignores_unchanged_total_episode():
"""Agent 回传相同总集数时,不应产生数据库写入或订阅调整事件。"""
subscribe = _AgentSubscribe(
id=160,
name="测试剧集",
type=MediaType.TV.value,
state="R",
total_episode=175,
lack_episode=0,
manual_total_episode=0,
)
oper = _SubscribeOperStub(subscribe)
with patch(
"app.agent.tools.impl.update_subscribe.SubscribeOper",
return_value=oper,
), patch(
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
new=AsyncMock(),
) as send_event:
result = asyncio.run(
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
subscribe_id=160,
total_episode=175,
)
)
payload = json.loads(result)
assert payload == {"success": False, "message": "没有提供要更新的字段"}
assert oper.updates == []
send_event.assert_not_awaited()
def test_agent_update_subscribe_only_updates_other_fields_with_unchanged_total_episode():
"""Agent 同时回传相同总集数和洗版设置时,只更新实际请求的其他字段。"""
subscribe = _AgentSubscribe(
id=160,
name="测试剧集",
type=MediaType.TV.value,
state="R",
total_episode=175,
lack_episode=0,
manual_total_episode=0,
best_version=0,
)
oper = _SubscribeOperStub(subscribe)
with patch(
"app.agent.tools.impl.update_subscribe.SubscribeOper",
return_value=oper,
), patch(
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
new=AsyncMock(),
) as send_event:
result = asyncio.run(
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
subscribe_id=160,
total_episode=175,
best_version=1,
)
)
payload = json.loads(result)
assert payload["success"] is True
assert payload["updated_fields"] == ["best_version"]
assert payload["subscribe"]["manual_total_episode"] == 0
assert oper.updates == [(160, {"best_version": 1})]
send_event.assert_awaited_once()
_, event_payload = send_event.await_args.args
assert event_payload["fields"] == ["best_version"]
def test_agent_update_subscribe_marks_changed_total_episode_as_manual():
"""Agent 真正修改总集数时,保持 Web API 的手动总集数语义。"""
subscribe = _AgentSubscribe(
id=160,
name="测试剧集",
type=MediaType.TV.value,
state="R",
total_episode=175,
lack_episode=0,
manual_total_episode=0,
)
oper = _SubscribeOperStub(subscribe)
with patch(
"app.agent.tools.impl.update_subscribe.SubscribeOper",
return_value=oper,
), patch(
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
new=AsyncMock(),
):
result = asyncio.run(
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
subscribe_id=160,
total_episode=190,
)
)
payload = json.loads(result)
assert payload["success"] is True
assert payload["subscribe"]["manual_total_episode"] == 1
assert oper.updates == [
(
160,
{
"total_episode": 190,
"lack_episode": 15,
"manual_total_episode": 1,
},
)
]
class _AgentSubscribe:
"""
最小订阅替身,模拟 Agent 工具依赖的订阅对象接口。