fix: harden douyin control panel auth inputs

This commit is contained in:
kris
2026-03-20 23:31:27 +08:00
parent 5d9c9cf048
commit 741fe4f983

View File

@@ -151,6 +151,9 @@ function getActiveRun() {
}
function buildCaptureArgs(payload, runBaseDir, readyFile) {
const token = String(payload.token || payload.storyforgeToken || "").trim();
const username = String(payload.username || payload.storyforgeUsername || "").trim();
const password = String(payload.password || payload.storyforgePassword || "");
const parsedMaxVideos = Number.parseInt(String(payload.maxVideos ?? "4"), 10);
const parsedWaitMs = Number.parseInt(String(payload.waitMs ?? "4000"), 10);
const args = [
@@ -185,23 +188,26 @@ function buildCaptureArgs(payload, runBaseDir, readyFile) {
if (payload.allowCreatorCenterFallback) {
args.push("--allow-creator-center-fallback");
}
if (payload.token) {
args.push("--storyforge-token", String(payload.token).trim());
if (token) {
args.push("--storyforge-token", token);
} else if (payload.syncEnabled) {
args.push("--storyforge-username", String(payload.username || "").trim());
args.push("--storyforge-password", String(payload.password || ""));
args.push("--storyforge-username", username);
args.push("--storyforge-password", password);
}
return args;
}
async function startRun(payload) {
const profileUrl = String(payload.profileUrl || "").trim();
const token = String(payload.token || payload.storyforgeToken || "").trim();
const username = String(payload.username || payload.storyforgeUsername || "").trim();
const password = String(payload.password || payload.storyforgePassword || "");
if (!profileUrl) {
throw new Error("请先填写抖音主页链接");
}
const syncEnabled = payload.syncEnabled !== false;
if (syncEnabled && !String(payload.token || "").trim()) {
if (!String(payload.username || "").trim() || !String(payload.password || "")) {
if (syncEnabled && !token) {
if (!username || !password) {
throw new Error("导入 StoryForge 时需要账号密码,或者直接提供 Token");
}
}
@@ -525,12 +531,12 @@ function renderPage() {
<form id="capture-form" class="stack">
<label>
抖音主页链接
<input id="profile-url" name="profileUrl" placeholder="https://www.douyin.com/user/..." required />
<input id="profile-url" name="profileUrl" placeholder="https://www.douyin.com/user/..." autocomplete="url" required />
</label>
<div class="row">
<label>
StoryForge 地址
<input id="backend-url" name="backendUrl" value="${DEFAULT_BACKEND_URL}" />
<input id="backend-url" name="backendUrl" value="${DEFAULT_BACKEND_URL}" autocomplete="url" />
</label>
<label>
备注
@@ -540,11 +546,11 @@ function renderPage() {
<div class="row">
<label>
StoryForge 用户名
<input id="username" name="username" placeholder="kris" />
<input id="username" name="username" placeholder="kris" autocomplete="username" />
</label>
<label>
StoryForge 密码
<input id="password" name="password" type="password" placeholder="用于自动导入时登录" />
<input id="password" name="password" type="password" placeholder="用于自动导入时登录" autocomplete="current-password" />
</label>
</div>
<div class="row">
@@ -605,6 +611,7 @@ function renderPage() {
const continueButton = document.getElementById("continue-button");
const refreshButton = document.getElementById("refresh-button");
const form = document.getElementById("capture-form");
const storageKey = "storyforge-douyin-control-panel";
let activeRunId = "";
function escapeHtml(value) {
@@ -666,6 +673,36 @@ function renderPage() {
renderRecentRuns(payload.recentRuns || []);
}
function loadSavedValues() {
try {
const saved = JSON.parse(localStorage.getItem(storageKey) || "{}");
if (saved.profileUrl) document.getElementById("profile-url").value = saved.profileUrl;
if (saved.backendUrl) document.getElementById("backend-url").value = saved.backendUrl;
if (saved.username) document.getElementById("username").value = saved.username;
if (saved.note) document.getElementById("note").value = saved.note;
if (saved.maxVideos !== undefined) document.getElementById("max-videos").value = saved.maxVideos;
if (saved.syncEnabled !== undefined) document.getElementById("sync-enabled").checked = Boolean(saved.syncEnabled);
if (saved.headless !== undefined) document.getElementById("headless").checked = Boolean(saved.headless);
if (saved.skipCreatorCenter !== undefined) document.getElementById("skip-creator-center").checked = Boolean(saved.skipCreatorCenter);
if (saved.allowCreatorCenterFallback !== undefined) document.getElementById("allow-fallback").checked = Boolean(saved.allowCreatorCenterFallback);
} catch {}
}
function saveValues(payload) {
const saved = {
profileUrl: payload.profileUrl,
backendUrl: payload.backendUrl,
username: payload.username,
note: payload.note,
maxVideos: payload.maxVideos,
syncEnabled: payload.syncEnabled,
headless: payload.headless,
skipCreatorCenter: payload.skipCreatorCenter,
allowCreatorCenterFallback: payload.allowCreatorCenterFallback
};
localStorage.setItem(storageKey, JSON.stringify(saved));
}
form.addEventListener("submit", async (event) => {
event.preventDefault();
const payload = {
@@ -673,7 +710,10 @@ function renderPage() {
backendUrl: document.getElementById("backend-url").value.trim(),
username: document.getElementById("username").value.trim(),
password: document.getElementById("password").value,
storyforgeUsername: document.getElementById("username").value.trim(),
storyforgePassword: document.getElementById("password").value,
token: document.getElementById("token").value.trim(),
storyforgeToken: document.getElementById("token").value.trim(),
note: document.getElementById("note").value.trim(),
maxVideos: document.getElementById("max-videos").value,
syncEnabled: document.getElementById("sync-enabled").checked,
@@ -681,6 +721,11 @@ function renderPage() {
skipCreatorCenter: document.getElementById("skip-creator-center").checked,
allowCreatorCenterFallback: document.getElementById("allow-fallback").checked
};
if (payload.syncEnabled && !payload.token && (!payload.username || !payload.password)) {
alert("当前页面没有读到 StoryForge 账号或密码。请重新输入,或直接填 Token。");
return;
}
saveValues(payload);
const response = await fetch("/api/start", {
method: "POST",
headers: { "content-type": "application/json" },
@@ -710,6 +755,7 @@ function renderPage() {
});
refreshButton.addEventListener("click", refreshStatus);
loadSavedValues();
refreshStatus();
setInterval(refreshStatus, 1500);
</script>