83 lines
2.4 KiB
JavaScript
83 lines
2.4 KiB
JavaScript
/** @typedef {{ name: string; value: string; domain: string; path: string; expires: number; httpOnly: boolean; secure: boolean; sameSite: string }} PlaywrightCookie */
|
|
|
|
const COOKIE_DOMAINS = ["threads.com", "instagram.com", "facebook.com"];
|
|
|
|
function mapSameSite(sameSite) {
|
|
if (sameSite === "no_restriction") return "None";
|
|
if (sameSite === "lax") return "Lax";
|
|
if (sameSite === "strict") return "Strict";
|
|
return "Lax";
|
|
}
|
|
|
|
/** @param {chrome.cookies.Cookie} cookie */
|
|
function toPlaywrightCookie(cookie) {
|
|
return {
|
|
name: cookie.name,
|
|
value: cookie.value,
|
|
domain: cookie.domain,
|
|
path: cookie.path || "/",
|
|
expires: cookie.expirationDate ?? -1,
|
|
httpOnly: cookie.httpOnly ?? false,
|
|
secure: cookie.secure ?? false,
|
|
sameSite: mapSameSite(cookie.sameSite),
|
|
};
|
|
}
|
|
|
|
export async function collectThreadsCookies() {
|
|
/** @type {PlaywrightCookie[]} */
|
|
const merged = [];
|
|
const seen = new Set();
|
|
|
|
for (const domain of COOKIE_DOMAINS) {
|
|
const batch = await chrome.cookies.getAll({ domain });
|
|
for (const cookie of batch) {
|
|
const key = `${cookie.domain}|${cookie.path}|${cookie.name}`;
|
|
if (seen.has(key)) continue;
|
|
seen.add(key);
|
|
merged.push(toPlaywrightCookie(cookie));
|
|
}
|
|
}
|
|
|
|
return merged;
|
|
}
|
|
|
|
export async function collectThreadsLocalStorage() {
|
|
const tabs = await chrome.tabs.query({
|
|
url: ["https://www.threads.com/*", "https://threads.com/*", "https://www.threads.net/*"],
|
|
});
|
|
|
|
if (!tabs.length || tabs[0].id == null) {
|
|
return [];
|
|
}
|
|
|
|
const [injection] = await chrome.scripting.executeScript({
|
|
target: { tabId: tabs[0].id },
|
|
func: () => {
|
|
const localStorageItems = [];
|
|
for (let i = 0; i < localStorage.length; i += 1) {
|
|
const name = localStorage.key(i);
|
|
if (!name) continue;
|
|
localStorageItems.push({ name, value: localStorage.getItem(name) ?? "" });
|
|
}
|
|
return { origin: location.origin, localStorage: localStorageItems };
|
|
},
|
|
});
|
|
|
|
const payload = injection?.result;
|
|
if (!payload || !Array.isArray(payload.localStorage)) {
|
|
return [];
|
|
}
|
|
|
|
return [payload];
|
|
}
|
|
|
|
export async function buildStorageState() {
|
|
const cookies = await collectThreadsCookies();
|
|
const origins = await collectThreadsLocalStorage();
|
|
|
|
if (!cookies.length) {
|
|
throw new Error("找不到 Threads / Instagram cookies。請先在 Chrome 登入 threads.com");
|
|
}
|
|
|
|
return JSON.stringify({ cookies, origins });
|
|
} |