Merge pull request #1018 from liuyuexi1987/liuyuexi1987/p115-qrcode-login-docs

This commit is contained in:
jxxghp
2026-05-10 11:48:02 +08:00
committed by GitHub
6 changed files with 66 additions and 6 deletions

View File

@@ -2157,7 +2157,7 @@ class AgentResourceOfficer(_PluginBase):
elif cookie_state.get("configured"):
p115_ready = "已配置但不是扫码会话"
else:
p115_ready = "复用 115 助手客户端"
p115_ready = "未配置扫码会话,尝试复用 P115StrmHelper"
hdhive_summary = self._build_hdhive_page_summary()
feishu_health = self._ensure_feishu_channel().health()
feishu_state = "已启用" if feishu_health.get("enabled") else "未启用"
@@ -2252,6 +2252,9 @@ class AgentResourceOfficer(_PluginBase):
f"默认目录:{self._p115_default_path}",
f"登录方式:{p115_ready}",
f"扫码客户端:{self._p115_client_type_title(self._p115_client_type)}",
"智能体命令115登录 → 检查115登录",
"复用顺序:插件扫码会话 > P115StrmHelper",
"不复用MoviePilot 主程序 115 登录态",
],
"success" if p115_health_ok else "error",
)
@@ -2968,7 +2971,7 @@ class AgentResourceOfficer(_PluginBase):
"props": {
"type": "info",
"variant": "tonal",
"text": "115 建议走扫码会话,不建议填网页版 Cookie。插件支持 /p115/qrcode 和 /p115/qrcode/check 两步扫码登录;手填 Cookie 仅作为高级兜底",
"text": "115 登录用法:下面的扫码会话 Cookie 可以不填;不填写时,插件会先尝试复用 P115StrmHelper 的已登录客户端。如果没有安装 P115StrmHelper或复用不可用就在外部智能体或飞书里发送「115登录」智能体会返回二维码图片用 115 App 扫码确认后再发送「检查115登录」。插件暂不复用 MoviePilot 主程序 115 登录态。高级用户才需要手填 UID/CID/SEID 客户端 Cookie普通网页版 Cookie 不建议填写",
},
}
],

View File

@@ -2157,7 +2157,7 @@ class AgentResourceOfficer(_PluginBase):
elif cookie_state.get("configured"):
p115_ready = "已配置但不是扫码会话"
else:
p115_ready = "复用 115 助手客户端"
p115_ready = "未配置扫码会话,尝试复用 P115StrmHelper"
hdhive_summary = self._build_hdhive_page_summary()
feishu_health = self._ensure_feishu_channel().health()
feishu_state = "已启用" if feishu_health.get("enabled") else "未启用"
@@ -2252,6 +2252,9 @@ class AgentResourceOfficer(_PluginBase):
f"默认目录:{self._p115_default_path}",
f"登录方式:{p115_ready}",
f"扫码客户端:{self._p115_client_type_title(self._p115_client_type)}",
"智能体命令115登录 → 检查115登录",
"复用顺序:插件扫码会话 > P115StrmHelper",
"不复用MoviePilot 主程序 115 登录态",
],
"success" if p115_health_ok else "error",
)
@@ -2968,7 +2971,7 @@ class AgentResourceOfficer(_PluginBase):
"props": {
"type": "info",
"variant": "tonal",
"text": "115 建议走扫码会话,不建议填网页版 Cookie。插件支持 /p115/qrcode 和 /p115/qrcode/check 两步扫码登录;手填 Cookie 仅作为高级兜底",
"text": "115 登录用法:下面的扫码会话 Cookie 可以不填;不填写时,插件会先尝试复用 P115StrmHelper 的已登录客户端。如果没有安装 P115StrmHelper或复用不可用就在外部智能体或飞书里发送「115登录」智能体会返回二维码图片用 115 App 扫码确认后再发送「检查115登录」。插件暂不复用 MoviePilot 主程序 115 登录态。高级用户才需要手填 UID/CID/SEID 客户端 Cookie普通网页版 Cookie 不建议填写",
},
}
],

View File

@@ -2157,7 +2157,7 @@ class AgentResourceOfficer(_PluginBase):
elif cookie_state.get("configured"):
p115_ready = "已配置但不是扫码会话"
else:
p115_ready = "复用 115 助手客户端"
p115_ready = "未配置扫码会话,尝试复用 P115StrmHelper"
hdhive_summary = self._build_hdhive_page_summary()
feishu_health = self._ensure_feishu_channel().health()
feishu_state = "已启用" if feishu_health.get("enabled") else "未启用"
@@ -2252,6 +2252,9 @@ class AgentResourceOfficer(_PluginBase):
f"默认目录:{self._p115_default_path}",
f"登录方式:{p115_ready}",
f"扫码客户端:{self._p115_client_type_title(self._p115_client_type)}",
"智能体命令115登录 → 检查115登录",
"复用顺序:插件扫码会话 > P115StrmHelper",
"不复用MoviePilot 主程序 115 登录态",
],
"success" if p115_health_ok else "error",
)
@@ -2968,7 +2971,7 @@ class AgentResourceOfficer(_PluginBase):
"props": {
"type": "info",
"variant": "tonal",
"text": "115 建议走扫码会话,不建议填网页版 Cookie。插件支持 /p115/qrcode 和 /p115/qrcode/check 两步扫码登录;手填 Cookie 仅作为高级兜底",
"text": "115 登录用法:下面的扫码会话 Cookie 可以不填;不填写时,插件会先尝试复用 P115StrmHelper 的已登录客户端。如果没有安装 P115StrmHelper或复用不可用就在外部智能体或飞书里发送「115登录」智能体会返回二维码图片用 115 App 扫码确认后再发送「检查115登录」。插件暂不复用 MoviePilot 主程序 115 登录态。高级用户才需要手填 UID/CID/SEID 客户端 Cookie普通网页版 Cookie 不建议填写",
},
}
],

