Bypass Roo
// ==UserScript==
// @name Roo Web Master
// @description Bypass Roo
// @match http://*/*
// @match https://*/*
// @run-at document-start
// @version 0.0.1.20260610050048
// @namespace https://greasyfork.org/users/1611219
// ==/UserScript==
(() => {
"use strict";
const code = `
(() => {
"use strict";
const DEBUG = true;
const HEADERS_TO_SET = {
"x-roo-client": "consumer-app",
"x-roo-platform": "ios"
};
const TARGET_METHODS = ["*"];
const TARGET_URL_PATTERN = /.*/;
function log(...args) {
if (DEBUG) {
console.log("[Roo headers]", ...args);
}
}
function normaliseUrl(url) {
try {
return new URL(String(url), location.href).href;
} catch {
return String(url);
}
}
function shouldModify(url, method) {
const fullUrl = normaliseUrl(url);
const upperMethod = String(method || "GET").toUpperCase();
const methodMatches =
TARGET_METHODS.includes("*") ||
TARGET_METHODS.map(m => m.toUpperCase()).includes(upperMethod);
return methodMatches && TARGET_URL_PATTERN.test(fullUrl);
}
function editHeaders(headersLike) {
const headers = new Headers(headersLike || {});
for (const [name, value] of Object.entries(HEADERS_TO_SET)) {
headers.set(name, value);
}
return headers;
}
function isManagedHeader(name) {
const lowerName = String(name).toLowerCase();
return Object.keys(HEADERS_TO_SET).some(
headerName => headerName.toLowerCase() === lowerName
);
}
/*
Patch fetch()
*/
const originalFetch = window.fetch;
window.fetch = function patchedFetch(input, init = {}) {
let url;
let method;
let originalHeaders;
if (input instanceof Request) {
url = input.url;
method = init.method || input.method || "GET";
originalHeaders = init.headers || input.headers;
} else {
url = input;
method = init.method || "GET";
originalHeaders = init.headers;
}
if (!shouldModify(url, method)) {
return originalFetch.call(this, input, init);
}
log("patching fetch", method, normaliseUrl(url), HEADERS_TO_SET);
const newInit = {
...init,
method,
headers: editHeaders(originalHeaders)
};
if (input instanceof Request) {
return originalFetch.call(this, new Request(input, newInit));
}
return originalFetch.call(this, input, newInit);
};
/*
Patch XMLHttpRequest
*/
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.open = function patchedOpen(method, url, ...rest) {
this.__rooHeaderUrl = url;
this.__rooHeaderMethod = method;
this.__rooHeaderShouldModify = shouldModify(url, method);
return originalOpen.call(this, method, url, ...rest);
};
XMLHttpRequest.prototype.setRequestHeader = function patchedSetRequestHeader(name, value) {
if (this.__rooHeaderShouldModify && isManagedHeader(name)) {
return;
}
return originalSetRequestHeader.call(this, name, value);
};
XMLHttpRequest.prototype.send = function patchedSend(body) {
if (this.__rooHeaderShouldModify) {
log("patching xhr", this.__rooHeaderMethod, normaliseUrl(this.__rooHeaderUrl), HEADERS_TO_SET);
for (const [name, value] of Object.entries(HEADERS_TO_SET)) {
originalSetRequestHeader.call(this, name, value);
}
}
return originalSend.call(this, body);
};
log("installed");
})();
`;
const script = document.createElement("script");
script.textContent = code;
const target = document.documentElement || document.head || document.body;
if (target) {
target.appendChild(script);
script.remove();
} else {
document.addEventListener("DOMContentLoaded", () => {
document.documentElement.appendChild(script);
script.remove();
}, { once: true });
}
})();