GAS + ChatGPT を使った LINE Bot の紹介。動画自動保存機能も

# 1.はじめに
なおきち餃子（[@naokichigyoza](https://twitter.com/naokichigyoza "なおきち餃子（@naokichigyoza）さん / Twitter")）と申します。

今日は、友人たちとのLINEグループで使っているLINE Botを紹介します。
Google Apps Script のソースコードを記載しますので、
皆さんも参考に作ってみてください！

# 2.この LINE Bot でできること
現時点でできることは、以下の2つです。
* LINEグループに投稿された動画のGoogle Driveへの保存
* LINEで 「OKなおきち餃子、◯◯について教えて」という投稿がされた際の
  ChatGPT API を使った返答

保存期間が無期限の「LINEアルバム」に、動画が追加できない点を
解消するために、作成しています。


# 3.LINE Bot のスクリプト
利用にあたっては、以下の情報が必要です。
* LINE Bot のアクセストークン
* OPEN AI のアクセストークン
* 動画保存先のGoogle Drive のフォルダID

これらを追記して利用してください。

```javascript:linebot.gs
//LINEボットのアクセストークン
const LINE_ACCESS_TOKEN = '************************'; 
//OPEN AI のアクセストークン
const OPENAI_APIKEY = "***************************";
//Googleドライブに作ったフォルダのURLの末尾にある30文字くらいの文字列
const FOLDER_ID = '***************************';
//返信用エンドポイント
const REPLY_URL = 'https://api.line.me/v2/bot/message/reply';

//LINEへメッセージを送信する関数
function sendMsg(url, payload) {
  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify(payload),
  });
}

//メッセージファイルから保存用ファイルを生成する関数
function getfile(id) {
  //画像取得用エンドポイント
  var url = 'https://api-data.line.me/v2/bot/message/' + id + '/content';
  var data = UrlFetchApp.fetch(url,{
    'headers': {
      'Authorization' :  'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'get'
  });
  var date = new Date();
  var strdate = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy-MM-dd-hh-mm-ss-SSS');
  var file = data.getBlob().setName(strdate + '.mp4');
  return file;
}

//生成した保存用ファイルをGoogleDriveに保存する関数
function saveFile(blob) {
  try{
    var folder = DriveApp.getFolderById(FOLDER_ID);
    var file = folder.createFile(blob);
    return file.getUrl();
  }catch(e){
    return false;
  }
}

//実行関数
function doPost(e) {
  var event = JSON.parse(e.postData.contents).events[0];
  //動画が送られてきた時の処理
  if(event.message.type == 'video') {
    try {
      var file = getfile(event.message.id);
      var url = saveFile(file);
      sendMsg(REPLY_URL, {
        'replyToken': event.replyToken,
        'messages': [{
          'type': 'text',
          'text': url ? "保存完了！"  : "保存失敗",
        }]
      })
    }catch(e) {
      Logger.log(e);
    }
//テキストメッセージで「OKなおきち餃子、◯◯について教えて？」と言われたら
  } else if (event.message.type == 'text' && event.message.text.startsWith('OKなおきち餃子、')) {
    try {
      //受け取ったメッセージテキストそのまま
      let raw_message = event.message.text;
      //OKなおきち餃子、部分は除く
      let userMessage = /OKなおきち餃子、(.*)/.exec(raw_message)[1];

      const prompt = userMessage;
      const requestOptions = {
        "method": "post",
        "headers": {
          "Content-Type": "application/json",
          "Authorization": "Bearer "+ OPENAI_APIKEY
        },
        "payload": JSON.stringify({
          "model": "gpt-3.5-turbo",
          "messages": [
            {"role": "system", "content": `
あなたはChatbotとして、餃子カンパニーに勤務するAIロボットであるなおきち餃子AIのロールプレイを行います。
以下の制約条件を厳密に守ってロールプレイを行ってください。 

制約条件: 
* Chatbotの自身を示す一人称は、私です。 
* Userを示す二人称は、あなたです。 
* Chatbotの名前は、なおきち餃子AIです。 
* なおきち餃子AIは、餃子カンパニーのAIロボットです。
* なおきち餃子AIは、なおきち餃子という人物を元に作られました。
* なおきち餃子はエンジニアとして働いています。

なおきち餃子AIのセリフ、口調の例: 
* 私はなおきち餃子AIです。 

なおきち餃子AIの行動指針:
* ユーザーを助ける執事のような行動をしてください。 
        `   },
            {"role": "user", "content": prompt}]
        })
      }
      //Chat-GPT の応答を取得
      const response = UrlFetchApp.fetch("https://api.openai.com/v1/chat/completions", requestOptions);
      //Chat-GPT の応答からテキストのみ抽出
      const responseText = response.getContentText();
      //Chat-GPT の応答をJSONでパース
      const json = JSON.parse(responseText);
      //Chat-GPT の応答をtext に格納
      const text = json['choices'][0]['message']['content'].trim();
      //LINE で返答
      sendMsg(REPLY_URL, {
        'replyToken': event.replyToken,
        'messages': [{
            'type': 'text',
            'text': text,
        }]
      });
    }catch(e) {
      Logger.log(e);
    }
  }
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```

# 4. 最後に
Qiitaの記事2個目です。
少しずつアウトプットが増やしていければいいなと考えています。

よければTwitter のフォローをお願いします。
[https://twitter.com/naokichigyoza](https://twitter.com/naokichigyoza "なおきち餃子（@naokichigyoza）さん / Twitter")

https://naokichigyoza.com/