Linebotを作る(Step1: Gasで作成)

## はじめに
表題通り、Linebotを作成します。最終的にAIと連動させてコンシェルジュサービスまで作ろうと思います。
まずは、Lineの疎通をできるようにGasで基盤を作っていきます！

## 成果物
![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/b38bf56c-492e-4a15-a6de-cf2e1b710774.gif)


## 技術スタック

- Google Apps Script (GAS)
- TypeScript
- LINE Messaging API
- Clasp (Command Line Apps Script Projects)

## 前提条件

- Node.jsがインストールされていること
- Google アカウントを持っていること
- LINE Developersアカウントを持っていること

## 1. プロジェクトのセットアップ

### 1.1 プロジェクトディレクトリの作成

```bash
mkdir line_bot_concierge
cd line_bot_concierge
```

### 1.2 必要なパッケージのインストール

```bash
# package.jsonの初期化
npm init -y

# TypeScript関連パッケージのインストール
npm install --save-dev @types/google-apps-script

# Claspのインストール
npm install -g @google/clasp
```

### 1.3 Claspの設定

```bash
# Googleアカウントでログイン
clasp login

# 新しいGASプロジェクトの作成（スプレッドシートタイプ）
clasp create --type sheets --title "LINE Bot Echo" --rootDir ./src
```

## 2. TypeScriptの設定

### 2.1 tsconfig.jsonの作成

```json
{
  "compilerOptions": {
    "target": "ES2019",
    "module": "None",
    "lib": ["ESNext"],
    "outDir": "build",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
```

### 2.2 型定義ファイルの作成

```typescript
// src/types.d.ts
interface LineEvent {
  type: string;
  replyToken: string;
  source: {
    userId: string;
    type: string;
  };
  timestamp: number;
  mode: string;
  message: {
    type: string;
    id: string;
    text: string;
  };
}

interface LineMessage {
  type: string;
  text: string;
}

interface LineReplyMessage {
  replyToken: string;
  messages: LineMessage[];
}
```

## 3. LINE Botの実装

### 3.1 メインコードの作成

```typescript
// src/Code.ts
// LINE Messaging APIのチャネルアクセストークン
const CHANNEL_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('CHANNEL_ACCESS_TOKEN');

// Webhookのエンドポイント
function doPost(e: GoogleAppsScript.Events.DoPost): GoogleAppsScript.Content.TextOutput {
  if (!CHANNEL_ACCESS_TOKEN) {
    throw new Error('CHANNEL_ACCESS_TOKEN is not set in script properties');
  }

  const event: LineEvent = JSON.parse(e.postData.contents).events[0];
  
  // メッセージイベントの場合
  if (event.type === 'message' && event.message.type === 'text') {
    // 受信したメッセージをそのまま返信
    const replyMessage: LineReplyMessage = {
      replyToken: event.replyToken,
      messages: [{
        type: 'text',
        text: event.message.text
      }]
    };
    
    // LINE Messaging APIにリクエストを送信
    const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${CHANNEL_ACCESS_TOKEN}`
      },
      payload: JSON.stringify(replyMessage)
    };
    
    UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', options);
  }
  
  return ContentService.createTextOutput(JSON.stringify({ status: 'ok' }))
    .setMimeType(ContentService.MimeType.JSON);
}

// スクリプトプロパティを管理する関数群
function setScriptProperty(key: string, value: string) {
  PropertiesService.getScriptProperties().setProperty(key, value);
}

function getScriptProperty(key: string) {
  return PropertiesService.getScriptProperties().getProperty(key);
}

function deleteScriptProperty(key: string) {
  PropertiesService.getScriptProperties().deleteProperty(key);
}

function getAllScriptProperties() {
  return PropertiesService.getScriptProperties().getProperties();
}
```

### 3.2 GASの設定ファイル

```json
// src/appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```

## 4. 環境変数の設定

LINE Botのチャネルアクセストークンは、セキュリティのためにスクリプトプロパティとして管理します。
設定方法は2つあります：

### 4.1 GASエディタのUIから設定

1. 「ファイル」→「プロジェクトのプロパティ」→「スクリプトのプロパティ」
2. 「行を追加」をクリック
3. プロパティ名: `CHANNEL_ACCESS_TOKEN`
4. 値: LINEチャネルアクセストークン
5. 「保存」をクリック

### 4.2 スクリプト関数から設定

1. GASエディタで`setScriptProperty`関数を実行
2. プロパティ名と値を入力

## 5. デプロイ

### 5.1 コードのアップロード

```bash
clasp push
```

### 5.2 ウェブアプリとしてデプロイ

1. GASエディタで「デプロイ」→「新しいデプロイ」
2. 「種類の選択」で「ウェブアプリ」を選択
3. 設定：
   - 説明：「LINE Bot Echo」
   - 次のユーザーとして実行：「自分」
   - アクセスできるユーザー：「全員（匿名ユーザーを含む）」
4. 「デプロイ」をクリック
5. 権限を承認

### 5.3 LINE Developersコンソールの設定

1. Webhook URLの設定
   - デプロイ時に表示されたウェブアプリのURLをコピー
   - LINE DevelopersコンソールでWebhook URLとして設定
2. Webhookの利用をオン
3. 接続確認

## 6. 動作確認

1. LINEアプリでボットを友だち追加
2. メッセージを送信
3. ボットが同じメッセージを返信することを確認

## 7. プロジェクト管理

### 7.1 .gitignoreの設定

```plaintext
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# TypeScript
*.tsbuildinfo
build/
dist/

# Google Apps Script
.clasp.json
.clasprc.json

# Environment variables
.env
.env.local
.env.*.local

# IDE
.idea/
.vscode/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Logs
logs
*.log
```

### 7.2 .claspignoreの設定

```plaintext
**/*.ts
!Code.ts
!types.d.ts
node_modules/**
package.json
package-lock.json
README.md
test/**
*.test.js
*.test.ts
```

## まとめ

この記事では、TypeScriptとGASを使用してLINE Botを作成する方法を解説しました。
主なポイントは以下の通りです：

1. TypeScriptによる型安全な開発
2. Claspを使用したGASプロジェクトの管理
3. スクリプトプロパティによる環境変数の管理
4. セキュアなデプロイ方法

## 次のステップ

基本的なオウム返しボットが完成したら、以下のような機能追加を検討できます：

1. スプレッドシートへのログ記録
2. 画像やスタンプへの対応
3. 特定のキーワードに対する応答
4. リッチメニューの追加

## 参考リンク

- [LINE Messaging API](https://developers.line.biz/ja/docs/messaging-api/)
- [Google Apps Script](https://developers.google.com/apps-script)
- [Clasp](https://github.com/google/clasp)