Skip to content

Instantly share code, notes, and snippets.

@logan-mcgee
Last active July 15, 2025 14:26
Show Gist options
  • Save logan-mcgee/13d11f6e251e1ab7ceeeb900f6c291fe to your computer and use it in GitHub Desktop.
Save logan-mcgee/13d11f6e251e1ab7ceeeb900f6c291fe to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Social Club Downgrader
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Downgrades socialclub to bring back wall / user functionality
// @author logan
// @match *://socialclub.rockstargames.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
const newPrefix = 'https://s.rsg.sc/sc/js/20250617cdii/';
const newWebpackPath = 'https://s.rsg.sc/sc/js/20250617cdii/build/';
const oldPrefix = 'https://s.rsg.sc/sc/js/';
// Robust SPA-safe publicPath enforcement
let _publicPath = newWebpackPath;
Object.defineProperty(unsafeWindow, 'webpackPublicPath', {
configurable: false,
enumerable: true,
get() {
return _publicPath;
},
set(val) {
_publicPath = newWebpackPath;
}
});
unsafeWindow.webpackPublicPath = newWebpackPath;
// Patch on every navigation event (SPA)
function forcePublicPath() {
unsafeWindow.webpackPublicPath = newWebpackPath;
}
window.addEventListener('popstate', forcePublicPath);
window.addEventListener('pushstate', forcePublicPath);
window.addEventListener('replacestate', forcePublicPath);
// Patch pushState/replaceState to emit events
const origPushState = history.pushState;
history.pushState = function () {
const ret = origPushState.apply(this, arguments);
window.dispatchEvent(new Event('pushstate'));
return ret;
};
const origReplaceState = history.replaceState;
history.replaceState = function () {
const ret = origReplaceState.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
return ret;
};
function replaceScriptSrc(el) {
if (el.src && el.src.startsWith(oldPrefix)) {
el.src = newPrefix + el.src.substring(el.src.indexOf('/', oldPrefix.length) + 1);
}
}
function patchDataConfig(el) {
const dataConfig = el.getAttribute('data-config');
if (!dataConfig) return;
let obj;
try {
obj = JSON.parse(dataConfig);
} catch {
return;
}
if (
obj.uiLib &&
(obj.uiLib.webpackPath || obj.uiLib.cdnBaseUrl)
) {
if (obj.uiLib.webpackPath) obj.uiLib.webpackPath = newWebpackPath;
el.setAttribute('data-config', JSON.stringify(obj));
}
}
document.querySelectorAll('script[src]').forEach((el) => {
replaceScriptSrc(el);
patchDataConfig(el);
});
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (
node.nodeType === 1 &&
node.tagName === 'SCRIPT'
) {
replaceScriptSrc(node);
patchDataConfig(node);
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment