RTEx is a userscript to limit switching and visiting sites.
Warning
The password protection is not secure, it stores the raw password. The password can be leaked and the settings can be changed via the console.
RTEx is a userscript to limit switching and visiting sites.
Warning
The password protection is not secure, it stores the raw password. The password can be leaked and the settings can be changed via the console.
// ==UserScript== | |
// @name RTEx | |
// @version 2024-01-15 | |
// @description try to take over the world! | |
// @author romw314 | |
// @match http*://*/* | |
// @exclude /turbowarp\.org/ | |
// @exclude /scratch\.mit\.edu/ | |
// @exclude /localhost/ | |
// @exclude /xcratch\.github\.io/ | |
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | |
// @grant window.focus | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_deleteValue | |
// @sandbox JavaScript | |
// ==/UserScript== | |
(function() { | |
(async function() { | |
const bgc = 'orange'; | |
const text = 'RTEx Loading...'; | |
document.body.innerHTML += ` | |
<div id="rtex-on" style="z-index:1000;position:fixed;top:0;left:50%;transform:translateX(-50%);background-color:${bgc};color:black;padding:10px;width:auto;">${text}</div> | |
<div id="rtex-container" style="z-index:1000;display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background-color:lightgreen;border:5px solid green;padding:20px;margin:20px;color:black;width:auto;"> | |
<h3>RTEx <span id="rtex-x" style="color:red;cursor:hand;">✕</span></h3> | |
<ul> | |
<li><input id="rtex-cb" type="checkbox" /><label for="rtex-cb" style="z-index:1003;">Always have focus</label></li> | |
<li><input id="rtex-block" type="checkbox" /><label for="rtex-block" style="z-index:1003;">Block other sites (will not affect sites that are already open, will only block HTTP and HTTPS sites)</label></li> | |
<li>Password protection<ul> | |
<li><strong>WARNING: The password protection is not secure at all - it stores the password without a hash and checks it only when opening the UI.</strong></li> | |
<li><input id="rtex-pass" type="password" placeholder="Enter password..." /><label for="rtex-pass">Password; Use <strong>New password</strong> instead to set password (use this for old password and login).</label></li> | |
<li><input id="rtex-pass-next" type="password" placeholder="Enter password..." /><label for="rtex-pass">New password; Use only for setting new password.</label></li> | |
<li><button id="rtex-setpassword">Set password</button></li> | |
<li><button id="rtex-removepassword">Remove password</button></li> | |
</ul></li> | |
</ul> | |
</div> | |
`; | |
unsafeWindow.rtex = (state) => { | |
const cb = document.getElementById('rtex-cb'); | |
const block = document.getElementById('rtex-block'); | |
const on = document.getElementById('rtex-on'); | |
const pass = document.getElementById('rtex-pass'); | |
const newPass = document.getElementById('rtex-pass-next'); | |
const container = document.getElementById('rtex-container'); | |
const closeX = document.getElementById('rtex-x'); | |
const setpassword = document.getElementById('rtex-setpassword'); | |
const removepassword = document.getElementById('rtex-removepassword'); | |
if (state === 'init') { | |
on.addEventListener('click', () => unsafeWindow.rtex(true)); | |
cb.addEventListener('change', () => unsafeWindow.rtex('cbch')); | |
block.addEventListener('change', () => unsafeWindow.rtex('block')); | |
block.checked = Boolean(GM_getValue('onesite')); | |
unsafeWindow.rtex('block'); | |
closeX.addEventListener('click', () => unsafeWindow.rtex(false)); | |
setpassword.addEventListener('click', () => unsafeWindow.rtex('setpassword')); | |
removepassword.addEventListener('click', () => unsafeWindow.rtex('removepassword')); | |
on.innerText = 'RTEx'; | |
on.style.backgroundColor = 'lightgreen'; | |
} | |
else if (state === 'cbch') { | |
if (unsafeWindow.rtex_interval) { | |
const password = GM_getValue('password'); | |
if (password && pass.value !== password) { | |
cb.checked = true; | |
unsafeWindow.alert('Wrong password'); | |
return; | |
} | |
clearInterval(unsafeWindow.rtex_interval); | |
} | |
if (cb.checked) { | |
unsafeWindow.rtex_interval = setInterval(() => window.focus(), 200); | |
} | |
} | |
else if (state === 'block') { | |
if (block.checked) { | |
GM_setValue('onesite', unsafeWindow.location.hostname); | |
} else { | |
const password = GM_getValue('password'); | |
if (password && pass.value !== password) { | |
block.checked = true; | |
unsafeWindow.alert('Wrong password'); | |
return; | |
} | |
GM_deleteValue('onesite'); | |
} | |
} | |
else if (state === 'setpassword') { | |
const password = GM_getValue('password'); | |
if (password && pass.value !== password) { | |
unsafeWindow.alert('Wrong password'); | |
return; | |
} | |
const newPassword = newPass.value; | |
if (newPassword.length < 3) { | |
unsafeWindow.alert('Must be at least 3 characters'); | |
return; | |
} | |
GM_setValue('password', newPassword); | |
unsafeWindow.alert('Password added successfully'); | |
} | |
else if (state === 'removepassword') { | |
const password = GM_getValue('password'); | |
if (password && pass.value !== password) { | |
unsafeWindow.alert('Wrong password'); | |
return; | |
} | |
GM_deleteValue('password'); | |
unsafeWindow.alert('Password removed successfully'); | |
} | |
else { | |
on.style.display = state ? 'none' : 'block'; | |
container.style.display = state ? 'block' : 'none'; | |
} | |
} | |
const notwork = []; // array of hostnames that don't work | |
if (!(function() { | |
if (notwork.includes(unsafeWindow.location.hostname)) { | |
return false; | |
} | |
return Boolean(unsafeWindow.rtex); | |
})()) { | |
throw new Error('Unknown error'); | |
} | |
console.log('RTEx window ok', unsafeWindow.rtex); | |
const onesite = GM_getValue('onesite'); | |
if (onesite && onesite !== unsafeWindow.location.hostname) { | |
document.body.innerHTML = '<h1>RTEx Block</h1><p>Site blocked by RTEx.</p><p>RTEx is created by <a href="https://romw314.github.io">romw314</a>.</p>'; | |
return; | |
} | |
unsafeWindow.rtex('init'); | |
})().catch(function(err) { | |
try { | |
const on = document.getElementById('rtex-on'); | |
on.innerText = `RTEx ${err.name}: ${err.message}`; | |
} catch { | |
unsafeWindow.alert(`RTEx ${err.name}: ${err.message}`); | |
} | |
}); | |
})(); |