Use Cases

Claude CodeでDiscord Botを開発する実践ガイド

Claude Codeを活用したDiscord Botの開発方法を解説。discord.js、スラッシュコマンド、ボタン操作、Embed、音声チャンネル連携まで実践的に紹介します。

Discord Bot開発をClaude Codeで効率化する

Discord Botはコミュニティ運営、ゲームサーバー管理、通知配信など幅広い用途で活用されています。discord.jsライブラリを使えばTypeScriptで快適に開発できますが、インタラクション処理やパーミッション管理には多くの実装が必要です。Claude Codeを活用して、高機能なDiscord Botを効率的に構築しましょう。

プロジェクトのセットアップ

> Discord Botのプロジェクトを作成して。
> discord.js v14、TypeScript、コマンドハンドラー構成で。
npm init -y
npm install discord.js
npm install -D typescript @types/node tsx
// src/index.ts
import { Client, GatewayIntentBits, Collection, Events } from 'discord.js';
import { registerCommands } from './commands';

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

client.commands = new Collection();

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

// コマンドハンドラー
client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  const command = client.commands.get(interaction.commandName);
  if (!command) return;

  try {
    await command.execute(interaction);
  } catch (error) {
    console.error(error);
    const reply = {
      content: 'コマンドの実行中にエラーが発生しました。',
      ephemeral: true,
    };
    if (interaction.replied || interaction.deferred) {
      await interaction.followUp(reply);
    } else {
      await interaction.reply(reply);
    }
  }
});

registerCommands(client);
client.login(process.env.DISCORD_TOKEN);

スラッシュコマンドの実装

> /poll コマンドで投票機能を実装して。
> ボタンで投票できるようにして。
// src/commands/poll.ts
import {
  SlashCommandBuilder,
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  EmbedBuilder,
  ChatInputCommandInteraction,
  ButtonInteraction,
} from 'discord.js';

const polls = new Map<string, { question: string; votes: Map<string, Set<string>> }>();

export const data = new SlashCommandBuilder()
  .setName('poll')
  .setDescription('投票を作成します')
  .addStringOption((opt) =>
    opt.setName('question').setDescription('質問').setRequired(true)
  )
  .addStringOption((opt) =>
    opt.setName('option1').setDescription('選択肢1').setRequired(true)
  )
  .addStringOption((opt) =>
    opt.setName('option2').setDescription('選択肢2').setRequired(true)
  )
  .addStringOption((opt) =>
    opt.setName('option3').setDescription('選択肢3').setRequired(false)
  );

export async function execute(interaction: ChatInputCommandInteraction) {
  const question = interaction.options.getString('question', true);
  const options = [
    interaction.options.getString('option1', true),
    interaction.options.getString('option2', true),
    interaction.options.getString('option3'),
  ].filter(Boolean) as string[];

  const pollId = `poll-${Date.now()}`;
  const votes = new Map<string, Set<string>>();
  options.forEach((opt) => votes.set(opt, new Set()));
  polls.set(pollId, { question, votes });

  const embed = new EmbedBuilder()
    .setTitle('📊 ' + question)
    .setColor(0x6366f1)
    .setDescription(
      options.map((opt) => `**${opt}**: 0票`).join('\n')
    )
    .setFooter({ text: `Poll ID: ${pollId}` });

  const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
    ...options.map((opt, i) =>
      new ButtonBuilder()
        .setCustomId(`${pollId}:${opt}`)
        .setLabel(opt)
        .setStyle(ButtonStyle.Primary)
    )
  );

  await interaction.reply({ embeds: [embed], components: [row] });
}

// ボタンハンドラー
export async function handlePollButton(interaction: ButtonInteraction) {
  const [pollId, option] = interaction.customId.split(':');
  const poll = polls.get(pollId);
  if (!poll) return;

  const userId = interaction.user.id;

  // 既存の投票を削除
  for (const voters of poll.votes.values()) {
    voters.delete(userId);
  }

  // 新しい投票を追加
  poll.votes.get(option)?.add(userId);

  const description = Array.from(poll.votes.entries())
    .map(([opt, voters]) => {
      const count = voters.size;
      const bar = '█'.repeat(count) || '░';
      return `**${opt}**: ${count}票 ${bar}`;
    })
    .join('\n');

  const embed = new EmbedBuilder()
    .setTitle('📊 ' + poll.question)
    .setColor(0x6366f1)
    .setDescription(description)
    .setFooter({ text: `Poll ID: ${pollId}` });

  await interaction.update({ embeds: [embed] });
}

Embedメッセージ

> サーバー情報を表示するコマンドを作って。
> リッチなEmbed形式で表示して。
// src/commands/serverinfo.ts
import {
  SlashCommandBuilder,
  EmbedBuilder,
  ChatInputCommandInteraction,
} from 'discord.js';

export const data = new SlashCommandBuilder()
  .setName('serverinfo')
  .setDescription('サーバー情報を表示します');

export async function execute(interaction: ChatInputCommandInteraction) {
  const guild = interaction.guild;
  if (!guild) return;

  const embed = new EmbedBuilder()
    .setTitle(guild.name)
    .setThumbnail(guild.iconURL() || '')
    .setColor(0x6366f1)
    .addFields(
      { name: 'メンバー数', value: `${guild.memberCount}人`, inline: true },
      { name: 'チャンネル数', value: `${guild.channels.cache.size}`, inline: true },
      { name: 'ロール数', value: `${guild.roles.cache.size}`, inline: true },
      { name: '作成日', value: guild.createdAt.toLocaleDateString('ja-JP'), inline: true },
      { name: 'ブースト', value: `Lv.${guild.premiumTier} (${guild.premiumSubscriptionCount}回)`, inline: true },
    )
    .setTimestamp();

  await interaction.reply({ embeds: [embed] });
}

コマンドの登録

// src/commands/index.ts
import { REST, Routes, Client } from 'discord.js';
import * as poll from './poll';
import * as serverinfo from './serverinfo';

const commands = [poll, serverinfo];

export function registerCommands(client: Client) {
  for (const command of commands) {
    client.commands.set(command.data.name, command);
  }
}

// スラッシュコマンドをDiscordに登録
export async function deployCommands() {
  const rest = new REST().setToken(process.env.DISCORD_TOKEN!);
  const body = commands.map((c) => c.data.toJSON());

  await rest.put(
    Routes.applicationCommands(process.env.DISCORD_CLIENT_ID!),
    { body }
  );
  console.log('Commands deployed');
}

まとめ

discord.jsとClaude Codeを組み合わせれば、インタラクティブなDiscord Botを効率的に構築できます。チャットボット開発ガイドAPI開発の基本も参考にしてください。

discord.jsの詳細はdiscord.js公式ガイドを参照してください。

#Claude Code #Discord Bot #discord.js #チャットボット #コミュニティ