Commit 55ca6d6f authored by 郭阔's avatar 郭阔

feat: one-click recipe auto-discovery from the panel

- nh_login_autodiscover (platform.sh): ensure the source's dedicated
  browser instance is up, load credentials, run skill discover
  (recipe generation + live login verification)
- /login-discover route + 自动配置配方并测试 button for sources with
  credentials but no recipe; reuses the background-test polling UI
parent 88a67a5f
......@@ -410,6 +410,26 @@ nh_login_preflight() { # <source>
return 0
}
nh_login_autodiscover() { # <source> 自动发现登录流程生成配方,并立即实登验证
local source="$1" creds tools_dir
creds="$CONF_DIR/logins/${source}.json"
[ -f "$creds" ] || { echo "❌ 未配置 $source 的凭据(看板「站点登录」页维护)" >&2; return 1; }
tools_dir="$(nh_skill_dir)"
[ -f "$tools_dir/scripts/login-tools.js" ] || { echo "❌ 技能缺少 login-tools.js" >&2; return 1; }
[ -f "$tools_dir/scripts/ensure-chromium.js" ] && {
# 确保该源的专属浏览器实例在线(darwin 隔离布局)
(cd "$tools_dir" && { [ -z "${CDP_PORT_OVERRIDE:-}" ] && nh_is_darwin && export CDP_PORT_OVERRIDE="$(nh_cdp_port "$source")" CDP_PROFILE_OVERRIDE="$HOME/.news-harvester/profiles/${source}"; \
node scripts/ensure-chromium.js >/dev/null 2>&1; })
}
if nh_is_darwin && [ -z "${CDP_PORT_OVERRIDE:-}" ]; then
export CDP_PORT_OVERRIDE="$(nh_cdp_port "$source")"
export CDP_PROFILE_OVERRIDE="$HOME/.news-harvester/profiles/${source}"
fi
export NH_LOGIN_USER="$(jq -r '.user // empty' "$creds" 2>/dev/null)"
export NH_LOGIN_PASS="$(jq -r '.password // empty' "$creds" 2>/dev/null)"
(cd "$tools_dir" && node scripts/login-tools.js discover "$source")
}
# --- CLI 派发(python 面板等外部调用):platform.sh call <函数> [参数...] ---
# 例:platform.sh call nh_schedule_enable wsj
if [ "${1:-}" = "call" ]; then
......
......@@ -1023,6 +1023,36 @@ def login_delete(source):
return redirect(url_for("login_list"))
@app.route("/login-discover/<source>", methods=["POST"])
@require_auth
def login_discover(source):
"""自动发现登录流程生成配方,并立即实登验证(后台线程,页面轮询)。"""
if not re.match(r"^[a-zA-Z0-9_-]+$", source):
abort(404)
if not pl.get_logins().get(source, {}).get("configured"):
flash(f"{source} 未配置凭据,请先在下方表单保存", "error")
return redirect(url_for("login_list"))
with _login_test_lock:
if _login_test.get(source, {}).get("running"):
flash(f"{source} 已有登录测试在运行", "error")
return redirect(url_for("login_list"))
_login_test[source] = {"running": True, "done": False, "start":
datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
def _run():
rc, out, err = call_platform("nh_login_autodiscover", source)
with _login_test_lock:
_login_test[source] = {
"running": False, "done": True, "rc": rc,
"output": ((out or "") + (("\n" + err) if err else ""))[-2000:],
"start": _login_test[source]["start"],
}
threading.Thread(target=_run, daemon=True).start()
flash(f"{source} 自动配置配方并测试已启动(约 30-90 秒,页面自动刷新)", "success")
return redirect(url_for("login_list"))
@app.route("/login-test/<source>", methods=["POST"])
@require_auth
def login_test(source):
......
......@@ -34,7 +34,7 @@
</td>
<td>
{% if r.has_recipe %}<span class="badge ok">支持</span>
{% else %}<span class="badge unknown">无配方(仅保存凭据)</span>{% endif %}
{% else %}<span class="badge unknown">无配方(点右侧按钮自动生成)</span>{% endif %}
</td>
<td>
{% set st = test_state.get(r.source) %}
......@@ -56,6 +56,11 @@
<form method="POST" action="{{ url_for('login_test', source=r.source) }}" style="display:inline">
<button type="submit" class="btn btn-sm" {% if st and st.running %}disabled{% endif %}>测试登录</button>
</form>
{% elif r.configured %}
<form method="POST" action="{{ url_for('login_discover', source=r.source) }}" style="display:inline"
onsubmit="return confirm('自动识别 {{ r.source }} 的登录流程并生成配方,随后立即用凭据实登验证?')">
<button type="submit" class="btn btn-sm btn-primary" {% if st and st.running %}disabled{% endif %}>自动配置配方并测试</button>
</form>
{% endif %}
<button class="btn btn-sm" onclick="fillForm('{{ r.source }}', '{{ r.url }}', '{{ r.user }}')">编辑</button>
<form method="POST" action="{{ url_for('login_delete', source=r.source) }}" style="display:inline"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment