本文へ移動
cccskills
無料GitHub で公開

discord

Discord is a chat platform whose bot API lets programs read events, answer slash commands and post messages in servers. Use this skill to create a Discord application and bot, choose gateway intents, register slash commands, reply to interactions, send embeds and buttons, check permissions, handle rate limits, and post through webhooks or the plain REST API with discord.js 14. Triggers: "make a Discord bot", "register slash commands", "ephemeral reply", "Discord webhook", "MessageContent intent".

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skillsスター 183(GitHub 183 + cccskills 0)
連携ツールDiscord

実行スコア 未検証

インストール方法を見る

含まれるファイル(2)

  • SKILL.md13.6 KB
  • _scores.json1.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Discord — bots, slash commands and webhooks with discord.js 14

Overview

A Discord bot is an application with a bot user. It connects to the Gateway (a WebSocket that streams events such as interactions) and calls the REST API (https://discord.com/api/v10) to act. Most bots today are driven by interactions: users run slash commands or press buttons, Discord sends the bot an event, and the bot must respond within 3 seconds.

This skill targets discord.js 14 (14.27 at the time of writing), the main Node.js library. Sources: the Discord developer docs (discord.com/developers/docs), the discord.js guide (discordjs.guide) and the library reference (discord.js.org). The code below type-checks under tsc --strict against discord.js 14.27.

Two lighter options need no gateway connection: a webhook (post-only, one URL per channel) and plain REST calls with the bot token.

Instructions

1. Create the application and bot (done by a human)

An agent cannot do this step; the owner must:

  1. Open the Developer Portal (discord.com/developers/applications), choose New Application.
  2. On the General Information page copy the Application ID into DISCORD_APP_ID.
  3. On the Bot page choose Reset Token and store it in DISCORD_TOKEN. The token is shown once; anyone holding it controls the bot.
  4. Under Installation / OAuth2 URL Generator select the scopes bot and applications.commands, pick the minimum bot permissions, open the generated URL and add the bot to a server you manage.
  5. For testing, enable Developer Mode (User Settings, Advanced), right-click the server and copy its ID into DISCORD_GUILD_ID.

2. Install

mkdir release-bot && cd release-bot
npm init -y
npm install discord.js
npm install -D typescript @types/node tsx

Never commit the token. Keep DISCORD_TOKEN, DISCORD_APP_ID and DISCORD_GUILD_ID in the environment or a gitignored .env (run with node --env-file=.env).

3. Gateway intents

Intents select which events the Gateway sends. Request only what you use.

IntentPrivilegedNeeded for
Guildsnoslash commands, guild and channel cache (enough for most bots)
GuildMembersyesmember join/leave events, full member lists
GuildPresencesyesonline status, activities
MessageContentyesreading the text of messages that do not mention the bot
GuildMessages, GuildMessageReactionsnomessage and reaction events (content is empty without MessageContent)

Privileged intents must be switched on in the Bot page of the Developer Portal. Once the people who can see your app across all its servers exceed 10,000, you must also apply for Discord's approval to use them (the older "100 servers" threshold no longer applies). A slash-command bot needs none of them; do not enable them "just in case".

4. Register slash commands

Registration is a separate step from running the bot. Run it when command definitions change, not on every start.

import { REST, Routes, SlashCommandBuilder, PermissionFlagsBits } from "discord.js";

const commands = [
  new SlashCommandBuilder()
    .setName("ping")
    .setDescription("Check that the bot is alive"),
  new SlashCommandBuilder()
    .setName("ticket")
    .setDescription("Open a support ticket")
    .addStringOption((o) =>
      o.setName("topic").setDescription("What do you need help with?").setRequired(true).setMaxLength(100),
    ),
  new SlashCommandBuilder()
    .setName("purge-notes")
    .setDescription("Delete the bot's saved notes")
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
    .setContexts(0), // 0 = guild only
].map((c) => c.toJSON());

const rest = new REST({ version: "10" }).setToken(process.env.DISCORD_TOKEN!);
const appId = process.env.DISCORD_APP_ID!;
const guildId = process.env.DISCORD_GUILD_ID;

async function main() {
  // Guild commands appear instantly; global commands can take up to an hour to propagate.
  const route = guildId
    ? Routes.applicationGuildCommands(appId, guildId)
    : Routes.applicationCommands(appId);
  const registered = (await rest.put(route, { body: commands })) as unknown[];
  console.log(`Registered ${registered.length} commands`);
}
main();
  • PUT replaces the whole command set for that scope, so omitted commands are deleted.
  • Develop against guild commands (instant). Ship global commands once stable, by leaving DISCORD_GUILD_ID unset.
  • setDefaultMemberPermissions only sets the default; server admins can override it in Server Settings, so still check permissions in code for dangerous actions.
  • Limits: 100 global chat-input commands, 25 options per command, 25 choices per option.

5. Handle interactions and reply

import {
  ActionRowBuilder, ButtonBuilder, ButtonStyle, Client, EmbedBuilder,
  Events, GatewayIntentBits, MessageFlags,
} from "discord.js";

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, (c) => {
  console.log(`Logged in as ${c.user.tag}`);
});

client.on(Events.InteractionCreate, async (interaction) => {
  if (interaction.isChatInputCommand()) {
    if (interaction.commandName === "ping") {
      await interaction.reply({ content: "Pong", flags: MessageFlags.Ephemeral });
      return;
    }
    if (interaction.commandName === "ticket") {
      const topic = interaction.options.getString("topic", true);
      await interaction.deferReply({ flags: MessageFlags.Ephemeral }); // 3 s limit to first response
      const embed = new EmbedBuilder()
        .setTitle(`Ticket: ${topic}`)
        .setDescription(`Opened by ${interaction.user}`)
        .setColor(0x5865f2)
        .addFields({ name: "Status", value: "Open", inline: true });
      const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
        new ButtonBuilder().setCustomId("ticket:close").setLabel("Close").setStyle(ButtonStyle.Danger),
      );
      await interaction.editReply({ embeds: [embed], components: [row] });
    }
    return;
  }
  if (interaction.isButton() && interaction.customId === "ticket:close") {
    await interaction.update({ content: "Ticket closed", components: [] });
  }
});

client.login(process.env.DISCORD_TOKEN);

Rules that cause most bugs:

  • Respond within 3 seconds: reply() or deferReply() first. After deferring you have 15 minutes (the interaction token lifetime) to editReply() or followUp().
  • Ephemeral replies (visible only to the invoker) use flags: MessageFlags.Ephemeral. The old ephemeral: true option is deprecated.
  • Each interaction is answered once; further messages use followUp().
  • Button, select-menu and modal interactions are separate types: test with isButton(), isStringSelectMenu(), isModalSubmit(). Put routing data in customId (max 100 characters), for example ticket:close:4812.
  • Wrap handlers in try/catch; an uncaught rejection in an event handler can crash the process.

6. Embeds and components

  • One message holds up to 10 embeds and 5 action rows. A row holds up to 5 buttons or exactly one select menu.
  • Embed limits: title 256, description 4096, 25 fields, field value 1024, 6000 characters in total across all embeds in a message.
  • Button styles: Primary, Secondary, Success, Danger, and Link (needs setURL, has no customId).
  • Modals (ModalBuilder with TextInputBuilder) are opened with interaction.showModal() and must be the first response to that interaction.

7. Permissions

  • Bot permissions are granted by the invite URL and by roles. Check before acting: interaction.appPermissions?.has(PermissionFlagsBits.ManageMessages).
  • Check the invoker with interaction.memberPermissions?.has(PermissionFlagsBits.BanMembers).
  • A bot can manage only members and roles below its highest role. If a role action fails with "Missing Permissions" (error code 50013), move the bot's role higher in Server Settings, Roles.
  • Request least privilege: avoid Administrator.

8. Webhooks (post-only, no bot)

Create one in Channel Settings, Integrations, Webhooks, and store the URL in DISCORD_WEBHOOK_URL. The URL itself is the credential.

import { WebhookClient } from "discord.js";

export async function notify(text: string) {
  const hook = new WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL! });
  await hook.send({ content: text, username: "Deploy bot" });
}

Webhooks can send embeds, but cannot receive commands or read messages.

9. Plain REST with a bot token

Use this from scripts or serverless jobs that only post. Authorization is Bot <token>; Discord asks for a descriptive User-Agent of the form DiscordBot (url, version).

const token = process.env.DISCORD_TOKEN!;

async function discord(path: string, init: RequestInit = {}) {
  const res = await fetch(`https://discord.com/api/v10${path}`, {
    ...init,
    headers: {
      Authorization: `Bot ${token}`,
      "Content-Type": "application/json",
      "User-Agent": "DiscordBot (https://github.com/acme-games/release-bot, 1.0.0)",
      ...init.headers,
    },
  });
  if (res.status === 429) {
    const body = (await res.json()) as { retry_after: number };
    await new Promise((r) => setTimeout(r, body.retry_after * 1000));
    return discord(path, init);
  }
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return res.status === 204 ? null : res.json();
}

export const postMessage = (channelId: string, content: string) =>
  discord(`/channels/${channelId}/messages`, {
    method: "POST",
    body: JSON.stringify({ content, allowed_mentions: { parse: [] } }),
  });

10. Rate limits

  • Global limit: 50 requests per second per bot, plus per-route buckets reported in X-RateLimit-* headers.
  • On HTTP 429 the body carries retry_after (seconds); wait that long. Repeated invalid requests (401, 403, 429) can get the IP banned by Cloudflare, so never loop on failures.
  • discord.js queues and retries REST calls for you; hand-written fetch code must do it itself, as above.
  • Do not edit a message or bulk-send in tight loops; batch with bulkDelete (up to 100 messages, none older than 14 days).

Examples

Example 1: A /ticket command for a game community

Request: "Add a /ticket command to our bot. It takes a topic, replies privately with an embed and a Close button."

Steps the agent takes:

