Detox of swopglow.net when accessed from https://cyclingtiz.live/
// ==UserScript==
// @name swopglow.net
// @run-at document-start
// @namespace https://github.com/GavinBrelstaff
// @description Detox of swopglow.net when accessed from https://cyclingtiz.live/
// @match https://swopglow.net/e/*
// @grant none
// @version 1.0
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// ==/UserScript==
// https://stackoverflow.com/a/76592599
// curl --referer "https://cyclingtiz.live/" "https://swopglow.net/e/1n56kvpbgvg06"
window.count=0;
new MutationObserver(async (mutations, observer) => {
const els = mutations
.flatMap(e => [...e.addedNodes])
.filter(e => e.tagName == 'SCRIPT')
for( el of els )
{
window.count++;
var safe = false;
var str = '';
if( el.type && el.type == 'importmap' )
{
safe = true;
str = el.type;
}
if( el.src && el.src.includes('clappr.min.js') )
{
safe = true;
str = el.src;
}
else if( el.src && el.src.includes('stream.js') )
{
safe = true;
el.setAttribute('defer','');
str = el.src;
}
else if( el.id && el.id == 'config' )
{
// hack the config
const LEAD_IN_STR = "window._econfig='";
const config_str = el.innerHTML.slice(LEAD_IN_STR.length,-1); // removes LEAD_IN_STR and the final '
const config_obj = decode_json_obj(config_str);
if( config_obj.stream_url_nop2p ) config_obj.p2p = false;
config_obj.sandbox_block = false;
config_obj.devtools_block = false;
config_obj.pop1 = false;
config_obj.alt_domain = true;
config_obj.hframes = [];
config_obj.pops = [];
const myStr = encode_json_obj(config_obj);
el.innerHTML = LEAD_IN_STR + myStr + "'";
safe = true;
}
//safe = false;
if( str.length <1 ) str = el.innerHTML.substring(0,40).replace(/\s*/g,'');
if( ! safe )
{
el.remove(); // kill script
console.log( window.count + 'UNSAFE: ' + str );
}
else
console.log( window.count + ' SAFE: ' + str );
}
}).observe(document, {
childList: true,
subtree: true,
})
function decode_json_obj(_econfig) { // from stream.js
if (!_econfig) return false;
const myArr = [2, 0, 3, 1], len = 4;
_econfig = atob(_econfig);
const size = _econfig.length, seg_len = Math.ceil(size / len), segArr = [];
console.log('size: ' + size);
console.log('seg_len: ' + seg_len);
let offset = 0;
for (let i = 0; i < len; i++) {
const str = _econfig.substr(offset, seg_len);
segArr.push(str), offset += seg_len;
}
//console.log( segArr );
const strArr = [];
for (let i = 0; i < myArr.length; i++) {
let str = String(segArr[i]);
str = str.slice(0, 3) + str.slice(4), // "12345" produces "1235" (drops the "4")
strArr[myArr[i]] = atob(str);
}
//console.log( strArr );
let txt = strArr.join("");
txt = atob(txt);
//console.log( txt );
try {
return JSON.parse(txt);
} catch (e) {
return false;
}
}
function encode_json_obj(jsonObj) {// reverse code by me!
if (!jsonObj) return false;
const myArr = [2, 0, 3, 1], len = 4; // Same permutation
let str = JSON.stringify(jsonObj);
str = str.replace( /\//g, '\\/'); // escape slash chars for compatibility
//console.log( str );
str = btoa(str); // Reverse final atob
const size = str.length;
const seg_len = Math.ceil(size / len);
console.log('size: ' + size);
console.log('seg_len: ' + seg_len);
// Split str into original order segments
const segArr = [];
let offset = 0;
for (let i = 0; i < len; i++) {
segArr[i] = str.substr(offset, seg_len);
offset += seg_len;
}
//console.log( segArr );
// Permute, modify (insert fixed 4th char '0'), base64 each
const strArr = [];
for (let i = 0; i < len; i++) {
let str = btoa(segArr[myArr[i]]);
strArr[i] = str.slice(0, 3) + 'a' + str.slice(3); // Insert char at pos 3 (0-indexed)
}
//console.log( strArr );
const permutedStr = strArr.join("");
const _econfig = btoa(permutedStr); // Final base64
return _econfig;
}