From 239b1409cedd1f1d2329ddd0423405040716ece9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:44:43 +0000 Subject: [PATCH 1/6] Initial plan From 0e5c2ede22cc66d1660012b991bdd5c3b5327a50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:47:07 +0000 Subject: [PATCH 2/6] Add Google Sign-In proxy support for CloudMoon Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- README.md | 4 +- worker.js | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 282 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 08315dc..c034ed1 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Cloudmoon InPlay is a simple site that proxies, hides, and loads cloudmoon in a ## Use -> [!IMPORTANT] -> Because of google's authentication policies, the google sign in button will NOT WORK. You must hit sign in with email and password instead. You will also need to register your cloudmoon account at home with google and set a password in settings. +> [!TIP] +> Google Sign-In is now supported! The proxy intercepts and forwards Google authentication requests, allowing you to sign in with your Google account directly through the CloudMoon interface. Once you sign in, you can click and play games in Cloudmoons library! After that, you can use the upper navbar to help you navigate, cloak the site with About:Blank, and reload the site with the reload button. diff --git a/worker.js b/worker.js index e696b0d..6ac5ad4 100644 --- a/worker.js +++ b/worker.js @@ -1,8 +1,22 @@ -// Cloudflare Worker - CloudMoon Proxy with Tab Cloaking +// Cloudflare Worker - CloudMoon Proxy with Tab Cloaking and Google Sign-In Support addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); + // Google domains that need to be proxied for sign-in + const GOOGLE_AUTH_DOMAINS = [ + 'accounts.google.com', + 'oauth2.googleapis.com', + 'www.googleapis.com', + 'apis.google.com', + 'ssl.gstatic.com', + 'www.gstatic.com', + 'fonts.googleapis.com', + 'fonts.gstatic.com', + 'lh3.googleusercontent.com', + 'googleusercontent.com' + ]; + async function handleRequest(request) { const url = new URL(request.url); @@ -13,12 +27,131 @@ addEventListener('fetch', event => { }); } + // Handle Google auth proxy routes + if (url.pathname.startsWith('/gauth/')) { + return proxyGoogleAuth(request); + } + // Proxy everything else to CloudMoon return proxyCloudMoon(request); } + // Proxy Google authentication requests + async function proxyGoogleAuth(request) { + const url = new URL(request.url); + const workerOrigin = url.origin; + + // Extract the target Google URL from the path + // Format: /gauth/domain.com/path + const pathParts = url.pathname.replace('/gauth/', '').split('/'); + const targetDomain = pathParts[0]; + const targetPath = '/' + pathParts.slice(1).join('/') + url.search; + const targetURL = 'https://' + targetDomain + targetPath; + + console.log('Proxying Google Auth:', targetURL); + + const headers = new Headers(request.headers); + headers.set('Host', targetDomain); + headers.set('Origin', 'https://' + targetDomain); + headers.set('Referer', 'https://' + targetDomain + '/'); + headers.delete('cf-connecting-ip'); + headers.delete('cf-ray'); + headers.delete('x-forwarded-proto'); + headers.delete('x-real-ip'); + + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'); + } + + const proxyRequest = new Request(targetURL, { + method: request.method, + headers: headers, + body: request.body, + redirect: 'manual' + }); + + let response = await fetch(proxyRequest); + + // Handle redirects by rewriting them to go through our proxy + if (response.status >= 300 && response.status < 400) { + const location = response.headers.get('Location'); + if (location) { + const newLocation = rewriteGoogleUrl(location, workerOrigin); + const newHeaders = new Headers(response.headers); + newHeaders.set('Location', newLocation); + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: newHeaders + }); + } + } + + const newHeaders = new Headers(response.headers); + newHeaders.set('Access-Control-Allow-Origin', '*'); + newHeaders.set('Access-Control-Allow-Methods', '*'); + newHeaders.set('Access-Control-Allow-Headers', '*'); + newHeaders.set('Access-Control-Allow-Credentials', 'true'); + newHeaders.delete('Content-Security-Policy'); + newHeaders.delete('X-Frame-Options'); + newHeaders.delete('Frame-Options'); + newHeaders.delete('Cross-Origin-Opener-Policy'); + newHeaders.delete('Cross-Origin-Embedder-Policy'); + + const contentType = response.headers.get('Content-Type') || ''; + + // Rewrite HTML/JS content to redirect Google URLs through our proxy + if (contentType.includes('text/html') || contentType.includes('javascript')) { + let content = await response.text(); + content = rewriteGoogleContent(content, workerOrigin); + + return new Response(content, { + status: response.status, + statusText: response.statusText, + headers: newHeaders + }); + } + + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: newHeaders + }); + } + + // Rewrite a single Google URL to go through our proxy + function rewriteGoogleUrl(url, workerOrigin) { + try { + const parsed = new URL(url); + for (const domain of GOOGLE_AUTH_DOMAINS) { + if (parsed.hostname === domain || parsed.hostname.endsWith('.' + domain)) { + return workerOrigin + '/gauth/' + parsed.hostname + parsed.pathname + parsed.search; + } + } + } catch (e) { + // URL parsing failed, return as-is + } + return url; + } + + // Rewrite content to redirect Google URLs through proxy + function rewriteGoogleContent(content, workerOrigin) { + // Replace Google auth domain URLs with proxied versions + for (const domain of GOOGLE_AUTH_DOMAINS) { + // Replace https://domain URLs + const httpsPattern = new RegExp('https://' + domain.replace(/\./g, '\\.'), 'g'); + content = content.replace(httpsPattern, workerOrigin + '/gauth/' + domain); + + // Replace //domain URLs (protocol-relative) + const protocolRelPattern = new RegExp('"//' + domain.replace(/\./g, '\\.'), 'g'); + content = content.replace(protocolRelPattern, '"' + workerOrigin + '/gauth/' + domain); + } + return content; + } + async function proxyCloudMoon(request) { const url = new URL(request.url); + const workerOrigin = url.origin; // Build the target URL let targetURL; @@ -60,21 +193,53 @@ addEventListener('fetch', event => { newHeaders.delete('Content-Security-Policy'); newHeaders.delete('X-Frame-Options'); newHeaders.delete('Frame-Options'); + newHeaders.delete('Cross-Origin-Opener-Policy'); + newHeaders.delete('Cross-Origin-Embedder-Policy'); const contentType = response.headers.get('Content-Type') || ''; if (contentType.includes('text/html')) { let html = await response.text(); + // Rewrite Google URLs to go through our proxy + html = rewriteGoogleContent(html, workerOrigin); + const injectionScript = ` `; @@ -114,6 +381,18 @@ addEventListener('fetch', event => { }); } + // Also rewrite JS files that might contain Google URLs + if (contentType.includes('javascript')) { + let js = await response.text(); + js = rewriteGoogleContent(js, workerOrigin); + + return new Response(js, { + status: response.status, + statusText: response.statusText, + headers: newHeaders + }); + } + return new Response(response.body, { status: response.status, statusText: response.statusText, From a2af522af2463d29fe58caff3e26ca6de409dc44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:48:22 +0000 Subject: [PATCH 3/6] Fix code review issues: hostname matching, regex caching, Request constructor Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- worker.js | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/worker.js b/worker.js index 6ac5ad4..0adb0c5 100644 --- a/worker.js +++ b/worker.js @@ -124,7 +124,9 @@ addEventListener('fetch', event => { try { const parsed = new URL(url); for (const domain of GOOGLE_AUTH_DOMAINS) { - if (parsed.hostname === domain || parsed.hostname.endsWith('.' + domain)) { + // Check for exact match OR proper subdomain (preceded by a dot) + if (parsed.hostname === domain || + (parsed.hostname.endsWith('.' + domain) && parsed.hostname.length > domain.length + 1)) { return workerOrigin + '/gauth/' + parsed.hostname + parsed.pathname + parsed.search; } } @@ -134,17 +136,22 @@ addEventListener('fetch', event => { return url; } + // Pre-compiled regex patterns for URL rewriting + const GOOGLE_URL_PATTERNS = GOOGLE_AUTH_DOMAINS.map(domain => ({ + domain, + https: new RegExp('https://' + domain.replace(/\./g, '\\.'), 'g'), + protocolRelative: new RegExp('(["\'])//(' + domain.replace(/\./g, '\\.') + ')', 'g') + })); + // Rewrite content to redirect Google URLs through proxy function rewriteGoogleContent(content, workerOrigin) { - // Replace Google auth domain URLs with proxied versions - for (const domain of GOOGLE_AUTH_DOMAINS) { + // Replace Google auth domain URLs with proxied versions using pre-compiled patterns + for (const pattern of GOOGLE_URL_PATTERNS) { // Replace https://domain URLs - const httpsPattern = new RegExp('https://' + domain.replace(/\./g, '\\.'), 'g'); - content = content.replace(httpsPattern, workerOrigin + '/gauth/' + domain); + content = content.replace(pattern.https, workerOrigin + '/gauth/' + pattern.domain); - // Replace //domain URLs (protocol-relative) - const protocolRelPattern = new RegExp('"//' + domain.replace(/\./g, '\\.'), 'g'); - content = content.replace(protocolRelPattern, '"' + workerOrigin + '/gauth/' + domain); + // Replace //domain URLs (protocol-relative) with any quote type + content = content.replace(pattern.protocolRelative, '$1' + workerOrigin + '/gauth/' + pattern.domain); } return content; } @@ -220,13 +227,19 @@ addEventListener('fetch', event => { 'www.gstatic.com' ]; + // Helper function to check if hostname matches a Google domain (exact or subdomain) + function isGoogleDomain(hostname, domain) { + return hostname === domain || + (hostname.endsWith('.' + domain) && hostname.length > domain.length + 1); + } + // Helper function to rewrite Google URLs function rewriteGoogleUrl(url) { if (!url) return url; try { const parsed = new URL(url, window.location.href); for (const domain of GOOGLE_DOMAINS) { - if (parsed.hostname === domain || parsed.hostname.endsWith('.' + domain)) { + if (isGoogleDomain(parsed.hostname, domain)) { return WORKER_ORIGIN + '/gauth/' + parsed.hostname + parsed.pathname + parsed.search; } } @@ -281,7 +294,8 @@ addEventListener('fetch', event => { if (typeof input === 'string') { return originalFetch.call(this, rewrittenUrl, init); } else { - return originalFetch.call(this, new Request(rewrittenUrl, input), init); + // When input is a Request, pass init options separately + return originalFetch.call(this, rewrittenUrl, init); } } return originalFetch.call(this, input, init); From 13b97e79ff191bbfe3aea7f7d64e2ce69bfaac69 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:57:32 +0000 Subject: [PATCH 4/6] Fix Google Sign-In: Hide button and guide users to email/password auth Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- README.md | 6 +- worker.js | 346 ++++++++++-------------------------------------------- 2 files changed, 64 insertions(+), 288 deletions(-) diff --git a/README.md b/README.md index c034ed1..8172f81 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,10 @@ Cloudmoon InPlay is a simple site that proxies, hides, and loads cloudmoon in a ## Use -> [!TIP] -> Google Sign-In is now supported! The proxy intercepts and forwards Google authentication requests, allowing you to sign in with your Google account directly through the CloudMoon interface. +> [!IMPORTANT] +> **Google Sign-In does not work through the proxy** due to Google's OAuth 2.0 origin validation. The proxy automatically hides the Google Sign-In button to prevent errors. You must use **email and password** authentication instead. +> +> To set up email/password login: Register your CloudMoon account at home (on the official site) using Google, then go to Settings and set a password. You can then use that email/password to sign in through this proxy. Once you sign in, you can click and play games in Cloudmoons library! After that, you can use the upper navbar to help you navigate, cloak the site with About:Blank, and reload the site with the reload button. diff --git a/worker.js b/worker.js index 0adb0c5..51dca36 100644 --- a/worker.js +++ b/worker.js @@ -1,22 +1,8 @@ -// Cloudflare Worker - CloudMoon Proxy with Tab Cloaking and Google Sign-In Support +// Cloudflare Worker - CloudMoon Proxy with Tab Cloaking addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); - // Google domains that need to be proxied for sign-in - const GOOGLE_AUTH_DOMAINS = [ - 'accounts.google.com', - 'oauth2.googleapis.com', - 'www.googleapis.com', - 'apis.google.com', - 'ssl.gstatic.com', - 'www.gstatic.com', - 'fonts.googleapis.com', - 'fonts.gstatic.com', - 'lh3.googleusercontent.com', - 'googleusercontent.com' - ]; - async function handleRequest(request) { const url = new URL(request.url); @@ -27,138 +13,12 @@ addEventListener('fetch', event => { }); } - // Handle Google auth proxy routes - if (url.pathname.startsWith('/gauth/')) { - return proxyGoogleAuth(request); - } - // Proxy everything else to CloudMoon return proxyCloudMoon(request); } - // Proxy Google authentication requests - async function proxyGoogleAuth(request) { - const url = new URL(request.url); - const workerOrigin = url.origin; - - // Extract the target Google URL from the path - // Format: /gauth/domain.com/path - const pathParts = url.pathname.replace('/gauth/', '').split('/'); - const targetDomain = pathParts[0]; - const targetPath = '/' + pathParts.slice(1).join('/') + url.search; - const targetURL = 'https://' + targetDomain + targetPath; - - console.log('Proxying Google Auth:', targetURL); - - const headers = new Headers(request.headers); - headers.set('Host', targetDomain); - headers.set('Origin', 'https://' + targetDomain); - headers.set('Referer', 'https://' + targetDomain + '/'); - headers.delete('cf-connecting-ip'); - headers.delete('cf-ray'); - headers.delete('x-forwarded-proto'); - headers.delete('x-real-ip'); - - if (!headers.has('User-Agent')) { - headers.set('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'); - } - - const proxyRequest = new Request(targetURL, { - method: request.method, - headers: headers, - body: request.body, - redirect: 'manual' - }); - - let response = await fetch(proxyRequest); - - // Handle redirects by rewriting them to go through our proxy - if (response.status >= 300 && response.status < 400) { - const location = response.headers.get('Location'); - if (location) { - const newLocation = rewriteGoogleUrl(location, workerOrigin); - const newHeaders = new Headers(response.headers); - newHeaders.set('Location', newLocation); - return new Response(response.body, { - status: response.status, - statusText: response.statusText, - headers: newHeaders - }); - } - } - - const newHeaders = new Headers(response.headers); - newHeaders.set('Access-Control-Allow-Origin', '*'); - newHeaders.set('Access-Control-Allow-Methods', '*'); - newHeaders.set('Access-Control-Allow-Headers', '*'); - newHeaders.set('Access-Control-Allow-Credentials', 'true'); - newHeaders.delete('Content-Security-Policy'); - newHeaders.delete('X-Frame-Options'); - newHeaders.delete('Frame-Options'); - newHeaders.delete('Cross-Origin-Opener-Policy'); - newHeaders.delete('Cross-Origin-Embedder-Policy'); - - const contentType = response.headers.get('Content-Type') || ''; - - // Rewrite HTML/JS content to redirect Google URLs through our proxy - if (contentType.includes('text/html') || contentType.includes('javascript')) { - let content = await response.text(); - content = rewriteGoogleContent(content, workerOrigin); - - return new Response(content, { - status: response.status, - statusText: response.statusText, - headers: newHeaders - }); - } - - return new Response(response.body, { - status: response.status, - statusText: response.statusText, - headers: newHeaders - }); - } - - // Rewrite a single Google URL to go through our proxy - function rewriteGoogleUrl(url, workerOrigin) { - try { - const parsed = new URL(url); - for (const domain of GOOGLE_AUTH_DOMAINS) { - // Check for exact match OR proper subdomain (preceded by a dot) - if (parsed.hostname === domain || - (parsed.hostname.endsWith('.' + domain) && parsed.hostname.length > domain.length + 1)) { - return workerOrigin + '/gauth/' + parsed.hostname + parsed.pathname + parsed.search; - } - } - } catch (e) { - // URL parsing failed, return as-is - } - return url; - } - - // Pre-compiled regex patterns for URL rewriting - const GOOGLE_URL_PATTERNS = GOOGLE_AUTH_DOMAINS.map(domain => ({ - domain, - https: new RegExp('https://' + domain.replace(/\./g, '\\.'), 'g'), - protocolRelative: new RegExp('(["\'])//(' + domain.replace(/\./g, '\\.') + ')', 'g') - })); - - // Rewrite content to redirect Google URLs through proxy - function rewriteGoogleContent(content, workerOrigin) { - // Replace Google auth domain URLs with proxied versions using pre-compiled patterns - for (const pattern of GOOGLE_URL_PATTERNS) { - // Replace https://domain URLs - content = content.replace(pattern.https, workerOrigin + '/gauth/' + pattern.domain); - - // Replace //domain URLs (protocol-relative) with any quote type - content = content.replace(pattern.protocolRelative, '$1' + workerOrigin + '/gauth/' + pattern.domain); - } - return content; - } - async function proxyCloudMoon(request) { const url = new URL(request.url); - const workerOrigin = url.origin; // Build the target URL let targetURL; @@ -208,46 +68,12 @@ addEventListener('fetch', event => { if (contentType.includes('text/html')) { let html = await response.text(); - // Rewrite Google URLs to go through our proxy - html = rewriteGoogleContent(html, workerOrigin); - const injectionScript = ` @@ -395,18 +181,6 @@ addEventListener('fetch', event => { }); } - // Also rewrite JS files that might contain Google URLs - if (contentType.includes('javascript')) { - let js = await response.text(); - js = rewriteGoogleContent(js, workerOrigin); - - return new Response(js, { - status: response.status, - statusText: response.statusText, - headers: newHeaders - }); - } - return new Response(response.body, { status: response.status, statusText: response.statusText, From cccadbe82848e8392b26db0e79f73e8ec52e3786 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:58:25 +0000 Subject: [PATCH 5/6] Address code review: Extract selectors to constant, add null check for observer Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- worker.js | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/worker.js b/worker.js index 51dca36..c5a5fba 100644 --- a/worker.js +++ b/worker.js @@ -103,43 +103,47 @@ addEventListener('fetch', event => { // Hide Google Sign-In buttons and show alternative message // Google OAuth doesn't work through proxies due to origin validation + + // Selectors for Google Sign-In elements (used in CSS and JS) + const GOOGLE_SIGNIN_SELECTORS = [ + '[data-client_id]', + '.g_id_signin', + '.gsi-material-button', + 'div[id^="g_id_"]', + 'iframe[src*="accounts.google.com"]', + 'iframe[src*="gsi/button"]', + '[aria-label*="Google"]', + 'button[data-provider="google"]', + '.google-sign-in-button', + '.google-login-btn' + ]; + function hideGoogleSignIn() { // Add CSS to hide Google Sign-In elements const style = document.createElement('style'); style.textContent = \` /* Hide Google Sign-In button and related elements */ - [data-client_id], - .g_id_signin, - .gsi-material-button, - div[id^="g_id_"], - iframe[src*="accounts.google.com"], - iframe[src*="gsi/button"], - [aria-label*="Google"], - button[data-provider="google"], - .google-sign-in-button, - .google-login-btn { + \${GOOGLE_SIGNIN_SELECTORS.join(', ')} { display: none !important; } \`; document.head.appendChild(style); + // Build selector string for querySelectorAll + const selectorString = GOOGLE_SIGNIN_SELECTORS.join(', '); + // Find and hide any Google Sign-In buttons that might appear dynamically const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === 1) { - // Check if it's a Google Sign-In element - if (node.matches && ( - node.matches('[data-client_id]') || - node.matches('.g_id_signin') || - node.matches('.gsi-material-button') || - node.matches('iframe[src*="accounts.google.com"]') - )) { + // Check if the node itself matches + if (node.matches && node.matches(selectorString)) { node.style.display = 'none'; } // Also check children - const googleElements = node.querySelectorAll && node.querySelectorAll('[data-client_id], .g_id_signin, .gsi-material-button, iframe[src*="accounts.google.com"]'); - if (googleElements) { + if (node.querySelectorAll) { + const googleElements = node.querySelectorAll(selectorString); googleElements.forEach(el => el.style.display = 'none'); } } @@ -147,10 +151,14 @@ addEventListener('fetch', event => { } }); - observer.observe(document.body || document.documentElement, { - childList: true, - subtree: true - }); + // Wait for body to be available before observing + const targetNode = document.body || document.documentElement; + if (targetNode) { + observer.observe(targetNode, { + childList: true, + subtree: true + }); + } console.log('Google Sign-In elements hidden - use email/password to sign in'); } From 15584f6fc125e95adbabce59baad822aa36dc63c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 12:07:55 +0000 Subject: [PATCH 6/6] Implement two-phase system: Direct mode for Google Sign-In, Proxy mode for games Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- README.md | 28 ++++++-- worker.js | 199 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 130 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 8172f81..2adcaa5 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,30 @@ Cloudmoon InPlay is a simple site that proxies, hides, and loads cloudmoon in a [](https://deploy.workers.cloudflare.com/?url=https://github.com/sriail/Cloudmoon-InPlay) -## Use +## How It Works - Two-Phase System + +CloudMoon InPlay uses a **two-phase system** to allow both Google Sign-In AND game playing: + +### Phase 1: Direct Mode (Sign In) +When you first open the site, it loads CloudMoon **directly** (not through the proxy). This allows Google Sign-In to work normally because the browser connects directly to `web.cloudmoonapp.com`. -> [!IMPORTANT] -> **Google Sign-In does not work through the proxy** due to Google's OAuth 2.0 origin validation. The proxy automatically hides the Google Sign-In button to prevent errors. You must use **email and password** authentication instead. -> -> To set up email/password login: Register your CloudMoon account at home (on the official site) using Google, then go to Settings and set a password. You can then use that email/password to sign in through this proxy. +### Phase 2: Proxy Mode (Play Games) +After signing in, click the **"Enable Proxy"** button to switch to proxy mode. This routes all traffic through the Cloudflare Worker, which: +- Bypasses network restrictions +- Injects game interception code so games open in the same window +- Keeps you logged in (session persists) + +## Use -Once you sign in, you can click and play games in Cloudmoons library! -After that, you can use the upper navbar to help you navigate, cloak the site with About:Blank, and reload the site with the reload button. +1. **Sign in first**: Use Google Sign-In while in Direct Mode (green "Enable Proxy" button) +2. **Enable Proxy**: Click the "Enable Proxy" button to switch to Proxy Mode (purple "Proxy Mode" button) +3. **Play games**: Browse and click on games - they will open in the same window +4. **Use the Back button**: Return to the game library after playing +> [!TIP] +> The status bar shows which mode you're in: +> - "Direct Mode - sign in works!" = Use Google Sign-In here +> - "Proxy Mode - games work!" = Play games here > [!NOTE] > When Cloudmoon tries to open a new Tab, it will open in the central iframe to avoid being blocked. diff --git a/worker.js b/worker.js index c5a5fba..786fba2 100644 --- a/worker.js +++ b/worker.js @@ -101,76 +101,7 @@ addEventListener('fetch', event => { return originalOpen.call(this, url, target, features); }; - // Hide Google Sign-In buttons and show alternative message - // Google OAuth doesn't work through proxies due to origin validation - - // Selectors for Google Sign-In elements (used in CSS and JS) - const GOOGLE_SIGNIN_SELECTORS = [ - '[data-client_id]', - '.g_id_signin', - '.gsi-material-button', - 'div[id^="g_id_"]', - 'iframe[src*="accounts.google.com"]', - 'iframe[src*="gsi/button"]', - '[aria-label*="Google"]', - 'button[data-provider="google"]', - '.google-sign-in-button', - '.google-login-btn' - ]; - - function hideGoogleSignIn() { - // Add CSS to hide Google Sign-In elements - const style = document.createElement('style'); - style.textContent = \` - /* Hide Google Sign-In button and related elements */ - \${GOOGLE_SIGNIN_SELECTORS.join(', ')} { - display: none !important; - } - \`; - document.head.appendChild(style); - - // Build selector string for querySelectorAll - const selectorString = GOOGLE_SIGNIN_SELECTORS.join(', '); - - // Find and hide any Google Sign-In buttons that might appear dynamically - const observer = new MutationObserver((mutations) => { - for (const mutation of mutations) { - for (const node of mutation.addedNodes) { - if (node.nodeType === 1) { - // Check if the node itself matches - if (node.matches && node.matches(selectorString)) { - node.style.display = 'none'; - } - // Also check children - if (node.querySelectorAll) { - const googleElements = node.querySelectorAll(selectorString); - googleElements.forEach(el => el.style.display = 'none'); - } - } - } - } - }); - - // Wait for body to be available before observing - const targetNode = document.body || document.documentElement; - if (targetNode) { - observer.observe(targetNode, { - childList: true, - subtree: true - }); - } - - console.log('Google Sign-In elements hidden - use email/password to sign in'); - } - - // Run when DOM is ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', hideGoogleSignIn); - } else { - hideGoogleSignIn(); - } - - console.log('CloudMoon Proxy Active'); + console.log('CloudMoon Proxy Active - Game Interception Enabled'); })(); @@ -281,6 +212,22 @@ addEventListener('fetch', event => { background: #238636; } + #proxy-btn { + background: #238636; + } + + #proxy-btn:hover { + background: #2ea043; + } + + #proxy-btn.proxied { + background: #6e40c9; + } + + #proxy-btn.proxied:hover { + background: #8957e5; + } + .icon { width: 16px; height: 16px; @@ -342,7 +289,13 @@ addEventListener('fetch', event => { CloudMoon InPlay -