View File

@@ -128,6 +128,8 @@ MCP 地址http://你的NAS地址:3000/api/v1/mcp
完整命令列表见 [ALL_COMMANDS.md](../../docs/ALL_COMMANDS.md)。
`115登录` 是一个容易被长线程摘要掉的命令:如果 helper 返回二维码图片路径或 Markdown 图片,外部智能体必须原样展示给用户,不能只说“二维码已生成”。用户扫码后,再回复 `检查115登录` 完成验证。
---
## MCP 要不要接

View File

@@ -80,6 +80,7 @@ Core rules:
- `1详情` and similar variants must preserve detail intent. Never collapse them into `1` or `选择 1`.
- Before confirming PT download execution, make sure the connected MoviePilot is the real download instance, not a cloud-drive/STRM-only instance.
- If the user says `校准影视技能`, run `python3 scripts/aro_request.py calibrate` or `python3 scripts/aro_request.py route "校准影视技能"` first, apply the returned hard rules to the current session, then reply only `影视技能已校准。`.
- If the user says `115登录`, route it through the helper and preserve the helper output exactly. When the helper prints a QR image path or Markdown image such as `![115扫码二维码](...)`, show it to the user; do not summarize it into plain text or drop the image/path. After the user scans, tell them to reply `检查115登录`.
- For explicit title searches such as `MP 搜索 罪无可逃`, the first and only initial action is helper `route "<原话>" --session <session>`. Do not pre-call TMDB, MCP search, raw MoviePilot API, or torrent search before that helper route.
Environment overrides:

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import argparse
import base64
import json
import os
import subprocess
@@ -880,6 +881,50 @@ def print_json(data):
print(json.dumps(data, ensure_ascii=False, indent=2))
def qrcode_payload(data):
if not isinstance(data, dict):
return {}
payload = data.get("data") if isinstance(data.get("data"), dict) else data
qrcode = str((payload or {}).get("qrcode") or "")
if qrcode.startswith("data:image/") and ";base64," in qrcode:
return payload
return {}
def write_qrcode_image(payload):
qrcode = str((payload or {}).get("qrcode") or "")
if not qrcode.startswith("data:image/") or ";base64," not in qrcode:
return ""
header, encoded = qrcode.split(",", 1)
suffix = ".png"
if "image/jpeg" in header or "image/jpg" in header:
suffix = ".jpg"
safe_uid = "".join(ch for ch in str(payload.get("uid") or "qrcode") if ch.isalnum() or ch in {"-", "_"})[:48]
output_dir = "/tmp/agent-resource-officer"
os.makedirs(output_dir, exist_ok=True)
path = os.path.join(output_dir, f"p115-login-{safe_uid or 'qrcode'}{suffix}")
with open(path, "wb") as f:
f.write(base64.b64decode(encoded))
return path
def print_qrcode_message(result):
payload = qrcode_payload(result)
if not payload:
return False
image_path = write_qrcode_image(payload)
message = str((result or {}).get("message") or "").strip()
if message:
print(message)
if image_path:
print("")
print(f"二维码图片:{image_path}")
print(f"![115扫码二维码]({image_path})")
print("")
print("扫码确认后回复检查115登录")
return True
def summary_command(summary, confirmed=False):
summary = summary or {}
explicit_behavior = str(summary.get("recommended_agent_behavior") or "").strip()
@@ -1222,6 +1267,7 @@ def calibration_payload():
"MP搜索/PT搜索 后面带 给我最新集、最新集、最新一集 时,仍然原样 route插件会只展示最高集数候选不要把上一批旧集数混回摘要。",
"MP搜索/PT搜索/下载 后面带 第4集、第四集、E04、S01E04 时,仍然原样 route插件会只展示包含该目标集的候选并安全重编号。",
"MP搜索/PT搜索 最新集 如果先返回影片候选,后续编号必须继续使用同一个 helper session不要新开会话裸跑 route \"1\",否则会丢失最新集过滤上下文。",
"115登录 必须原样展示 helper 输出中的二维码图片路径或 Markdown 图片;不能摘要成“二维码已生成”后吞掉图片。扫码后让用户回复 检查115登录。",
"下载/MP搜索/PT搜索 返回 PT 资源列表时,必须原样展示插件 message 里的编号资源不要压缩成“PT资源已列出”。",
"MP/PT 结果列表不能重新编号;插件返回 2、4、21、29 就原样显示并用这些编号继续选择/下载,不能改成 1、2、3、4也不要追加自己的选择提示尾巴。",
"编号详情、15详情、十六详情、选择 15 详情 = 只读详情,不能执行转存或下载。",
@@ -2534,6 +2580,8 @@ def main():
return 0
output = result if args.full else compact(result)
if args.command in {"route", "pick"} and not args.full and not args.json_output:
if print_qrcode_message(result):
return 0 if (result or {}).get("success", True) else 2
message = str((output or {}).get("message") or "").strip() if isinstance(output, dict) else ""
if message:
print(message)