28 September 2026
Overview
What it does
- Scam guard: spots the image bursts hacked accounts post with @everyone, times the account out and opens a case.
- Leak guard: deletes pasted bot tokens, webhooks, cloud keys and private keys, then DMs the person instructions for revoking them.
- Honeypot channel: anyone who posts in it is banned automatically; staff accounts trigger an alert instead.
- Captcha verification, and a role-safety check that refuses to auto-assign roles carrying dangerous permissions.
Generated images




The dashboard
How it's built
- Bot: Node.js with discord.js v14 and @discordjs/voice, about 80 slash commands (roughly 250 subcommands) and 9 right-click context-menu actions.
- Dashboard: a plain Node
httpserver with no web framework, rendering HTML on the server. Every page ships with a strict Content Security Policy, and most pages run no JavaScript at all. - Login: Discord OAuth2, with access re-checked on every request.
- Images: SVG rendered to PNG with resvg, in worker threads.
- Audio: ffmpeg plus a custom PCM mixer; voice lines are generated offline with Piper text-to-speech.
- Storage: JSON files written atomically, with corrupt files quarantined rather than silently reset.
Engineering highlights
Logging in without keeping the user's token
JavaScript
async function completeLogin({ code }) {
const accessToken = await exchangeCodeForToken(code);
try {
const headers = { Authorization: `Bearer ${accessToken}` };
const [me, guilds] = await Promise.all([
discordFetch(`${API}/users/@me`, { headers }),
discordFetch(`${API}/users/@me/guilds`, { headers }),
]);
return normalise(me, guilds);
} finally {
// The token isn't needed any more: revoke it so it can't be misused.
revokeToken(accessToken).catch(() => {});
}
}Talking over the radio
JavaScript
for (let i = 0; i < chunk.length; i += 4) {
// ease the music volume towards its target (ducked while speaking)
gain += Math.sign(target - gain) * Math.min(step, Math.abs(target - gain));
let left = chunk.readInt16LE(i) * gain;
let right = chunk.readInt16LE(i + 2) * gain;
if (voice) { // mix the voice line on top
left += voice.readInt16LE(pos) * voiceGain;
right += voice.readInt16LE(pos + 2) * voiceGain;
pos += 4;
}
out.writeInt16LE(clamp16(left), i);
out.writeInt16LE(clamp16(right), i + 2);
}Only showing what you can already see
JavaScript
const als = new AsyncLocalStorage();
const runAs = (member, fn) => als.run({ member }, fn);
function viewerCanSee(channel) {
const member = als.getStore()?.member;
if (!member) return true;
return channel.permissionsFor(member)?.has(PermissionFlagsBits.ViewChannel) ?? false;
}Challenges
- Discord's 100-command limit. Dark has more features than Discord allows top-level commands, so related commands are merged under parent commands (like
/settings) while each keeps its own handler. - Not getting the bot IP-banned. Discord bans bots that make too many failed requests, so Dark counts failed requests against Discord's limit, honours rate-limit headers when retrying, and caps how often it posts per user and per server.
- Safely fetching links people post. Features that fetch URLs check the address at connect time, block private and internal ranges (including tricky IPv6 forms) and refuse redirects, so the bot can't be used to reach internal services.
- Memory. Unused caches are switched off and old messages swept, while deliberately never sweeping the bot's own member object, which permission checks depend on.
- Securing a framework-free web app by hand: CSRF tokens, single-use OAuth state,
__Host-cookies, per-IP rate limiting, body-size limits, a host allowlist and sandboxed transcripts.

