| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // content/chatgpt.js — Content script for ChatGPT (steps 6, 7-receive, 8)
- // Injected on: chatgpt.com
- console.log('[MultiPage:chatgpt] Content script loaded on', location.href);
- // Listen for commands from Background
- chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
- if (message.type === 'EXECUTE_STEP' || message.type === 'FILL_CODE') {
- handleCommand(message).then(() => {
- sendResponse({ ok: true });
- }).catch(err => {
- reportError(message.step, err.message);
- sendResponse({ error: err.message });
- });
- return true;
- }
- });
- async function handleCommand(message) {
- switch (message.type) {
- case 'EXECUTE_STEP':
- switch (message.step) {
- case 6: return await step6_loginChatGPT();
- case 8: return await step8_navigateOAuth();
- default: throw new Error(`chatgpt.js does not handle step ${message.step}`);
- }
- case 'FILL_CODE':
- return await step7_fillLoginCode(message.payload);
- }
- }
- // ============================================================
- // Step 6: Login ChatGPT
- // ============================================================
- async function step6_loginChatGPT() {
- log('Step 6: Looking for login button on ChatGPT...');
- // Get state for email and password
- const state = await chrome.runtime.sendMessage({ type: 'GET_STATE' });
- const email = state.email;
- const password = state.password;
- if (!email) throw new Error('No email found in state. Complete earlier steps first.');
- // Find login button on ChatGPT homepage
- let loginBtn = null;
- try {
- loginBtn = await waitForElementByText(
- 'a, button, [role="button"], [role="link"]',
- /log\s*in|sign\s*in|登录/i,
- 10000
- );
- } catch {
- try {
- loginBtn = await waitForElement(
- '[data-testid="login-button"], a[href*="auth"], a[href*="login"]',
- 5000
- );
- } catch {
- throw new Error('Could not find Login button on ChatGPT. URL: ' + location.href);
- }
- }
- simulateClick(loginBtn);
- log('Step 6: Clicked Login button, waiting for auth page...');
- await sleep(3000);
- // We may be redirected to an auth page (auth0.openai.com etc.)
- // Or the login form may appear on the same page
- // Try to find email input
- let emailInput = null;
- try {
- emailInput = await waitForElement(
- 'input[type="email"], input[name="email"], input[name="username"], input[id*="email"], input[placeholder*="email" i]',
- 15000
- );
- } catch {
- throw new Error('Could not find email input on login page. URL: ' + location.href);
- }
- fillInput(emailInput, email);
- log(`Step 6: Filled email: ${email}`);
- // Submit email
- await sleep(500);
- const submitBtn1 = document.querySelector('button[type="submit"]')
- || await waitForElementByText('button', /continue|next|submit|继续/i, 5000).catch(() => null);
- if (submitBtn1) {
- simulateClick(submitBtn1);
- log('Step 6: Submitted email');
- }
- await sleep(2000);
- // Check: password field or OTP?
- const passwordInput = document.querySelector('input[type="password"]');
- if (passwordInput) {
- log('Step 6: Password field found, filling password...');
- fillInput(passwordInput, password);
- await sleep(500);
- const submitBtn2 = document.querySelector('button[type="submit"]')
- || await waitForElementByText('button', /continue|log\s*in|submit|sign\s*in|登录/i, 5000).catch(() => null);
- if (submitBtn2) {
- simulateClick(submitBtn2);
- log('Step 6: Submitted password');
- }
- await sleep(3000);
- // Check if we need OTP after password
- const codeInput = document.querySelector(
- 'input[name="code"], input[maxlength="6"], input[inputmode="numeric"], input[type="text"][maxlength="6"]'
- );
- if (codeInput) {
- log('Step 6: OTP code input found after password. Waiting for step 7...');
- reportComplete(6, { needsOTP: true });
- } else {
- // Check if we're actually logged in (redirected to chatgpt.com main page)
- log('Step 6: Login appears successful (no OTP needed)');
- reportComplete(6, { needsOTP: false });
- }
- } else {
- // No password field — check for OTP input or "check your email" message
- const codeInput = document.querySelector(
- 'input[name="code"], input[maxlength="6"], input[inputmode="numeric"]'
- );
- if (codeInput) {
- log('Step 6: OTP flow detected (no password). Waiting for step 7...');
- reportComplete(6, { needsOTP: true });
- } else {
- // Maybe the page is still loading or transitioning
- log('Step 6: No password or OTP field found. May need email verification. Waiting for step 7...');
- reportComplete(6, { needsOTP: true });
- }
- }
- }
- // ============================================================
- // Step 7 (receiving end): Fill Login Verification Code
- // ============================================================
- async function step7_fillLoginCode(payload) {
- const { code } = payload;
- if (!code) throw new Error('No verification code provided.');
- log(`Step 7: Filling login verification code: ${code}`);
- // Find code input — single input or multiple single-digit inputs
- let codeInput = null;
- try {
- codeInput = await waitForElement(
- 'input[name="code"], input[name="otp"], input[maxlength="6"], input[type="text"][inputmode="numeric"], input[aria-label*="code" i], input[placeholder*="code" i]',
- 10000
- );
- } catch {
- // Check for multiple single-digit inputs
- const singleInputs = document.querySelectorAll('input[maxlength="1"]');
- if (singleInputs.length >= 6) {
- log('Step 7: Found single-digit code inputs, filling individually...');
- for (let i = 0; i < 6 && i < singleInputs.length; i++) {
- fillInput(singleInputs[i], code[i]);
- await sleep(100);
- }
- await sleep(1000);
- // Auto-submit may happen; if not, try clicking submit
- const submitBtn = document.querySelector('button[type="submit"]')
- || await waitForElementByText('button', /continue|verify|submit|confirm/i, 3000).catch(() => null);
- if (submitBtn) simulateClick(submitBtn);
- await sleep(3000);
- reportComplete(7);
- return;
- }
- throw new Error('Could not find verification code input on ChatGPT login. URL: ' + location.href);
- }
- fillInput(codeInput, code);
- await sleep(500);
- const submitBtn = document.querySelector('button[type="submit"]')
- || await waitForElementByText('button', /continue|verify|submit|confirm|确认/i, 5000).catch(() => null);
- if (submitBtn) {
- simulateClick(submitBtn);
- log('Step 7: Login verification code submitted');
- }
- await sleep(3000);
- reportComplete(7);
- }
- // ============================================================
- // Step 8: Navigate to OAuth URL
- // ============================================================
- async function step8_navigateOAuth() {
- const state = await chrome.runtime.sendMessage({ type: 'GET_STATE' });
- const oauthUrl = state.oauthUrl;
- if (!oauthUrl) throw new Error('No OAuth URL found. Complete step 1 first.');
- log(`Step 8: Navigating to OAuth URL: ${oauthUrl.slice(0, 80)}...`);
- log('Step 8: Waiting for localhost redirect (captured by background)...');
- // Navigate — the webNavigation listener in background will capture localhost redirect
- window.location.href = oauthUrl;
- // Don't reportComplete here — background handles it via webNavigation
- }
|