XHS / extension /background.js
Trae Bot
Upload Spider_XHS project
c481f8a
const getActiveTab = () =>
new Promise((resolve) => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => resolve(tabs && tabs[0] ? tabs[0] : null));
});
const storageGet = (keys) =>
new Promise((resolve) => {
chrome.storage.local.get(keys, (items) => resolve(items || {}));
});
const storageSet = (items) =>
new Promise((resolve) => {
chrome.storage.local.set(items, () => resolve());
});
const sendToTab = (tabId, message) =>
new Promise((resolve, reject) => {
chrome.tabs.sendMessage(tabId, message, (resp) => {
const err = chrome.runtime.lastError;
if (err) {
reject(new Error(err.message));
return;
}
resolve(resp);
});
});
const badge = async (text) => {
try {
await chrome.action.setBadgeBackgroundColor({ color: "#2D7D46" });
await chrome.action.setBadgeText({ text: text || "" });
} catch (e) {}
};
const badgeError = async (text) => {
try {
await chrome.action.setBadgeBackgroundColor({ color: "#B42318" });
await chrome.action.setBadgeText({ text: text || "" });
} catch (e) {}
};
const normalizeBaseUrl = (url) => {
const u = String(url || "").trim();
if (!u) return "";
return u.endsWith("/") ? u.slice(0, -1) : u;
};
const extractTaskId = (text) => {
const t = String(text || "").trim();
if (!t) return "";
const m = t.match(/[0-9a-fA-F]{32}/);
return m ? m[0] : t;
};
const getOrPromptServiceUrl = async (tabId) => {
const items = await storageGet(["service_url"]);
const existing = normalizeBaseUrl(items.service_url);
if (existing) return existing;
const resp = await sendToTab(tabId, {
type: "PROMPT",
text: "Spider_XHS 服务地址(例如 http://localhost:8000)",
defaultValue: "http://localhost:8000",
});
const v = normalizeBaseUrl(resp && resp.value);
if (v) await storageSet({ service_url: v });
return v;
};
const getTaskId = async (tabId) => {
let clip = "";
try {
const resp = await sendToTab(tabId, { type: "READ_CLIPBOARD" });
clip = extractTaskId(resp && resp.text);
} catch (e) {}
if (clip) return clip;
const resp = await sendToTab(tabId, { type: "PROMPT", text: "task_id", defaultValue: "" });
return extractTaskId(resp && resp.value);
};
const collectPage = async (tabId) => {
const resp = await sendToTab(tabId, { type: "COLLECT_PAGE" });
return resp || {};
};
chrome.action.onClicked.addListener(async () => {
await badge("...");
try {
const tab = await getActiveTab();
const tabId = tab && tab.id;
if (!tabId) {
await badgeError("NO");
return;
}
const serviceUrl = await getOrPromptServiceUrl(tabId);
if (!serviceUrl) {
await badgeError("URL");
return;
}
const taskId = await getTaskId(tabId);
if (!taskId) {
await badgeError("ID");
return;
}
const page = await collectPage(tabId);
const url = String(page.url || "").trim();
const html = String(page.html || "");
const body = {
task_id: taskId,
raw: { url, html },
normalized: { url, kind: "page" },
meta: { source_engine: "extension_rpa", source_type: "page", source_ref: url, ingested_at: new Date().toISOString(), ok: true },
};
const endpoint = `${serviceUrl}/api/v1/import/extension`;
const resp = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (resp.ok) {
await badge("OK");
} else {
await badgeError(String(resp.status || "ERR"));
}
} catch (e) {
await badgeError("ERR");
} finally {
setTimeout(() => badge(""), 2000);
}
});