import GuJumpgate snapshot from GitHub

This commit is contained in:
2026-05-20 20:33:51 +08:00
commit f8903dcd14
335 changed files with 179790 additions and 0 deletions
@@ -0,0 +1,375 @@
(function attachBackgroundStep6(root, factory) {
root.MultiPageBackgroundStep6 = factory();
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundStep6Module() {
const DEFAULT_REGISTRATION_SUCCESS_WAIT_MS = 4000;
const LOCAL_CPA_JSON_NO_RT_PANEL_MODE = 'local-cpa-json-no-rt';
const LOCAL_CPA_JSON_EXPORT_NODE_ID = 'local-cpa-json-export';
const CHATGPT_SESSION_EXPORT_URL = 'https://chatgpt.com/';
const STEP6_COOKIE_CLEAR_DOMAINS = [
'chatgpt.com',
'chat.openai.com',
'pay.openai.com',
'openai.com',
'auth.openai.com',
'auth0.openai.com',
'accounts.openai.com',
'paypal.com',
'stripe.com',
'checkout.stripe.com',
'meiguodizhi.com',
'mail-api.yuecheng.shop',
'yuecheng.shop',
];
const STEP6_COOKIE_CLEAR_ORIGINS = [
'https://chatgpt.com',
'https://chat.openai.com',
'https://pay.openai.com',
'https://auth.openai.com',
'https://auth0.openai.com',
'https://accounts.openai.com',
'https://openai.com',
'https://www.paypal.com',
'https://paypal.com',
'https://checkout.stripe.com',
'https://www.meiguodizhi.com',
'https://meiguodizhi.com',
'https://mail-api.yuecheng.shop',
];
function normalizeStep6CookieDomain(domain) {
return String(domain || '').trim().replace(/^\.+/, '').toLowerCase();
}
function shouldClearStep6Cookie(cookie) {
const domain = normalizeStep6CookieDomain(cookie?.domain);
if (!domain) return false;
return STEP6_COOKIE_CLEAR_DOMAINS.some((target) => (
domain === target || domain.endsWith(`.${target}`)
));
}
function buildStep6CookieRemovalUrl(cookie) {
const host = normalizeStep6CookieDomain(cookie?.domain);
const rawPath = String(cookie?.path || '/');
const path = rawPath.startsWith('/') ? rawPath : `/${rawPath}`;
return `https://${host}${path}`;
}
async function collectStep6Cookies(chromeApi) {
if (!chromeApi.cookies?.getAll) {
return [];
}
const stores = chromeApi.cookies.getAllCookieStores
? await chromeApi.cookies.getAllCookieStores()
: [{ id: undefined }];
const cookies = [];
const seen = new Set();
for (const store of stores) {
const storeId = store?.id;
const batch = await chromeApi.cookies.getAll(storeId ? { storeId } : {});
for (const cookie of batch || []) {
if (!shouldClearStep6Cookie(cookie)) continue;
const key = [
cookie.storeId || storeId || '',
cookie.domain || '',
cookie.path || '',
cookie.name || '',
cookie.partitionKey ? JSON.stringify(cookie.partitionKey) : '',
].join('|');
if (seen.has(key)) continue;
seen.add(key);
cookies.push(cookie);
}
}
return cookies;
}
async function removeStep6Cookie(chromeApi, cookie, getErrorMessage) {
const details = {
url: buildStep6CookieRemovalUrl(cookie),
name: cookie.name,
};
if (cookie.storeId) {
details.storeId = cookie.storeId;
}
if (cookie.partitionKey) {
details.partitionKey = cookie.partitionKey;
}
try {
const result = await chromeApi.cookies.remove(details);
return Boolean(result);
} catch (error) {
console.warn('[MultiPage:step6] remove cookie failed', {
domain: cookie?.domain,
name: cookie?.name,
message: getErrorMessage(error),
});
return false;
}
}
function createStep6Executor(deps = {}) {
const {
addLog = async () => {},
buildLocalHelperEndpoint = null,
chrome: chromeApi = globalThis.chrome,
completeNodeFromBackground,
createLocalCliProxyApi = null,
ensureContentScriptReadyOnTab = async () => {},
getErrorMessage = (error) => error?.message || String(error || '未知错误'),
getPanelMode = (state = {}) => String(state?.panelMode || '').trim() || 'cpa',
getTabId = async () => null,
normalizeHotmailLocalBaseUrl = (value) => String(value || '').trim(),
registrationSuccessWaitMs = DEFAULT_REGISTRATION_SUCCESS_WAIT_MS,
sessionExportInjectFiles = ['content/utils.js', 'content/operation-delay.js', 'content/plus-checkout.js'],
sendToContentScriptResilient = null,
sleepWithStop = async (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, Number(ms) || 0))),
} = deps;
function normalizeString(value = '') {
return String(value || '').trim();
}
function isLocalCpaJsonNoRtMode(state = {}) {
return normalizeString(getPanelMode(state)) === LOCAL_CPA_JSON_NO_RT_PANEL_MODE;
}
function getLocalCliProxyApi() {
const factory = createLocalCliProxyApi
|| globalThis.MultiPageBackgroundLocalCliProxyApi?.createLocalCliProxyApi
|| null;
if (typeof factory !== 'function') {
throw new Error('本地 CPA JSON 无RT 模块未加载,无法导出认证文件。');
}
return factory({
crypto: globalThis.crypto,
fetch: typeof globalThis.fetch === 'function' ? globalThis.fetch.bind(globalThis) : null,
sessionToJsonConverter: globalThis.MultiPageSessionToJsonConverter,
});
}
async function saveLocalCpaJsonArtifactViaHelper(helperBaseUrl, artifact) {
const endpoint = typeof buildLocalHelperEndpoint === 'function'
? buildLocalHelperEndpoint(helperBaseUrl, '/save-auth-json')
: new URL('/save-auth-json', `${helperBaseUrl.replace(/\/+$/, '')}/`).toString();
const response = await fetch(endpoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
filePath: artifact.filePath,
directoryPath: artifact.directoryPath,
content: artifact.jsonText,
}),
});
let payload = {};
try {
payload = await response.json();
} catch {
payload = {};
}
if (!response.ok || payload?.ok === false) {
const helperError = normalizeString(payload?.error);
if (/Missing email\/clientId\/refreshToken/i.test(helperError)) {
throw new Error('本地 helper 未识别 /save-auth-json,当前运行的 hotmail_helper.py 版本过旧或不是当前项目目录。请停止旧 helper,并从当前 FlowPilot-FlowPilot1.0.2 目录重新启动本地助手。');
}
throw new Error(helperError || `本地 helper 写入失败(HTTP ${response.status})。`);
}
return {
...artifact,
filePath: normalizeString(payload?.filePath) || artifact.filePath,
};
}
async function openChatGptSessionExportTab(state = {}) {
if (chromeApi?.tabs?.create) {
const tab = await chromeApi.tabs.create({
url: CHATGPT_SESSION_EXPORT_URL,
active: false,
});
const tabId = Number(tab?.id);
if (Number.isInteger(tabId) && tabId > 0) {
return {
source: 'plus-checkout',
tabId,
temporary: true,
};
}
}
const fallbackTabId = Number(state?.plusCheckoutTabId || await getTabId('plus-checkout') || await getTabId('signup-page'));
if (!Number.isInteger(fallbackTabId) || fallbackTabId <= 0) {
throw new Error('未找到可读取 ChatGPT 会话的标签页,无法导出本地 CPA JSON 无RT。');
}
return {
source: 'plus-checkout',
tabId: fallbackTabId,
temporary: false,
};
}
async function closeTemporarySessionExportTab(tabInfo = {}) {
if (!tabInfo?.temporary || !Number.isInteger(Number(tabInfo?.tabId)) || !chromeApi?.tabs?.remove) {
return;
}
await chromeApi.tabs.remove(Number(tabInfo.tabId)).catch(() => {});
}
async function readChatGptSessionForExport(state = {}, visibleStep = 7) {
if (typeof sendToContentScriptResilient !== 'function') {
throw new Error('当前环境缺少 ChatGPT 会话读取通道,无法导出本地 CPA JSON 无RT。');
}
const tabInfo = await openChatGptSessionExportTab(state);
try {
await ensureContentScriptReadyOnTab(tabInfo.source, tabInfo.tabId, {
inject: sessionExportInjectFiles,
injectSource: tabInfo.source,
timeoutMs: 30000,
retryDelayMs: 800,
logMessage: `步骤 ${visibleStep}:正在连接 ChatGPT 页面,准备读取当前会话并导出 JSON...`,
logStep: visibleStep,
logStepKey: LOCAL_CPA_JSON_EXPORT_NODE_ID,
});
const sessionResult = await sendToContentScriptResilient(tabInfo.source, {
type: 'PLUS_CHECKOUT_GET_STATE',
step: visibleStep,
source: 'background',
payload: {
includeSession: true,
includeAccessToken: true,
},
}, {
timeoutMs: 15000,
retryDelayMs: 500,
logMessage: `步骤 ${visibleStep}:正在等待 ChatGPT 页面返回当前登录会话...`,
logStep: visibleStep,
logStepKey: LOCAL_CPA_JSON_EXPORT_NODE_ID,
});
if (sessionResult?.error) {
throw new Error(sessionResult.error);
}
return sessionResult;
} finally {
await closeTemporarySessionExportTab(tabInfo);
}
}
async function exportLocalCpaJsonNoRt(state = {}, options = {}) {
const visibleStep = Math.max(1, Math.floor(Number(options.visibleStep) || 7));
const helperBaseUrl = normalizeHotmailLocalBaseUrl(state.hotmailLocalBaseUrl);
const pluginDir = normalizeString(state.localCpaJsonPluginDir);
if (!helperBaseUrl) {
throw new Error('尚未配置 Hotmail 本地助手地址,请先在侧边栏填写。');
}
if (!pluginDir) {
throw new Error('尚未配置本地插件目录,请先在侧边栏填写。');
}
const sessionResult = await readChatGptSessionForExport(state, visibleStep);
const api = getLocalCliProxyApi();
const artifact = await api.buildAuthJsonArtifact({
pluginDir,
relativeAuthDir: state.localCpaJsonRelativeAuthDir,
session: sessionResult?.session,
accessToken: sessionResult?.accessToken,
sessionToken: sessionResult?.session?.sessionToken,
email: sessionResult?.email || sessionResult?.session?.user?.email || state?.email,
expiresAt: sessionResult?.expiresAt || sessionResult?.session?.expires,
accountId: sessionResult?.session?.account?.id,
userId: sessionResult?.session?.user?.id,
planType: sessionResult?.session?.account?.planType,
lastRefresh: '',
sourceName: 'SessionToJson Local No RT',
});
for (const warning of Array.isArray(artifact.warnings) ? artifact.warnings : []) {
await addLog(`步骤 ${visibleStep}${warning}`, 'warn');
}
const saved = await saveLocalCpaJsonArtifactViaHelper(helperBaseUrl, artifact);
const verifiedStatus = `本地CPA JSON 无RT 已导出:${saved.filePath}`;
await addLog(`步骤 ${visibleStep}${verifiedStatus}`, 'ok');
return {
verifiedStatus,
localCpaJsonFilePath: saved.filePath,
};
}
async function clearCookiesIfEnabled(state = {}) {
if (!state?.step6CookieCleanupEnabled) {
return;
}
if (!chromeApi?.cookies?.getAll || !chromeApi.cookies?.remove) {
await addLog('步骤 6:当前浏览器不支持 cookies API,跳过第六步 Cookies 清理。', 'warn');
return;
}
try {
await addLog('步骤 6:已开启 Cookies 清理,正在清理 ChatGPT / OpenAI cookies...', 'info');
const cookies = await collectStep6Cookies(chromeApi);
let removedCount = 0;
for (const cookie of cookies) {
if (await removeStep6Cookie(chromeApi, cookie, getErrorMessage)) {
removedCount += 1;
}
}
if (chromeApi.browsingData?.removeCookies) {
try {
await chromeApi.browsingData.removeCookies({
since: 0,
origins: STEP6_COOKIE_CLEAR_ORIGINS,
});
} catch (error) {
await addLog(`步骤 6browsingData 补扫 cookies 失败:${getErrorMessage(error)}`, 'warn');
}
}
await addLog(`步骤 6:已清理 ${removedCount} 个 ChatGPT / OpenAI cookies。`, 'ok');
} catch (error) {
await addLog(`步骤 6:Cookies 清理失败,已跳过并继续后续流程:${getErrorMessage(error)}`, 'warn');
}
}
async function executeStep6(state = {}) {
const baseWaitMs = Math.max(0, Math.floor(Number(registrationSuccessWaitMs) || 0));
const waitMs = baseWaitMs;
if (waitMs > 0) {
await addLog(`步骤 6:等待 ${Math.round(waitMs / 1000)} 秒,确认注册成功并让页面稳定...`, 'info');
await sleepWithStop(waitMs);
}
await clearCookiesIfEnabled(state);
await addLog('步骤 6:注册成功等待完成,注册阶段已结束。', 'ok');
await completeNodeFromBackground('wait-registration-success', {});
}
async function executeLocalCpaJsonNoRtExport(state = {}) {
if (!isLocalCpaJsonNoRtMode(state)) {
throw new Error('当前不是本地CPA JSON 无RT 模式,不能执行无RT导出节点。');
}
await addLog('步骤 7Plus Checkout 已完成,等待 5 秒后导出本地 CPA JSON 无RT...', 'info');
await sleepWithStop(5000);
const completionPayload = await exportLocalCpaJsonNoRt(state, { visibleStep: 7 });
await completeNodeFromBackground(LOCAL_CPA_JSON_EXPORT_NODE_ID, completionPayload);
}
return {
executeLocalCpaJsonNoRtExport,
executeStep6,
};
}
return { createStep6Executor };
});