// content/vps-panel.js — Content script for VPS panel (steps 1, 9) // Injected on: VPS panel (user-configured URL) // // Actual DOM structure (after login click): //
//
// Codex OAuth // //
//
//
//
授权链接:
//
https://auth.openai.com/...
//
// // //
//
//
// // //
//
//
console.log('[MultiPage:vps-panel] Content script loaded on', location.href); // Listen for commands from Background chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'EXECUTE_STEP') { resetStopState(); handleStep(message.step, message.payload).then(() => { sendResponse({ ok: true }); }).catch(err => { if (isStopError(err)) { log(`Step ${message.step}: Stopped by user.`, 'warn'); sendResponse({ stopped: true, error: err.message }); return; } reportError(message.step, err.message); sendResponse({ error: err.message }); }); return true; } }); async function handleStep(step, payload) { switch (step) { case 1: return await step1_getOAuthLink(); case 9: return await step9_vpsVerify(payload); default: throw new Error(`vps-panel.js does not handle step ${step}`); } } // ============================================================ // Step 1: Get OAuth Link // ============================================================ async function step1_getOAuthLink() { log('Step 1: Waiting for VPS panel to load (auto-login may take a moment)...'); // The page may start at #/login and auto-redirect to #/oauth. // Wait for the Codex OAuth card to appear (up to 30s for auto-login + redirect). let loginBtn = null; try { // Wait for any card-header containing "Codex" to appear const header = await waitForElementByText('.card-header', /codex/i, 30000); loginBtn = header.querySelector('button.btn.btn-primary, button.btn'); log('Step 1: Found Codex OAuth card'); } catch { throw new Error( 'Codex OAuth card did not appear after 30s. Page may still be loading or not logged in. ' + 'Current URL: ' + location.href ); } if (!loginBtn) { throw new Error('Found Codex OAuth card but no login button inside it. URL: ' + location.href); } // Check if button is disabled (already clicked / loading) if (loginBtn.disabled) { log('Step 1: Login button is disabled (already loading), waiting for auth URL...'); } else { await humanPause(500, 1400); simulateClick(loginBtn); log('Step 1: Clicked login button, waiting for auth URL...'); } // Wait for the auth URL to appear in the specific div let authUrlEl = null; try { authUrlEl = await waitForElement('[class*="authUrlValue"]', 15000); } catch { throw new Error( 'Auth URL did not appear after clicking login. ' + 'Check if VPS panel is logged in and Codex service is running. URL: ' + location.href ); } const oauthUrl = (authUrlEl.textContent || '').trim(); if (!oauthUrl || !oauthUrl.startsWith('http')) { throw new Error(`Invalid OAuth URL found: "${oauthUrl.slice(0, 50)}". Expected URL starting with http.`); } log(`Step 1: OAuth URL obtained: ${oauthUrl.slice(0, 80)}...`, 'ok'); reportComplete(1, { oauthUrl }); } // ============================================================ // Step 9: VPS Verify — paste localhost URL and submit // ============================================================ async function step9_vpsVerify(payload) { // Get localhostUrl from payload (passed directly by background) or fallback to state let localhostUrl = payload?.localhostUrl; if (!localhostUrl) { log('Step 9: localhostUrl not in payload, fetching from state...'); const state = await chrome.runtime.sendMessage({ type: 'GET_STATE' }); localhostUrl = state.localhostUrl; } if (!localhostUrl) { throw new Error('No localhost URL found. Complete step 8 first.'); } log(`Step 9: Got localhostUrl: ${localhostUrl.slice(0, 60)}...`); log('Step 9: Looking for callback URL input...'); // Find the callback URL input // Actual DOM: let urlInput = null; try { urlInput = await waitForElement('[class*="callbackSection"] input.input', 10000); } catch { try { urlInput = await waitForElement('input[placeholder*="localhost"]', 5000); } catch { throw new Error('Could not find callback URL input on VPS panel. URL: ' + location.href); } } await humanPause(600, 1500); fillInput(urlInput, localhostUrl); log(`Step 9: Filled callback URL: ${localhostUrl.slice(0, 80)}...`); // Find and click "提交回调 URL" button let submitBtn = null; try { submitBtn = await waitForElementByText( '[class*="callbackActions"] button, [class*="callbackSection"] button', /提交/, 5000 ); } catch { try { submitBtn = await waitForElementByText('button.btn', /提交回调/, 5000); } catch { throw new Error('Could not find "提交回调 URL" button. URL: ' + location.href); } } await humanPause(450, 1200); simulateClick(submitBtn); log('Step 9: Clicked "提交回调 URL", waiting for authentication result...'); // Wait for "认证成功!" status badge to appear try { await waitForElementByText('.status-badge, [class*="status"]', /认证成功/, 30000); log('Step 9: Authentication successful!', 'ok'); } catch { // Check if there's an error message instead const statusEl = document.querySelector('.status-badge, [class*="status"]'); const statusText = statusEl ? statusEl.textContent : 'unknown'; if (/成功|success/i.test(statusText)) { log('Step 9: Authentication successful!', 'ok'); } else { log(`Step 9: Status after submit: "${statusText}". May still be processing.`, 'warn'); } } reportComplete(9); }