PDS CORS Reload Workaround
pdscors.js
92 lines 3.5 kB view raw
1// ==UserScript== 2// @name PDS CORS Reload Workaround 3// @namespace Violentmonkey Scripts 4// @match https://pds-nd.whey.party/oauth/authorize* 5// @grant none 6// @version 1.3 7// @author - 8// @description Reliably bypasses the 'sec-fetch-site' error by using a MutationObserver to wait for the error message and then triggering a cross-site reload via a hidden iframe. 9// ==/UserScript== 10 11(function () { 12 'use strict'; 13 14 // Use a session storage flag to prevent an infinite redirect loop. 15 const retryKey = '__cors_workaround_attempted__'; 16 17 // 1. ABORT if we've already tried the fix in this session. 18 // This is the most important check to prevent loops. 19 if (sessionStorage.getItem(retryKey)) { 20 console.log("[Workaround] Already attempted a fix in this session. Aborting."); 21 // The page has reloaded. We now assume it's either fixed or has a different error. 22 // We clear the key so that a manual refresh by the user can trigger the script again. 23 sessionStorage.removeItem(retryKey); 24 return; 25 } 26 27 // 2. Define the keywords that identify the specific error message. 28 const TARGET_KEYWORDS = [ 29 'Forbidden sec-fetch-site header', 30 'same-site', 31 'expected cross-site', 32 ]; 33 34 // The function that performs the fix. 35 function triggerFix() { 36 console.log("[Workaround] Error detected in DOM. Initiating cross-site reload via hidden iframe."); 37 38 // Set the flag BEFORE navigating to prevent a loop if the fix fails. 39 sessionStorage.setItem(retryKey, '1'); 40 41 const iframe = document.createElement('iframe'); 42 iframe.style.display = 'none'; 43 iframe.src = `data:text/html,<script>window.top.location.replace(${JSON.stringify(location.href)});</script>`; 44 document.body.appendChild(iframe); 45 } 46 47 // 3. The CORE LOGIC: Use a MutationObserver to watch for the error. 48 // This solves the race condition where the error message is added dynamically. 49 const observer = new MutationObserver((mutations, obs) => { 50 const bodyText = document.body.textContent || ''; 51 const isErrorPage = TARGET_KEYWORDS.every(k => bodyText.includes(k)); 52 53 if (isErrorPage) { 54 // Error found! Trigger the fix. 55 triggerFix(); 56 // IMPORTANT: Stop observing once we've acted. 57 obs.disconnect(); 58 } 59 }); 60 61 // 4. Start observing. 62 // We need to wait for the <body> to exist before we can observe it. 63 function startObserver() { 64 if (document.body) { 65 console.log("[Workaround] Observer started. Waiting for 'same-site' error to appear..."); 66 // Also do an initial check, in case the error is already present. 67 const initialBodyText = document.body.textContent || ''; 68 if (TARGET_KEYWORDS.every(k => initialBodyText.includes(k))) { 69 triggerFix(); 70 return; // No need to observe if we fix it instantly. 71 } 72 73 observer.observe(document.body, { 74 childList: true, // Watch for added/removed nodes (like the error <dd>) 75 subtree: true, // Watch all descendants of the body 76 }); 77 } else { 78 // If body isn't ready, wait for DOMContentLoaded. 79 window.addEventListener("DOMContentLoaded", startObserver, { once: true }); 80 } 81 } 82 83 startObserver(); 84 85 // Safety net: Stop observing after 10 seconds if nothing happens, 86 // to prevent it from running forever on a page that is just slow to load. 87 setTimeout(() => { 88 observer.disconnect(); 89 console.log("[Workaround] Observer timed out after 10 seconds. Assuming no error or a different issue."); 90 }, 10000); 91 92})();