Claude Code से Discord Bot बनाएं: discord.js Slash Command गाइड
Claude Code और discord.js से support Discord Bot बनाएं: permissions, env vars, local run और deployment checklist.
Discord Bot सिर्फ chat demo नहीं, support workflow है
Discord Bot एक application है जो Discord server में शामिल होकर user actions पर response देता है। आसान भाषा में, यह community के अंदर automatic reception desk जैसा काम करता है। यह support request ले सकता है, छोटी FAQ answer दे सकता है, moderators को notify कर सकता है, handoff note बना सकता है, और incident को सही internal channel तक पहुंचा सकता है।
Real community में सबसे बड़ी समस्या यह नहीं होती कि लोग बात नहीं कर रहे। समस्या यह होती है कि important सवाल chat में खो जाते हैं। “setup नहीं हो रहा”, “guide कहां है”, “इस issue को कौन देखेगा”, “क्या इसे escalate करना चाहिए” जैसी बातें अगर general channel में रहती हैं, तो context खो जाता है। Application commands से वही काम structured और repeatable बनता है।
Claude Code को यहाँ सिर्फ code generator की तरह इस्तेमाल न करें। एक काम का Discord Bot command registration, environment variables, permission boundary, interaction replies, error handling, token safety और deployment checklist मांगता है। अगर prompt सिर्फ “Discord Bot बना दो” है, तो output demo जैसा होगा। अगर prompt production constraints लिखता है, तो result review करने लायक होता है।
इस article में हम discord.js से /support, /faq, और /handoff commands बनाते हैं। Bot message content intent पर depend नहीं करता, slash commands इस्तेमाल करता है, mention abuse रोकता है, और development में test server पर guild commands register करता है। Node.js version 22.12.0 या नया रखें, क्योंकि current discord.js docs यही requirement दिखाते हैं।
flowchart LR
A["User runs /support"] --> B["Discord interaction"]
B --> C["discord.js bot"]
C --> D["Ephemeral user reply"]
C --> E["Support channel message"]
E --> F["Moderator handoff"]
पहली version का goal smart AI support agent नहीं है। Goal है reliable intake path। Database, queue, LLM summary, CRM sync या paid-member check बाद में जोड़ें। पहले यह पक्का करें कि command चले, user को private reply मिले, और team को useful support note मिले।
application commands और interactions आसान भाषा में
Discord application commands वे commands हैं जो Discord client में native रूप से दिखती हैं। /support जैसा slash command सबसे common example है। यह पुराने !help style prefix commands से बेहतर है, क्योंकि Discord user को submit करने से पहले command name, description, options, choices और permissions दिखा सकता है।
Interactions वे events हैं जो user के command चलाने, button click करने, select menu इस्तेमाल करने या modal submit करने पर application तक आते हैं। discord.js और Gateway के साथ इन्हें आम तौर पर Events.InteractionCreate में handle किया जाता है। Discord HTTP endpoint के जरिए भी interactions भेज सकता है, लेकिन small team और local debugging के लिए Gateway Bot ज्यादा सीधा रास्ता है।
Rules के लिए official docs देखें। Command types, names, guild commands और global commands की details Discord Application Commands में हैं। Initial response, followup और interaction token behavior Receiving and Responding to Interactions में है। Library API और Node requirement के लिए discord.js documentation और discord.js guide देखें।
permissions, env vars और minimum architecture
Developer Portal में Discord application बनाएं, Bot user add करें, और invite URL में bot और applications.commands scopes रखें। शुरुआत administrator permission से न करें। इस Bot को support channel देखने और message भेजने की permission चाहिए। /handoff सिर्फ moderator-level users के लिए रखें, जैसे Manage Messages permission वाले members।
| Item | Value | Production note |
|---|---|---|
| Node.js | 22.12.0 या नया | current discord.js requirement |
| OAuth2 scopes | bot, applications.commands | bot और slash commands के लिए |
| Bot permissions | View Channels, Send Messages | minimum से शुरू करें |
DISCORD_TOKEN | Bot token | commit, screenshot, log में न डालें |
DISCORD_CLIENT_ID | Application ID | command registration में use |
DISCORD_GUILD_ID | Test server ID | development में guild commands |
SUPPORT_CHANNEL_ID | Internal support channel | Bot वहां send कर सके |
Claude Code prompt साफ होना चाहिए: “Node.js 22 और discord.js से support Bot बनाओ। /support, /faq, /handoff commands हों। .env use हो, development में guild commands register हों, minimum permissions, ephemeral replies और deployment checklist शामिल हो।” ऐसा prompt generic chatbot के बजाय practical project देता है।
Related internal reading के लिए environment variables guide, error handling patterns और code review checklist देखें। Bot छोटा है, लेकिन production habit वही है।
runnable discord.js starter
यह starter JavaScript ES modules में है, इसलिए TypeScript setup के बिना paste करके चलाया जा सकता है। DISCORD_GUILD_ID set है तो commands test server में register होंगे। हटाने पर global commands register होंगे। Local setup में DEPLOY_COMMANDS=true रखें; production restart में command registration को controlled deploy step बनाना बेहतर है।
mkdir discord-support-bot
cd discord-support-bot
npm init -y
npm install discord.js dotenv
mkdir src
package.json में type और start जोड़ें।
{
"type": "module",
"scripts": {
"start": "node src/bot.js"
},
"dependencies": {
"discord.js": "latest",
"dotenv": "latest"
}
}
.env बनाएं।
DISCORD_TOKEN=replace_with_bot_token
DISCORD_CLIENT_ID=replace_with_application_id
DISCORD_GUILD_ID=replace_with_test_guild_id
SUPPORT_CHANNEL_ID=replace_with_support_channel_id
DEPLOY_COMMANDS=true
src/bot.js बनाएं।
import "dotenv/config";
import {
Client,
Events,
GatewayIntentBits,
MessageFlags,
PermissionFlagsBits,
REST,
Routes,
SlashCommandBuilder,
} from "discord.js";
const token = process.env.DISCORD_TOKEN;
const clientId = process.env.DISCORD_CLIENT_ID;
const guildId = process.env.DISCORD_GUILD_ID;
const supportChannelId = process.env.SUPPORT_CHANNEL_ID;
for (const [name, value] of Object.entries({ token, clientId, supportChannelId })) {
if (!value) throw new Error(`${name} is required.`);
}
const commands = [
new SlashCommandBuilder()
.setName("support")
.setDescription("Send a support request to the team")
.addStringOption((option) =>
option
.setName("summary")
.setDescription("What happened?")
.setMaxLength(900)
.setRequired(true),
)
.addStringOption((option) =>
option
.setName("severity")
.setDescription("How urgent is it?")
.setRequired(true)
.addChoices(
{ name: "low", value: "low" },
{ name: "normal", value: "normal" },
{ name: "high", value: "high" },
),
)
.addStringOption((option) =>
option
.setName("context")
.setDescription("Steps, links, or error messages")
.setMaxLength(1500),
),
new SlashCommandBuilder()
.setName("faq")
.setDescription("Show a short answer for a common topic")
.addStringOption((option) =>
option
.setName("topic")
.setDescription("FAQ topic")
.setRequired(true)
.addChoices(
{ name: "setup", value: "setup" },
{ name: "permissions", value: "permissions" },
{ name: "rollout", value: "rollout" },
),
),
new SlashCommandBuilder()
.setName("handoff")
.setDescription("Create a moderator handoff note")
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)
.addUserOption((option) =>
option.setName("target").setDescription("User to hand off").setRequired(true),
)
.addStringOption((option) =>
option
.setName("note")
.setDescription("What should the next moderator know?")
.setMaxLength(1500)
.setRequired(true),
),
].map((command) => command.toJSON());
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (readyClient) => {
console.log(`Logged in as ${readyClient.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
try {
if (!interaction.inGuild()) {
await interaction.reply({
content: "Please use this command inside the server.",
flags: MessageFlags.Ephemeral,
});
return;
}
if (interaction.commandName === "support") await handleSupport(interaction);
else if (interaction.commandName === "faq") await handleFaq(interaction);
else if (interaction.commandName === "handoff") await handleHandoff(interaction);
else await safeReply(interaction, "Unknown command.");
} catch (error) {
console.error("Interaction failed:", error);
await safeReply(interaction, "Something went wrong. Please contact a moderator.");
}
});
async function handleSupport(interaction) {
const summary = interaction.options.getString("summary", true);
const severity = interaction.options.getString("severity", true);
const context = interaction.options.getString("context") ?? "No extra context.";
const channel = await fetchSupportChannel();
await channel.send({
content: [
"**New support request**",
`Reporter: ${interaction.user.tag} (${interaction.user.id})`,
`Severity: ${severity}`,
`Channel: <#${interaction.channelId}>`,
`Summary: ${neutralizeMentions(summary)}`,
`Context: ${neutralizeMentions(context)}`,
].join("\n"),
allowedMentions: { parse: [] },
});
await interaction.reply({
content: "Thanks. Your request was sent to the support team.",
flags: MessageFlags.Ephemeral,
});
}
async function handleFaq(interaction) {
const topic = interaction.options.getString("topic", true);
const answers = {
setup: "Install Node.js 22.12+, invite the bot with bot and applications.commands scopes, then run npm start.",
permissions: "Start with View Channels and Send Messages. Reserve Manage Messages for moderator-only commands.",
rollout: "Use guild commands for testing. Promote to global commands only after rollback and logging are checked.",
};
await interaction.reply({
content: answers[topic],
flags: MessageFlags.Ephemeral,
});
}
async function handleHandoff(interaction) {
if (!interaction.memberPermissions?.has(PermissionFlagsBits.ManageMessages)) {
await interaction.reply({
content: "You need Manage Messages permission to use this command.",
flags: MessageFlags.Ephemeral,
});
return;
}
const target = interaction.options.getUser("target", true);
const note = interaction.options.getString("note", true);
const channel = await fetchSupportChannel();
await channel.send({
content: [
"**Moderator handoff**",
`Target: ${target.tag} (${target.id})`,
`From: ${interaction.user.tag} (${interaction.user.id})`,
`Note: ${neutralizeMentions(note)}`,
].join("\n"),
allowedMentions: { parse: [] },
});
await interaction.reply({
content: "Handoff note created.",
flags: MessageFlags.Ephemeral,
});
}
async function fetchSupportChannel() {
const channel = await client.channels.fetch(supportChannelId);
if (!channel || !channel.isTextBased() || typeof channel.send !== "function") {
throw new Error("SUPPORT_CHANNEL_ID must be a text channel the bot can send to.");
}
return channel;
}
function neutralizeMentions(value) {
return value
.replaceAll("@everyone", "@ everyone")
.replaceAll("@here", "@ here")
.replace(/<@!?(\d+)>/g, "user:$1")
.replace(/<@&(\d+)>/g, "role:$1");
}
async function safeReply(interaction, content) {
const payload = { content, flags: MessageFlags.Ephemeral };
if (interaction.replied || interaction.deferred) await interaction.followUp(payload);
else await interaction.reply(payload);
}
async function deployCommands() {
const rest = new REST({ version: "10" }).setToken(token);
const route = guildId
? Routes.applicationGuildCommands(clientId, guildId)
: Routes.applicationCommands(clientId);
await rest.put(route, { body: commands });
console.log(guildId ? "Guild commands deployed." : "Global commands deployed.");
}
if (process.env.DEPLOY_COMMANDS === "true") {
await deployCommands();
}
await client.login(token);
Local test में node --version देखें, फिर npm start चलाएं। सबसे पहले /support use करें। User को private reply मिलना चाहिए और internal support channel में structured message जाना चाहिए। फिर /faq test करें। आखिर में moderator account और normal account से /handoff चलाकर permission boundary verify करें।
Use case: तीन practical workflows
पहला Use case support intake है। अच्छा command बहुत लंबे form की जरूरत नहीं रखता। Summary, severity और context काफी हैं। इससे triage शुरू हो जाता है, यानी case को answer, reproduce, assign या escalate करना है, यह तय होता है। Small test server में यह flow free-form message से बेहतर निकला, क्योंकि पहली note में urgency और reproduction hint पहले से था।
दूसरा Use case FAQ routing है। Bot को पूरी documentation chat में paste नहीं करनी चाहिए। Short answer और सही link बेहतर है। Setup issue के लिए Claude Code getting started, CLI सवालों के लिए CLI tool development, और team rules के लिए CLAUDE.md templates भेजें। इससे Bot दूसरी documentation नहीं बनता, बल्कि site navigation बनता है।
तीसरा Use case moderator handoff है। Paid community, training cohort, game server और product support में shift बदलती रहती है। “कोई देख ले” वाला message context खो देता है। /handoff target user, note लिखने वाले person और next moderator के लिए जरूरी context एक जगह रखता है।
चौथा scenario training support है। Claude Code workshop में learners अक्सर same Node version, env var या command error पर अटकते हैं। Bot पहले version, command और last log lines ले ले, तो instructor basics पूछने के बजाय diagnosis से शुरू कर सकता है। Team rollout के लिए next CTA training and consultation है।
Pitfall: production से पहले हटाने वाली गलतियां
पहला Pitfall Bot token leak है। Token Git, screenshot, CI log या article में दिख जाए तो उसे compromised मानें। Developer Portal में rotate करें और पुराना value हटाएं। Claude Code prompt में साफ लिखें कि .env.example placeholders के साथ बने और real secrets कभी print न हों।
दूसरा Pitfall development में global commands बार-बार register करना है। Guild commands सिर्फ test server पर रहते हैं और जल्दी reflect होते हैं। Global commands production surface हैं। Command names, descriptions, permissions और rollback clear होने के बाद ही उन्हें promote करें।
तीसरा Pitfall interaction branch बिना reply के छोड़ना है। User को यह broken command जैसा लगता है। हर path reply, defer या follow up करे, चाहे unknown command हो या caught error। External API या LLM summary जोड़ें तो पहले defer करें, फिर result भेजें।
चौथा Pitfall mention abuse है। User input को internal channel में raw भेजने पर @everyone, @here, user mention और role mention notification incident बना सकते हैं। Example code allowedMentions: { parse: [] } और text cleanup दोनों use करता है। दोनों रखें।
पांचवां Pitfall bot को administrator देना है। यह permission design छिपा देता है और token चोरी होने पर नुकसान बढ़ाता है। View Channels और Send Messages से शुरू करें। Extra permission तभी जोड़ें जब review में reason साफ हो।
security और deployment checklist
- Developer Portal में token rotate करने वाला owner तय है
.envGit में नहीं जाता और.env.exampleमें placeholder values हैं- Invite URL
botऔरapplications.commandsscopes से शुरू होता है - Bot permissions View Channels और Send Messages से शुरू होती हैं
/handoffसिर्फ moderators के लिए है- Guild commands test होने के बाद global commands promote होते हैं
- हर interaction path reply, defer या follow up करता है
- User input mentions trigger नहीं कर सकता
- Logs में token, payment data, email या private support data नहीं है
- Hosting Node.js 22.12.0 या नया चला रहा है
- Restart और rollback steps लिखे गए हैं
Small bot Railway, Render, Fly.io, VPS या internal server पर चल सकता है। Platform से ज्यादा जरूरी है कि secrets code से अलग हों, logs दिखें और restart documented हो। README बनवाते समय Claude Code से ये sections explicitly लिखवाएं।
Reusable templates चाहिए तो ClaudeCodeLab products देखें। Team को Discord support, Claude Code permissions, review rules और training process बनाना हो तो training and consultation देखें। Bot को real feature की तरह maintain करना है तो code review automation से भी जोड़ें।
Test करने के बाद result
Small server में starter चलाने पर सबसे बड़ा benefit bot की intelligence नहीं था। Benefit request का shape था। Free-form messages अक्सर “काम नहीं कर रहा” से शुरू होते हैं। /support summary, severity और context लेता है, इसलिए moderator का पहला reply diagnosis के करीब था। Risky areas token, global commands, mentions और permissions निकले। Claude Code तब ज्यादा useful रहा जब उससे code के साथ .env.example, permission table, error replies और deployment checklist भी बनवाई गई।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.