152 lines
5.2 KiB
JavaScript
152 lines
5.2 KiB
JavaScript
function setStatus(message) {
|
||
document.getElementById("status").textContent = message;
|
||
}
|
||
|
||
async function getActiveTab() {
|
||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||
if (!tab?.id) {
|
||
throw new Error("No readable active tab found.");
|
||
}
|
||
return tab;
|
||
}
|
||
|
||
async function captureFromActiveTab(tabId) {
|
||
const [result] = await chrome.scripting.executeScript({
|
||
target: { tabId },
|
||
func: deerExtractCurrentPage,
|
||
});
|
||
if (!result?.result?.content) {
|
||
throw new Error("The current page has no readable text to send.");
|
||
}
|
||
return result.result;
|
||
}
|
||
|
||
async function submitToZncm(page, settings, prompt) {
|
||
const apiBaseUrl = deerNormalizeBaseUrl(settings.apiBaseUrl || DEER_CLIPPER_DEFAULTS.apiBaseUrl);
|
||
const response = await fetch(`${apiBaseUrl}/api/browser-context/capture`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
...deerAuthHeaders(settings),
|
||
},
|
||
body: JSON.stringify({
|
||
title: page.title,
|
||
url: page.url,
|
||
content: page.content,
|
||
content_type: page.contentType,
|
||
prompt,
|
||
}),
|
||
});
|
||
|
||
const data = await response.json().catch(() => ({}));
|
||
if (!response.ok) {
|
||
const detail = typeof data.detail === "string" ? data.detail : JSON.stringify(data.detail || data);
|
||
throw new Error(detail || `HTTP ${response.status}`);
|
||
}
|
||
return data;
|
||
}
|
||
|
||
async function sendCurrentPage() {
|
||
const sendButton = document.getElementById("send");
|
||
sendButton.disabled = true;
|
||
setStatus("正在读取当前页面...");
|
||
try {
|
||
await syncToken({ silent: true });
|
||
const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS);
|
||
const prompt = document.getElementById("prompt").value.trim() || settings.defaultPrompt || DEER_CLIPPER_DEFAULT_PROMPT;
|
||
const tab = await getActiveTab();
|
||
const page = await captureFromActiveTab(tab.id);
|
||
setStatus("正在发送到 zncm...");
|
||
const result = await submitToZncm(page, settings, prompt);
|
||
const webBaseUrl = deerNormalizeBaseUrl(settings.webBaseUrl || DEER_CLIPPER_DEFAULTS.webBaseUrl);
|
||
await chrome.tabs.create({ url: `${webBaseUrl}/${result.chat_url}`.replace(/\/#/g, "/#") });
|
||
setStatus("已发送,zncm 聊天页面已打开。");
|
||
} catch (error) {
|
||
setStatus(error instanceof Error ? error.message : "发送失败。");
|
||
} finally {
|
||
sendButton.disabled = false;
|
||
}
|
||
}
|
||
|
||
function sendSyncTokenMessage() {
|
||
return new Promise((resolve, reject) => {
|
||
chrome.runtime.sendMessage({ type: "zncm-sync-token" }, (response) => {
|
||
const error = chrome.runtime.lastError;
|
||
if (error) {
|
||
reject(new Error(error.message));
|
||
return;
|
||
}
|
||
resolve(response || { ok: false, message: "Token 同步没有返回结果。" });
|
||
});
|
||
});
|
||
}
|
||
|
||
function sendPollNowMessage() {
|
||
return new Promise((resolve, reject) => {
|
||
chrome.runtime.sendMessage({ type: "zncm-poll-now" }, (response) => {
|
||
const error = chrome.runtime.lastError;
|
||
if (error) {
|
||
reject(new Error(error.message));
|
||
return;
|
||
}
|
||
resolve(response || { ok: true, message: "Poll requested." });
|
||
});
|
||
});
|
||
}
|
||
|
||
async function syncToken(options = {}) {
|
||
const button = document.getElementById("syncToken");
|
||
button.disabled = true;
|
||
if (!options.silent) {
|
||
setStatus("正在同步 zncm token...");
|
||
}
|
||
try {
|
||
const response = await sendSyncTokenMessage();
|
||
if (!options.silent) {
|
||
setStatus(response.message || "Token sync finished.");
|
||
}
|
||
return response;
|
||
} catch (error) {
|
||
if (!options.silent) {
|
||
setStatus(error instanceof Error ? error.message : "Token 同步失败。");
|
||
}
|
||
return { ok: false, message: error instanceof Error ? error.message : "Token 同步失败。" };
|
||
} finally {
|
||
button.disabled = false;
|
||
}
|
||
}
|
||
|
||
async function pollNow() {
|
||
const button = document.getElementById("pollNow");
|
||
button.disabled = true;
|
||
setStatus("正在检查 zncm 浏览器任务...");
|
||
try {
|
||
await syncToken({ silent: true });
|
||
const response = await sendPollNowMessage();
|
||
setStatus(response.message || "任务检查完成。");
|
||
} catch (error) {
|
||
setStatus(error instanceof Error ? error.message : "任务检查失败。");
|
||
} finally {
|
||
button.disabled = false;
|
||
}
|
||
}
|
||
|
||
async function togglePageAssistant() {
|
||
const enabled = document.getElementById("pageAssistantEnabled").checked;
|
||
await chrome.storage.sync.set({ pageAssistantEnabled: enabled });
|
||
setStatus(enabled ? "页面问答框已开启。" : "页面问答框已关闭。");
|
||
}
|
||
|
||
async function init() {
|
||
const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS);
|
||
document.getElementById("prompt").value = settings.defaultPrompt || DEER_CLIPPER_DEFAULT_PROMPT;
|
||
document.getElementById("pageAssistantEnabled").checked = Boolean(settings.pageAssistantEnabled);
|
||
document.getElementById("send").addEventListener("click", sendCurrentPage);
|
||
document.getElementById("syncToken").addEventListener("click", () => syncToken());
|
||
document.getElementById("pollNow").addEventListener("click", pollNow);
|
||
document.getElementById("pageAssistantEnabled").addEventListener("change", togglePageAssistant);
|
||
document.getElementById("options").addEventListener("click", () => chrome.runtime.openOptionsPage());
|
||
}
|
||
|
||
void init();
|