【LINE✖️GAS】はじめてのGoogleAppsScript<protoout体験会資料>

![スクリーンショット 2024-01-30 4.09.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/3d81c98f-3e2e-ba1d-a9ee-d166397e6934.png)
この記事の内容を理解すればこんなLINEBotが簡単にできちゃいます！！

# 前々準備
1. GoogleDriveにログイン
1. [LINE Developersにログイン](https://developers.line.biz/ja/services/line-login/)
1. [OpenAIのAPIクレジット登録](https://qiita.com/okinakamasayoshi/items/247c58342e5cf15c7bcd)

# 前準備
1. [LINE公式アカウント作成](https://qiita.com/okinakamasayoshi/items/bf9593b2af20148c4d19)
1. [OpenAI_key取得](https://qiita.com/okinakamasayoshi/items/247c58342e5cf15c7bcd)
1. [こちらのスプレッドシート](https://docs.google.com/spreadsheets/d/1BITOclhyS5pisfPiRP8DUkF8vcHFy-DhZ0-RUcJ6zPM/edit#gid=0)をコピー

![スクリーンショット 2024-01-30 2.14.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/18cc9bfb-7b6d-40de-125e-79f3eb9886c5.png)
4. 拡張機能からGoogleAppsScriptを立ち上げる

![スクリーンショット 2024-01-30 2.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/0af57e47-8df3-0721-290a-fb8e9245e49e.png)
こんな画面が出てくるはずです。
![スクリーンショット 2024-01-30 2.18.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/040be10e-d990-0dd0-1de7-ece3ccc52d7f.png)

※以降に出てくるコードはほとんど上記GASに既に記載されています。
# おうむ返しBotを作ろう
## 必要なこと
1. LINEチャンネルアクセストークンの貼り付け
1. OpenAIのAPI_keyの貼り付け（厳密にはここでは必要ないですが準備としてまとめてやっちゃいましょう）
1. [デプロイ](https://qiita.com/cog1t0/items/f6e832d54a7b0e692434#googleappscript%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AB%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%93%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%82%92%E3%81%97%E3%81%BE%E3%81%99)
```javascript
function doPost(e) {
  let json = JSON.parse(e.postData.contents)
  let reply_token= json.events[0].replyToken;
  if (typeof reply_token === 'undefined') {
    return;
  }
  if (json.events[0].type == 'message'){
    const userMessage = json.events[0].message.text
    // ☆ここのメッセージを変更することで、返信内容が変更できる☆
    messages = [
      { type: 'text', 
        text: userMessage  
      }
    ]
    // ☆メッセージ内容はここまで☆
    sendmessage(messages, reply_token)
  }
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

function sendmessage(message, reply_token){
  UrlFetchApp.fetch(line_endpoint, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': reply_token,
      'messages': message
    })
  })
}
```
LINEに何か送ってみておうむ返しされたら成功！！
![スクリーンショット 2024-01-30 2.26.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/ca7da7be-e03e-2d4c-d7a4-54f7787270b7.png)

# 自分の言葉に変えてみよう
```javascript
messages = [
      { type: 'text', 
        text: userMessage + "ってどういうこと？"  
      }
    ]
```
「こんにちは」に対し「こんにちはってどういうこと？」と返ってきたら成功！
# 2つメッセージを返そう(オブジェクトの単位を学ぶ)
```javascript
messages = [
      { type: 'text', 
        text: userMessage  
      },
       { type: 'text', 
        text: userMessage + "2回目" 
      }
    ]
```
「こんにちは」に対し「こんにちは」「こんにちは２回目」と返ってきたら成功！
２回目以降のデプロイは「デプロイの管理」を選択しましょう。Webhookの再設定は不要です。デプロイ前には必ずスクリプトが保存されていることを確認します。
![スクリーンショット 2024-01-30 2.45.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/2c9f9641-f82c-9470-6498-31a112c01072.png)
右上のペンのマークを押して「新バージョン」を選択します。
![スクリーンショット 2024-01-30 2.48.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/bb8dd7bc-cb4e-1c27-211c-5c1d3ed923b6.png)



# いきなり応用！ChatGPTにメッセージを作ってもらおう
下記のような関数を作っておけば、contentで指示を書き、callChatGPT(userMessage)と書けばChatGPTが作成したメッセージが利用できます。
```javascript
function callChatGPT(userMessage) {
  let system_content = `あなたは○○です（役割を設定）。${userMessage}に対して＊＊＊＊のように回答してください。文字数は＊＊＊。`
  const url = 'https://api.openai.com/v1/chat/completions';
  const options = {
    method: "post",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${OPENAI_API_KEY}`,
    },
    payload: JSON.stringify({
      model: "gpt-3.5-turbo",
      messages: [{ role: "system", content: system_content }, { role: "user", content: userMessage }],
    }),
  };
  const response = UrlFetchApp.fetch(url, options);
  const result = JSON.parse(response.getContentText());
  const text = result.choices[0].message.content.trim();
  return text;
}
```
このメッセージをmessagesの中に入れます。
```javascript
messages = [
      { type: 'text', 
        text: callChatGPT(userMessage)
      }
    ]
```
# 2つの分岐を作ろう（○○だったらこう返信、✖️✖️だったら...）
```javascript
function doPost(e) {
  let json = JSON.parse(e.postData.contents)
  let reply_token= json.events[0].replyToken;
  if (typeof reply_token === 'undefined') {
    return;
  }
  // もしユーザーが送信したもののタイプが「message」だったら
  if (json.events[0].type == 'message'){
    const userMessage = json.events[0].message.text
    if(userMessage == "東北東"){
          messages = [
      { type: 'text', 
        text: "大正解！"  
      }
    ]
    }else{
          messages = [
      { type: 'text', 
        text: "どーこ見て食べてんだよ"  
      }
    ]
    }
    // ☆メッセージ内容はここまで☆
    sendmessage(messages, reply_token)
  }
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```
さらに分岐が増やしたい場合は、
```javascript
function doPost(e) {
  let json = JSON.parse(e.postData.contents)
  let reply_token= json.events[0].replyToken;
  if (typeof reply_token === 'undefined') {
    return;
  }
  // もしユーザーが送信したもののタイプが「message」だったら
  if (json.events[0].type == 'message'){
    const userMessage = json.events[0].message.text
    if(userMessage == "東北東"){
          messages = [
          { type: 'text', 
            text: "大正解！"  
          }
    ]
    }else if(userMessage == "北北東"){
          messages = [
      { type: 'text', 
        text: "惜しい！"  
      }
    ]
    }else{
          messages = [
      { type: 'text', 
        text: "どーこ見て食べてんだよ" 
      }
    ]
    }
    // ☆メッセージ内容はここまで☆
    sendmessage(messages, reply_token)
  }
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```

# 補足：カスタマイズ方法
ここまでの流れを理解できれば、様々な応用の仕方が可能です。
## 返信内容をカスタマイズ
```javascript
messages = [
      { type: 'text', 
        text: callChatGPT(userMessage)
      }
    ]
```
これはテキストを返すコードですが、その他スタンプ、画像、位置情報などのタイプを選択することが可能です。詳しくはLINE公式ドキュメントをご参照ください。

https://developers.line.biz/ja/docs/messaging-api/message-types/

## イベントタイプやメッセージ内容をカスタマイズ
if分岐をどのように作るかで想定されるいろんなパターンに応用可能です。eventのtypeにはmessageの他にfollow(誰かが友だち追加したとき)、follow(誰かが友だち追加した）、postback(ユーザーからのアクション）などがあります。来たメッセージが画像だったら、メッセージに○○が含まれていたら、などシチュエーションによって分岐できます。

https://developers.line.biz/ja/docs/messaging-api/receiving-messages/#webhook-event-in-one-on-one-talk-or-group-chat

## スプレッドシートをデータベースに使用
送信するメッセージの情報源としてスプレッドシートを使えばさらにバリエーションが増やせます。

https://qiita.com/ped-yui123/items/dd6811343d6e39133ea5

## 体験会後自分でやっていて詰まったら
今は大概のことはChatGPTに聞けば解決してくれますが、解決しない場合自分で試せることが下記に書かれていますのでこちらもぜひご参考になさってください。

https://qiita.com/ped-yui123/items/d7971fd59df3a3245de1