npm install discord.js && npm install -D typescript @types/node tsx
export DISCORD_TOKEN="..." DISCORD_APP_ID="1234567890123456789" DISCORD_GUILD_ID="9876543210987654321"
npx tsx src/deploy.ts   # code from section 4
npx tsx src/bot.ts      # code from section 5

(Set the three variables from the Developer Portal in your own shell; the agent never invents or prints them.)

Result: deploy.ts prints Registered 3 commands. In the server, /ticket topic:Cannot join voice shows only to the member an embed "Ticket: Cannot join voice" with a red Close button; pressing it replaces the message with "Ticket closed" and removes the button.

Example 2: Post a release note from CI without running a bot

Request: "When a release is tagged, post a message to #releases."

// scripts/announce.ts, run in the release job with DISCORD_WEBHOOK_URL set from CI secrets
import { WebhookClient } from "discord.js";

const hook = new WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL! });
await hook.send({
  content: "Release 2.4.0 is live: dark mode, faster search, 14 bug fixes",
  username: "Release bot",
});
npx tsx scripts/announce.ts

Result: the message appears in #releases under the name "Release bot". If the webhook was deleted, Discord answers 404 (Unknown Webhook); the fix is to create a new one.

Guidelines

  • Prefer slash commands and components over reading message text. They need no privileged intent and work with Discord's built-in permission UI.
  • Enable MessageContent only if you truly parse arbitrary messages; verify the toggle in the Developer Portal when message content arrives empty.
  • Keep tokens and webhook URLs in environment variables. If one leaks, reset the token or delete the webhook immediately; do not paste them into chat, logs or screenshots.
  • Disable unwanted pings on bot output: set allowedMentions: { parse: [] } (discord.js) or allowed_mentions (REST) when echoing user text, otherwise @everyone in user input will fire.
  • Always validate user input from slash options; treat it as untrusted text.
  • Run one gateway connection per shard; a single process is fine under 2,500 servers, beyond that use ShardingManager.
  • Discord changes the API; check GET /gateway/bot and the changelog at discord.com/developers/docs/change-log when behavior shifts, and pin the discord.js minor version in package.json.
  • Not for: user-account automation (self-bots violate the Terms of Service), scraping servers, or sending unsolicited DMs.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Scripts and configures production rendering in Autodesk 3ds Max with the V-Ray and Corona renderers: output size and files, render elements, denoising, light mix, batch and command-line rendering, and network rendering. Use when a user asks to set up a production render, render several cameras in one batch, render from the command line or on a render farm, add render passes for compositing, or cut render time for archviz and product shots.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

Covers scripting Autodesk 3ds Max, the 3D modeling and rendering application, with MAXScript and Python (pymxs): scene manipulation, object creation, material assignment, camera and light setup, batch operations, and file I/O. Use when tasks involve automating repetitive 3ds Max workflows, batch processing scenes, running scripts headless with 3dsmaxbatch, creating custom tools, or scripting scene setup for archviz, product visualization, or VFX.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

3proxy

無料

3proxy is a small open-source proxy server that runs HTTP/HTTPS, SOCKS4/5, SNI and TCP/UDP port-mapping proxies from one config file. Use when a user asks to set up an HTTP or SOCKS5 proxy, add proxy users and passwords, write 3proxy access rules, chain or rotate upstream (parent) proxies, limit bandwidth, connections or monthly traffic per user, run 3proxy in Docker, or fix a 3proxy.cfg that will not start.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

Builds Agent2Agent (A2A) servers and clients, the open protocol (originally from Google, now under the Linux Foundation) that lets AI agents from different frameworks call each other. Use when the user wants to create an A2A-compliant agent, build an Agent Card, implement task management, connect agents across frameworks, set up agent discovery, handle streaming responses, implement push notifications, or orchestrate multi-agent workflows. Trigger words: a2a, agent to agent, agent2agent, a2a protocol, a2a server, a2a client, agent card, agent interoperability, agent collaboration, multi-agent, agent discovery, a2a sdk, a2a task.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

a2ui

無料

Lets an AI agent describe a user interface as declarative JSON that a client renders with its own trusted components. Use when a user asks to generate forms, cards or dashboards from an agent, wants an agent to return UI instead of text, asks about the A2UI protocol, createSurface or updateComponents messages, catalogs, data binding, or the Lit, Angular, React and Flutter renderers. Covers the v0.9 message format, validating payloads and the official packages.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

Plans a controlled experiment (A/B test) so its result can be trusted: writes the hypothesis, picks one primary metric and the guardrails, computes sample size and run time, specifies how visitors are assigned and when exposure is logged, and reads out the result with a confidence interval. Use when someone says "set up an A/B test", "split test this page", "how many visitors do I need", "how long should the experiment run", "is this result significant", "can I stop the test early", or wants to test a headline, price, layout or onboarding change against the current version.

日本語の概要は準備中です。原文の説明を表示しています。

TerminalSkills/skills1832026年10月29日 更新

TerminalSkills のスキルをすべて見る

このスキルの問題を報告する