vps-panel.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // content/vps-panel.js — Content script for VPS panel (steps 1, 9)
  2. // Injected on: http://154.26.182.181:8317/*
  3. console.log('[MultiPage:vps-panel] Content script loaded on', location.href);
  4. // Listen for commands from Background
  5. chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  6. if (message.type === 'EXECUTE_STEP') {
  7. handleStep(message.step, message.payload).then(() => {
  8. sendResponse({ ok: true });
  9. }).catch(err => {
  10. reportError(message.step, err.message);
  11. sendResponse({ error: err.message });
  12. });
  13. return true;
  14. }
  15. });
  16. async function handleStep(step, payload) {
  17. switch (step) {
  18. case 1: return await step1_getOAuthLink();
  19. case 9: return await step9_vpsVerify();
  20. default:
  21. throw new Error(`vps-panel.js does not handle step ${step}`);
  22. }
  23. }
  24. // ============================================================
  25. // Step 1: Get OAuth Link
  26. // ============================================================
  27. async function step1_getOAuthLink() {
  28. log('Step 1: Checking VPS panel state...');
  29. // --- Selector strategy ---
  30. // The VPS panel is at management.html#/oauth
  31. // We need to: 1) find OAuth login section, 2) click Codex login, 3) read auth URL
  32. // TODO: These selectors MUST be adjusted after inspecting the actual VPS panel DOM
  33. // The selectors below are best-guess placeholders.
  34. // Try to find OAuth login button by text content
  35. log('Step 1: Looking for OAuth login button...');
  36. let oauthBtn = null;
  37. try {
  38. oauthBtn = await waitForElementByText(
  39. 'button, a, [role="button"], .el-button, div[class*="btn"]',
  40. /oauth|OAuth/i,
  41. 10000
  42. );
  43. } catch {
  44. // Fallback: try common UI framework selectors
  45. try {
  46. oauthBtn = await waitForElement('.oauth-login-btn, [data-action="oauth-login"]', 5000);
  47. } catch {
  48. throw new Error(
  49. 'Could not find OAuth login button. ' +
  50. 'Please inspect the VPS panel page in DevTools and update the selector in vps-panel.js. ' +
  51. 'URL: ' + location.href
  52. );
  53. }
  54. }
  55. simulateClick(oauthBtn);
  56. log('Step 1: Clicked OAuth login, waiting for Codex login option...');
  57. await sleep(1500);
  58. // Wait for Codex login option to appear
  59. let codexBtn = null;
  60. try {
  61. codexBtn = await waitForElementByText(
  62. 'button, a, [role="button"], .el-button, div[class*="btn"], span',
  63. /codex/i,
  64. 10000
  65. );
  66. } catch {
  67. try {
  68. codexBtn = await waitForElement('[data-action="codex-login"], .codex-login-btn', 5000);
  69. } catch {
  70. throw new Error(
  71. 'Could not find Codex login button after clicking OAuth. ' +
  72. 'Check the VPS panel DOM in DevTools. URL: ' + location.href
  73. );
  74. }
  75. }
  76. simulateClick(codexBtn);
  77. log('Step 1: Clicked Codex login, waiting for auth URL...');
  78. await sleep(2000);
  79. // Extract the auth URL — could be in various elements
  80. let oauthUrl = null;
  81. // Strategy 1: Look for an input/textarea with a URL value
  82. const inputs = document.querySelectorAll('input[readonly], input[type="text"], textarea, code, pre');
  83. for (const el of inputs) {
  84. const val = (el.value || el.textContent || '').trim();
  85. if (val.startsWith('http') && val.length > 30) {
  86. oauthUrl = val;
  87. log(`Step 1: Found URL in <${el.tagName}>: ${val.slice(0, 80)}...`);
  88. break;
  89. }
  90. }
  91. // Strategy 2: Look for any element containing a long URL
  92. if (!oauthUrl) {
  93. const allElements = document.querySelectorAll('span, p, div, a, code, pre');
  94. for (const el of allElements) {
  95. const text = (el.textContent || '').trim();
  96. // Match a URL that looks like an OAuth authorization URL
  97. const urlMatch = text.match(/(https?:\/\/[^\s<>"']{30,})/);
  98. if (urlMatch) {
  99. oauthUrl = urlMatch[1];
  100. log(`Step 1: Found URL in text: ${oauthUrl.slice(0, 80)}...`);
  101. break;
  102. }
  103. }
  104. }
  105. // Strategy 3: Check clipboard (if the page auto-copies)
  106. if (!oauthUrl) {
  107. try {
  108. oauthUrl = await navigator.clipboard.readText();
  109. if (oauthUrl && oauthUrl.startsWith('http') && oauthUrl.length > 30) {
  110. log(`Step 1: Found URL in clipboard: ${oauthUrl.slice(0, 80)}...`);
  111. } else {
  112. oauthUrl = null;
  113. }
  114. } catch {
  115. // Clipboard access may be denied
  116. }
  117. }
  118. if (!oauthUrl) {
  119. throw new Error(
  120. 'Could not find auth URL. The URL may be displayed in a format we cannot detect. ' +
  121. 'Please check the VPS panel page and copy the URL manually, or update the extraction logic in vps-panel.js. ' +
  122. 'URL: ' + location.href
  123. );
  124. }
  125. log(`Step 1: OAuth URL obtained: ${oauthUrl.slice(0, 80)}...`, 'ok');
  126. reportComplete(1, { oauthUrl: oauthUrl.trim() });
  127. }
  128. // ============================================================
  129. // Step 9: VPS Verify
  130. // ============================================================
  131. async function step9_vpsVerify() {
  132. log('Step 9: Getting localhost URL from storage...');
  133. // Get localhostUrl from storage (via Background)
  134. const state = await chrome.runtime.sendMessage({ type: 'GET_STATE' });
  135. const localhostUrl = state.localhostUrl;
  136. if (!localhostUrl) {
  137. throw new Error('No localhost URL found. Complete step 8 first.');
  138. }
  139. log(`Step 9: Looking for URL input field on VPS panel...`);
  140. // Try to find URL input field
  141. let urlInput = null;
  142. try {
  143. urlInput = await waitForElement(
  144. 'input[placeholder*="localhost"], input[placeholder*="callback"], input[placeholder*="URL"], input[placeholder*="url"], input[name*="callback"], input[name*="url"]',
  145. 10000
  146. );
  147. } catch {
  148. // Fallback: find any text input that's visible and empty
  149. const inputs = document.querySelectorAll('input[type="text"], input:not([type])');
  150. for (const input of inputs) {
  151. if (input.offsetParent !== null && !input.value) {
  152. urlInput = input;
  153. log('Step 9: Using fallback empty input field');
  154. break;
  155. }
  156. }
  157. if (!urlInput) {
  158. throw new Error(
  159. 'Could not find URL input field on VPS panel. ' +
  160. 'Check DOM structure in DevTools. URL: ' + location.href
  161. );
  162. }
  163. }
  164. fillInput(urlInput, localhostUrl);
  165. log(`Step 9: Filled URL input with: ${localhostUrl}`);
  166. // Find and click verify button
  167. let verifyBtn = null;
  168. try {
  169. verifyBtn = await waitForElementByText(
  170. 'button, [role="button"], .el-button, a',
  171. /verif|确认|验证|submit|提交/i,
  172. 10000
  173. );
  174. } catch {
  175. throw new Error(
  176. 'Could not find verify/submit button. ' +
  177. 'Check VPS panel DOM in DevTools. URL: ' + location.href
  178. );
  179. }
  180. simulateClick(verifyBtn);
  181. log('Step 9: Clicked verify button', 'ok');
  182. reportComplete(9);
  183. }