結論から言うと、GASとスプレッドシートを使えば、サーバー代完全無料で「特定の言葉にだけ反応するBot」は作れます。 「おはよう」には挨拶を、「推しの名前」には尊い語りを。あなたの会話に合わせて成長するBotを、コピペだけで実装してみましょう。


そもそも、どうやって「言葉」を判断しているの?

Bot作りで一番楽しいのが、言葉の「判定ロジック」です。今回はスプレッドシートを使って、以下の2つのパターンを使い分けられる高機能なBotを作ります。

判定モード仕組み (プログラム)特徴使用例
完全一致=== (イコール)一言一句合っていないと反応しない合言葉、コマンド、パスワード
部分一致includes (含む)文中にキーワードが含まれていれば反応する会話、挨拶、推し語り

例えばキーワードが**「犬」**の場合:

  • 完全一致: 「犬」→ ⭕️反応 / 「犬が好き」→ ❌無視
  • 部分一致: 「犬」→ ⭕️反応 / 「犬が好き」→ ⭕️反応

これを使い分けることで、「会話に自然に割り込むBot」や「特定のコマンドだけ聞くBot」を自由に作れます。


ステップ1:スプレッドシートを「Botの脳(辞書)」にする

まずはBotが覚える言葉のリストを作ります。コードを書き換えるのではなく、シートに行を追加するだけで言葉を増やせるのが最大のメリットです。

  1. Googleスプレッドシートを新規作成します。
  2. シート名(画面下のタブ)を「Dictionary」に変更します。
  3. 1行目に見出しを作り、2行目以降にデータを入力します。

【シートの入力例】

A列 (Keyword)B列 (Response)C列 (Mode)
1言葉返信モード
2おはようおはようございます!exact
3ニャー🐱exact
4ラーメン今日のご飯はラーメンですか?partial
  • exact: 完全一致させたい時に入力
  • partial: 部分一致(〜を含む)させたい時に入力(空欄でもOK)

ステップ2:GASで「定期見回りシステム」を作る

GASは通常、自分から動くことができません。そこで**「1分に1回、Discordを見に行く」**という仕組み(ポーリング)を作ります。

  1. スプレッドシートのメニューから [拡張機能][Apps Script] を開きます。
  2. エディタのコードを全て消して、以下のコードを丸ごとコピペしてください。
  3. コード上部の DISCORD_TOKENCHANNEL_ID を自分のものに書き換えます。

※注意: Bot Tokenの取得方法やDeveloper Portalでの設定(Message Content IntentをONにする等)は、Bot作成の基本手順通りに行っておいてください。

【コピペ用】特定の単語反応Bot 全コード

JavaScript

/**
 * 特定の単語に反応するDiscord Bot (GAS版)
 * * 機能:
 * 1. Discordの特定チャンネルのメッセージを定期的に取得
 * 2. スプレッドシートの「辞書」と照らし合わせる
 * 3. マッチしたら返信する
 */

// --- 設定エリア ---
// ※本来はスクリプトプロパティ推奨ですが、初心者向けに直接記述式にしています
const DISCORD_TOKEN = 'ここにBotトークンを貼り付け';
const CHANNEL_ID = 'ここにチャンネルIDを貼り付け';
const SHEET_NAME = 'Dictionary';

/**
 * メイン関数 (これをトリガーで1分ごとに実行)
 */
