Skip to content

Instantly share code, notes, and snippets.

@romw314
Last active January 15, 2024 18:48
Show Gist options
  • Save romw314/e6887be02415948375fd92017100db5e to your computer and use it in GitHub Desktop.
Save romw314/e6887be02415948375fd92017100db5e to your computer and use it in GitHub Desktop.
RTEx - the userscript to limit sites

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;">&#x2715;</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}`);
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment