function cleanText(value) { return String(value || '') .replace(/\s+/g, ' ') .replace(/\u200b/g, '') .trim(); } function pageText() { const body = document.body; return cleanText(body && (body.innerText || body.textContent || '')); } function isLoginBlocked(url, text) { return /\/signin\b|\/signup\b/.test(url) || /登录|注册|验证码|安全验证|验证后继续|请先登录/.test(text); } function isVisible(node) { if (!node) { return false; } const rect = typeof node.getBoundingClientRect === 'function' ? node.getBoundingClientRect() : null; return !rect || rect.width > 0 || rect.height > 0; } function attrText(node, name) { if (!node || typeof node.getAttribute !== 'function') { return ''; } return cleanText(node.getAttribute(name) || ''); } function looksLikeTitleInput(node) { const signals = [ attrText(node, 'placeholder'), attrText(node, 'data-placeholder'), attrText(node, 'aria-label'), ].filter(Boolean); return signals.some((value) => value.includes('标题')); } function dispatchTextInput(node) { node.dispatchEvent(new Event('input', { bubbles: true, composed: true })); node.dispatchEvent(new Event('change', { bubbles: true, composed: true })); } function fillInput(node, value) { node.focus(); if ('value' in node) { node.value = ''; dispatchTextInput(node); node.value = value; dispatchTextInput(node); return; } node.textContent = value; dispatchTextInput(node); } function fillEditable(node, value) { node.focus(); node.innerHTML = ''; const lines = String(value || '').split(/\n/); lines.forEach((line, index) => { if (index > 0) { node.appendChild(document.createElement('br')); } node.appendChild(document.createTextNode(line)); }); dispatchTextInput(node); } function findVisible(selectors) { for (const selector of selectors) { const nodes = Array.from(document.querySelectorAll(selector)); const match = nodes.find((node) => { return isVisible(node); }); if (match) { return match; } } return null; } function findBodyEditor(titleInput) { for (const selector of [ "div[contenteditable='true'][role='textbox']", "div.public-DraftEditor-content[contenteditable='true']", "[role='textbox'][contenteditable='true']", "[contenteditable='true'][data-placeholder]", "div[contenteditable='true']", ]) { const nodes = Array.from(document.querySelectorAll(selector)); const match = nodes.find((node) => isVisible(node) && node !== titleInput && !looksLikeTitleInput(node)); if (match) { return match; } } return null; } function findButtonByText(fragment) { const candidates = Array.from(document.querySelectorAll("button, [role='button'], a")); const wanted = cleanText(fragment); return candidates.find((node) => { const text = cleanText(node.textContent); if (!text || !text.includes(wanted)) { return false; } return isVisible(node); }) || null; } const currentUrl = location.href; const text = pageText(); if (isLoginBlocked(currentUrl, text)) { return { status: 'login_required', current_url: currentUrl, }; } const titleInput = findVisible([ "textarea[placeholder*='标题']", "input[placeholder*='标题']", "textarea[data-placeholder*='标题']", "input[data-placeholder*='标题']", "[role='textbox'][aria-label*='标题']", "[contenteditable='true'][aria-label*='标题']", "[contenteditable='true'][data-placeholder*='标题']", ]); const bodyEditor = findBodyEditor(titleInput); if (!titleInput || !bodyEditor) { return { status: 'editor_not_ready', current_url: currentUrl, }; } fillInput(titleInput, String(args.title || '')); fillEditable(bodyEditor, String(args.body || '')); const publishMode = String(args.publish_mode || '').toLowerCase() === 'true'; if (!publishMode) { return { status: 'draft_ready', current_url: currentUrl, title: cleanText(args.title), }; } const publishButton = findButtonByText('发布'); if (!publishButton) { return { status: 'publish_button_missing', current_url: currentUrl, title: cleanText(args.title), }; } publishButton.click(); const confirmButton = findButtonByText('确认发布'); if (!confirmButton) { return { status: 'publish_clicked', current_url: currentUrl, title: cleanText(args.title), }; } confirmButton.click(); return { status: 'publish_submitted', current_url: currentUrl, title: cleanText(args.title), };