function main() {
  // 1. メッセージを取得
  const messages = fetchMessages();
  if (!messages || messages.length === 0) return;

  // 2. 辞書データを取得
  const dictionary = getDictionary();

  // 3. 処理済みチェック用のキャッシュ
  const cache = CacheService.getScriptCache();

  // 新しいメッセージから順にチェック
  for (const msg of messages) {
    // Bot自身の発言は無視(無限ループ防止)
    if (msg.author.bot) continue;

    // 既に返信済みなら無視(キャッシュ確認)
    if (cache.get(msg.id)) continue;

    const content = msg.content;
    let replyText = null;

    // 辞書と照合
    for (const row of dictionary) {
      const keyword = row.keyword;
      const response = row.response;
      const mode = row.mode; // 'exact' か 'partial'

      if (mode === 'exact') {
        // 完全一致判定 (前後の空白は無視)
        if (content.trim() === keyword) {
          replyText = response;
          break; // マッチしたらループを抜ける
        }
      } else {
        // 部分一致判定
        if (content.includes(keyword)) {
          replyText = response;
          break;
        }
      }
    }

    // 返信対象が見つかった場合
    if (replyText) {
      sendDiscordMessage(replyText, msg.id); // メンション付きで返信
      
      // 二重返信防止のためキャッシュに保存 (有効期限10分)
      cache.put(msg.id, 'done', 600);
      
      // 1回の実行で1件返信したら終了する(スパム防止)
      break; 
    }
  }
}

/**
 * スプレッドシートから辞書データを取得
 */
function getDictionary() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
  if (!sheet || sheet.getLastRow() < 2) return [];

  // A列:キーワード, B列:返信, C列:モード
  const data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).getValues();
  
  return data.map(row => ({
    keyword: row[0].toString(),
    response: row[1].toString(),
    mode: row[2].toString().toLowerCase() || 'partial'
  })).filter(item => item.keyword !== ''); 
}

/**
 * Discord API: メッセージ取得
 */
function fetchMessages() {
  const url = `https://discord.com/api/v10/channels/${CHANNEL_ID}/messages?limit=10`;
  const options = {
    method: 'get',
    headers: { 'Authorization': `Bot ${DISCORD_TOKEN}` },
    muteHttpExceptions: true
  };
  
  try {
    const res = UrlFetchApp.fetch(url, options);
    if (res.getResponseCode() === 200) {
      return JSON.parse(res.getContentText());
    }
  } catch (e) {
    console.error('メッセージ取得失敗:', e);
  }
  return [];
}

/**
 * Discord API: メッセージ送信 (Reply形式)
 */
function sendDiscordMessage(text, replyMessageId) {
  const url = `https://discord.com/api/v10/channels/${CHANNEL_ID}/messages`;
  const payload = {
    content: text,
    message_reference: { message_id: replyMessageId }
  };

  const options = {
    method: 'post',
    headers: {
      'Authorization': `Bot ${DISCORD_TOKEN}`,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  try {
    UrlFetchApp.fetch(url, options);
    console.log(`返信しました: ${text}`);
  } catch (e) {
    console.error(`送信エラー: ${e.toString()}`);
  }
}

ステップ3:自動実行(トリガー)のセット

最後に「1分ごとに見回りに行く」設定をします。

  1. 左メニューの [トリガー] (時計アイコン) をクリック。
  2. 右下の [トリガーを追加] をクリック。
  3. 以下のように設定して保存します。
    • 実行する関数: main
    • イベントのソース: 時間主導型
    • 時間ベースのトリガーのタイプ: 分ベースのタイマー
    • 間隔: 1分おき

これで完了です!Discordで辞書に登録した言葉を呟いてみましょう。Botが巡回してきたタイミング(最大1分後)に返信が来ます。


トラブルシューティング(動かない時は?)

Q. Botが反応しません(エラーも出ない)。

A. 「Message Content Intent」 がOFFになっていませんか?

Developer Portalの「Bot」ページにあるこのスイッチをONにしないと、Botはメッセージの中身が空っぽに見えてしまい、反応できません。

Q. 「自分(Bot)」の発言にまた反応して無限ループします。

A. コード内の if (msg.author.bot) continue; という行がその防止策です。この行を消さないように注意してください。

Q. 少し反応が遅いです。

A. GASのトリガー実行は「1分に1回」なので、タイミングによっては最大1分のラグがあります。これは「サーバー代無料」の対価として、のんびり待ちましょう。