Hides recursion access unless RC potential meets a user-defined target.
// ==UserScript==
// @name DeepCo Recursion Gatekeeper
// @namespace https://deepco.app/
// @version 2026-05-02
// @author M3P / ChatGPT
// @license MIT
// @description Hides recursion access unless RC potential meets a user-defined target.
// @match https://deepco.app/dig
// @icon https://www.google.com/s2/favicons?sz=64&domain=deepco.app
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// ==/UserScript==
(() => {
'use strict';
const KEY = 'deepco_gatekeeper_v1';
function parseNumber(str) {
if (!str) return NaN;
return Number(
str
.replace(/[^\d.,-]/g, '')
.replace(/,/g, '')
);
}
function getRC() {
const el = document.querySelector('[data-role="rc-potential"]');
if (!el) return null;
return parseNumber(el.textContent);
}
function getData() {
return GM_getValue(KEY, null);
}
function setData(obj) {
GM_setValue(KEY, obj);
}
function clearData() {
GM_deleteValue(KEY);
}
function formatDuration(ms) {
const s = Math.floor(ms / 1000);
const h = Math.floor(s / 3600);
const m = Math.floor((s % 3600) / 60);
return `${h}h ${m}m`;
}
function estimateETA(data, current) {
if (!data || !data.baseRC) return null;
const elapsed = Date.now() - data.timestamp;
if (elapsed <= 0) return null;
const delta = current - data.baseRC;
if (delta <= 0) return null;
const rate = delta / elapsed; // RC per ms
const remaining = data.target - current;
if (remaining <= 0) return 0;
const eta = remaining / rate;
return eta;
}
function openDialog() {
const current = getRC();
const data = getData();
let info = '';
if (data) {
const elapsed = Date.now() - data.timestamp;
const eta = estimateETA(data, current);
info =
`Current target: ${data.target}
Elapsed: ${formatDuration(elapsed)}
ETA: ${eta ? formatDuration(eta) : 'N/A'}
(Leave blank to clear)`;
} else {
info = '(Leave blank to cancel)';
}
const input = prompt(
`Set target RC\n\n${info}`,
data?.target ?? ''
);
// User hit cancel → do nothing
if (input === null) return;
// Empty input → clear stored data
if (!input.trim()) {
clearData();
render();
return;
}
const parsed = parseNumber(input);
if (!Number.isFinite(parsed)) {
alert('Invalid number');
return;
}
setData({
target: parsed,
timestamp: Date.now(),
baseRC: current
});
render();
}
function render() {
const li = document.querySelector('[data-tutorial-target="sidebarRecursion"]');
if (!li) return;
if (document.getElementById('gatekeeper-li')) return;
const newLi = document.createElement('li');
newLi.id = 'gatekeeper-li';
const btn = document.createElement('button');
btn.className = 'btn btn-ghost btn-sm w-full justify-between gap-2';
const label = document.createElement('span');
label.textContent = 'GateKeeper';
label.className = 'font-semibold tracking-widest uppercase text-xs'
const value = document.createElement('span');
const data = getData();
const current = getRC();
if (!data) {
value.textContent = 'UNSET';
value.className = 'text-primary';
} else {
const pct = current / data.target;
value.textContent = `${(pct * 100).toFixed(1)}%`;
value.className = pct >= 1 ? 'text-success' : 'text-error';
}
btn.appendChild(label);
btn.appendChild(value);
btn.addEventListener('click', openDialog);
newLi.appendChild(btn);
li.parentNode.insertBefore(newLi, li.nextSibling);
}
function blockIfNeeded() {
const data = getData();
if (!data) return;
const current = getRC();
if (current == null) return;
if (current >= data.target) return;
const header = document.querySelector('#recursion-header');
if (!header) return;
header.removeAttribute('href');
header.addEventListener('click', (e) => {
e.preventDefault();
showNo();
});
}
function showNo() {
const container = document.createElement('div');
Object.assign(container.style, {
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
padding: '1.5rem 2.25rem',
borderRadius: '0.75rem',
// Strong contrast background
background: 'rgba(0, 0, 0, 0.9)',
// Visual separation
boxShadow: '0 16px 60px rgba(0,0,0,0.6)',
border: '1px solid rgba(255,255,255,0.12)',
zIndex: 2147483647,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
});
const text = document.createElement('span');
text.textContent = 'NO!';
text.className = 'gradient-rainbow';
Object.assign(text.style, {
fontSize: '2.75rem',
fontWeight: '800',
letterSpacing: '0.05em',
lineHeight: '1'
});
container.appendChild(text);
document.body.appendChild(container);
// Optional subtle pop-in
container.animate(
[
{ transform: 'translate(-50%, -60%) scale(0.85)', opacity: 0 },
{ transform: 'translate(-50%, -50%) scale(1)', opacity: 1 }
],
{ duration: 120, easing: 'ease-out' }
);
setTimeout(() => container.remove(), 1000);
}
function observe() {
const mo = new MutationObserver(() => {
if (!document.querySelector('[data-role="rc-potential"]')) return;
render();
blockIfNeeded();
mo.disconnect();
});
mo.observe(document.body, { childList: true, subtree: true });
}
observe();
})();