GAS + ChatGPT で Slack に自作 Bot を作る方法【GPT-4o / ファイルレビュー対応】

# Google Apps Script で ChatGPT (GPT-4o) を Slack Bot にしてコードレビューさせてみた

自分の OpenAI API Key を使って、GPT-4o を **Slack に Bot として入れてみた** 記事です ☕️

- **自分好みの性格付け GPT Bot を入れたい**
- **ファイルを添付してコードレビューもさせたい**
- **グループチャットでコードレビューしたい**

そんなニーズに GAS (Google Apps Script) で対応してみました 🚀

---

## この記事でできること

✅ 自分の GPT-4o を Slack Bot にする  
✅ ファイル（.php, .js, .py, .txt など）を添付してレビューさせる  
✅ GAS なのでサーバ不要・無料で動作  
✅ Slack App の作り方も手順付きで解説  
✅ GPT の personality (性格) を自由に付けられる  

---

## 想定読者

- ChatGPT API (GPT-4o) を Slack で使いたい人  
- 会社の Slack にコードレビュー Bot を入れたい人  
- 自分の好みの性格・回答スタイルの Bot を作りたい人  
- サーバを借りずに Google Apps Script で動かしたい人  

---

## 記事内容

1️⃣ Slack App の作り方（手順つき）  
2️⃣ 必要なスコープ 
3️⃣ GAS 側のコード例
4️⃣ ファイル添付レビューに対応する方法  
5️⃣ よくあるハマりポイント（ファイルの扱いなど）  
6️⃣ 性格付け・カスタマイズの例  

---

## 完成イメージ

Slack で：

```

@GPTBot このコードレビューして
（.php ファイル添付）

```

↓

GPT-4o がコードレビューして返答してくれる ☕️

---

## こんな方におすすめです！

✅ 自分の GPT-4o API Key を有効活用したい方  
✅ 自分の好みの性格（技術アドバイザー、やさしい先生 etc）の Bot を入れたい方  

---

## Slack App の作り方（詳細手順）

### 1️⃣ App の作成

- [https://api.slack.com/apps](https://api.slack.com/apps) にアクセス  
- 「Create New App」 → `From scratch` を選択  
- App Name（例: `GPTBot`）と ワークスペース を選んで「Create App」  

---

### 2️⃣ Event Subscriptions を設定

- メニューの **Event Subscriptions** を ON にする  
- **Request URL** は一旦ダミーでもOK（後で GAS Web App URL を貼る）  
- 「Subscribe to Bot Events」 に以下を追加：

```

app_mention

```

---

### 3️⃣ OAuth & Permissions の設定

- メニューの **OAuth & Permissions** → **Scopes** → **Bot Token Scopes** に追加：

```

chat:write
app_mentions:read
files:read（ファイル添付レビューのため）

```

---

### 4️⃣ Bot Token を取得する

- 上部の **Install to Workspace** ボタンを押して、ワークスペースにインストール  
- Bot User OAuth Token (`xoxb-...`) が発行される  

---

### 5️⃣ イベントURLの設定

- Google Apps Script 側で Web App をデプロイ（後述）  
- デプロイ時の URL を Slack App の **Event Subscriptions → Request URL** に設定  
- Slack が URL を確認して「verified」になる  

---

### 6️⃣ チャンネルに Bot を招待

Slack 側で Bot を使いたいチャンネルに：

```

/invite @Bot名

```

と招待しておくと、メンションが飛ぶようになります 🚀


---

### ✅ ここまでのチェックポイント

- Bot Token (`xoxb-...`) は取得できた？  
- `files:read` スコープは入れた？  
- チャンネルに Bot を Invite 済み？  

---

## Google Apps Script (GAS) 側のコード例

以下のコードを Google Apps Script に貼り付けて **Web アプリとしてデプロイ** します。  

（「新しいデプロイ」 → Web アプリ → 発行した URL を Slack に貼る）

```js
function doPost(e) {
  const params = JSON.parse(e.postData.contents);

  // Slack Event Verification
  if (params.type === "url_verification") {
    return ContentService.createTextOutput(params.challenge);
  }

  const event = params.event;

  // メンション時のみ、かつ subtype 無し（編集時などは無視）
  if (event && event.type === "app_mention" && !event.subtype) {
    const userMessage = event.text;
    const channel = event.channel;

    let fileText = "";
    const allowedExt = ['.php', '.js', '.py', '.txt', '.md'];

    if (event.files && event.files.length > 0) {
      event.files.forEach(file => {
        const downloadUrl = file.url_private_download;
        const fileName = file.name.toLowerCase();
        const isTextFile = allowedExt.some(ext => fileName.endsWith(ext));

        const response = UrlFetchApp.fetch(downloadUrl, {
          method: 'get',
          headers: {
            'Authorization': 'Bearer xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // Slack Bot Token
          },
          muteHttpExceptions: true,
        });

        if (isTextFile) {
          const content = response.getContentText("UTF-8");
          fileText += `\n\n【ファイル: ${file.name}】\n` + content + "\n";
        } else {
          fileText += `\n\n【ファイル: ${file.name}】\n※ サポート対象外のファイル種別でした\n`;
        }
      });
    }

    const fullMessage = `${userMessage}\n\n${fileText}`;

    const openai_response = UrlFetchApp.fetch('https://api.openai.com/v1/chat/completions', {
      method: 'post',
      contentType: 'application/json',
      headers: {
        'Authorization': 'Bearer sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // OpenAI API Key
      },
      payload: JSON.stringify({
        model: 'gpt-4o',
        messages: [
          {
            role: 'system',
            content: 'あなたはユーザーが自由に性格付けできる GPT Bot です。たとえば「論理的な技術アドバイザー」「やさしいコード先生」など好みに応じた人格で回答します。ファイルが添付された場合はコードレビューにも対応します。',
          },
          {
            role: 'user',
            content: fullMessage
          }
        ]
      }),
    });

    const replyText = JSON.parse(openai_response.getContentText()).choices[0].message.content;

    UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', {
      method: 'post',
      contentType: 'application/json',
      headers: {
        'Authorization': 'Bearer xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
      },
      payload: JSON.stringify({
        channel: channel,
        text: replyText.length > 3800 ? replyText.substring(0, 3800) + '...(省略)' : replyText,
      }),
    });
  }

  return ContentService.createTextOutput('OK');
}
````

---

### GAS デプロイ手順

1️⃣ Google Apps Script に上記コードを貼り付け
2️⃣ 「デプロイ」 → 「新しいデプロイ」 → 「種類：Web アプリ」
3️⃣ 実行するユーザー：自分
4️⃣ アクセスできるユーザー：全員（匿名ユーザー）
5️⃣ デプロイ → URL 発行
6️⃣ Slack App 側の **Event Subscriptions** に URL を貼り付けて verified

---

### コメント

* Bot Token (`xoxb-...`) と OpenAI API Key (`sk-...`) はご自身のものに置き換えてください
* ファイル種別は `allowedExt` に `.vue`, `.json`, `.yml` など自由に追加できます
* ファイルの中身が長すぎる場合は Slack API の制限によりカットされます（本コードは3800文字上限にカット）

---

## まとめ・今後の応用

* ファイルの拡張子は自由に増やせます（`.vue`, `.json`, `.yml`, `.go` など）
* キャラクター性（性格付け）は `system` メッセージで自由に変更可能
* GAS での運用に慣れたら、GCP Cloud Functions に載せても OK
* PR 自動レビューにも応用可能

---

よかったらぜひ試してみてください ☕️🚀