Skip to content

Instantly share code, notes, and snippets.

@Justman100
Created February 16, 2025 17:12
Show Gist options
  • Save Justman100/d210d1f99fe08bb50f3fdb4ff494e69b to your computer and use it in GitHub Desktop.
Save Justman100/d210d1f99fe08bb50f3fdb4ff494e69b to your computer and use it in GitHub Desktop.
Clears/Deletes all registered commands by a Discord bot app
#!/usr/bin/env node
import { REST, Routes } from "discord.js";
import chalk from "chalk";
import ora from "ora";
import readline from "readline";
import { argv } from "process";
class CommandCleaner {
constructor(token) {
this.token = token;
this.rest = null;
this.applicationId = null;
}
async initialize() {
try {
this.rest = new REST({ version: "10" }).setToken(this.token);
const app = await this.rest.get(Routes.oauth2CurrentApplication());
this.applicationId = app.id;
return true;
} catch (error) {
console.error(chalk.red("Error: Invalid token provided"));
console.log("\nMake sure to:");
console.log("1. Use the bot token, not the client secret");
console.log("2. Copy the entire token correctly");
console.log("3. Enable the applications.commands scope for your bot");
return false;
}
}
async getRegisteredCommands() {
try {
return await this.rest.get(
Routes.applicationCommands(this.applicationId),
);
} catch (error) {
console.error(chalk.red(`Error fetching commands: ${error.message}`));
return [];
}
}
async deleteCommand(commandId) {
try {
await this.rest.delete(
Routes.applicationCommand(this.applicationId, commandId),
);
return true;
} catch (error) {
console.error(
chalk.red(`Error deleting command ${commandId}: ${error.message}`),
);
return false;
}
}
}
function getTokenFromArgs() {
const args = {};
for (let i = 2; i < argv.length; i++) {
if (argv[i] === "--token" && i + 1 < argv.length) {
args.token = argv[i + 1];
i++;
} else if (argv[i] === "--yes" || argv[i] === "-y") {
args.yes = true;
} else if (argv[i] === "--help" || argv[i] === "-h") {
console.log(chalk.blue("Discord Slash Commands Cleanup Utility\n"));
console.log("Usage: node clear-commands.js [options]\n");
console.log("Options:");
console.log(" --token TOKEN Discord bot token");
console.log(" --yes, -y Skip confirmation prompts");
console.log(" --help, -h Show this help message");
process.exit(0);
}
}
return args;
}
async function promptForInput(question) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
try {
return await new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer.trim());
});
});
} catch (error) {
rl.close();
return null;
}
}
async function getToken() {
const args = getTokenFromArgs();
// Try command line argument first
if (args.token) {
return { token: args.token, skipConfirmation: args.yes };
}
// Try environment variable
if (process.env.DISCORD_BOT_TOKEN) {
return { token: process.env.DISCORD_BOT_TOKEN, skipConfirmation: args.yes };
}
// Show instructions
console.log(chalk.yellow("\nTo get your bot token:"));
console.log("1. Go to https://discord.com/developers/applications");
console.log("2. Select your application");
console.log("3. Go to the 'Bot' section");
console.log("4. Click 'Reset Token' or 'Copy' under the token section");
console.log(
chalk.yellow(
"\nNote: Make sure your bot has the 'applications.commands' scope enabled",
),
);
console.log(chalk.yellow("\nYou can provide the token in three ways:"));
console.log("1. As a command line argument: --token YOUR_TOKEN");
console.log("2. As an environment variable: DISCORD_BOT_TOKEN=YOUR_TOKEN");
console.log("3. Interactive input (if available)");
// Try interactive input as last resort
try {
const token = await promptForInput(
chalk.yellow("\nPlease enter your bot token: "),
);
return { token: token || null, skipConfirmation: args.yes };
} catch {
console.log(chalk.yellow("\nNo token provided through interactive input."));
return { token: null, skipConfirmation: args.yes };
}
}
async function main() {
console.log(chalk.blue.bold("Discord Slash Commands Cleanup Utility"));
console.log("━".repeat(50));
const { token, skipConfirmation } = await getToken();
if (!token) {
console.error(chalk.red("No token provided. Exiting..."));
return;
}
const cleaner = new CommandCleaner(token);
// Initialize the client
const initSpinner = ora("Initializing...").start();
if (!(await cleaner.initialize())) {
initSpinner.fail();
return;
}
initSpinner.succeed();
// Fetch registered commands
const fetchSpinner = ora("Fetching registered commands...").start();
const commands = await cleaner.getRegisteredCommands();
fetchSpinner.stop();
if (!commands.length) {
console.log(chalk.yellow("No slash commands found."));
return;
}
// Display found commands
console.log(chalk.green("\nFound the following slash commands:"));
commands.forEach((cmd) => {
console.log(`- ${cmd.name}: ${cmd.description}`);
});
// Confirm deletion
if (!skipConfirmation) {
try {
const answer = await promptForInput(
chalk.red("\nDo you want to delete all these commands? (y/n): "),
);
if (answer.toLowerCase() !== "y") {
console.log(chalk.yellow("Operation cancelled by user."));
return;
}
} catch {
console.log(
chalk.yellow("\nOperation cancelled due to no input available."),
);
return;
}
}
// Delete commands
const deleteSpinner = ora("Deleting commands...").start();
for (const cmd of commands) {
if (await cleaner.deleteCommand(cmd.id)) {
deleteSpinner.text = `Deleting commands...\n${chalk.green(`Successfully deleted command: ${cmd.name}`)}`;
} else {
console.log(chalk.red(`Failed to delete command: ${cmd.name}`));
}
}
deleteSpinner.succeed("Command cleanup completed!");
}
main().catch((error) => {
console.error(chalk.red(`An unexpected error occurred: ${error.message}`));
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment