夫婦（カップル）喧嘩を仲裁してくれるLINEBot〜言いたいことも言えないそんな時にはこれ〜

## 最近喧嘩してますか？
夫婦って生活を共にしていく中で、ちょっとしたすれ違いで喧嘩したり、喧嘩にはならないまでもお互いちょっとした不満をためこんだりしていることってありますよね。
ということで、「喧嘩裁判長」という名の、喧嘩仲裁LINEBotを作ってみました。
どうぞお使いください。
![saibanchoqrcode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/0db960df-0176-4732-ab6c-9df99916d5f6.png)


![赤色 白色 パターン クリスマス セール LINEリッチメニュー (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/892c55d0-3f62-83d5-2ca3-fcc3340f1f6f.png)

## 誰か仲裁を！！

喧嘩した時、誰かに仲裁してほしいけど、なかなか適した相談相手っていなくないですか？
▶︎中立的な立場が取れる
▶︎まともな意見を言ってくれる
▶︎時間気にせず話を聞いてくれる（どんな時間帯も、どんな長時間も）
▶︎身内の恥がさらせる
こんなちょうどいい条件がそろった人なんて・・・・・・・

あ、人じゃなければいた！！！
ChatGPTだ！
ということで下記のような構成で作ってみました。
![スクリーンショット 2023-12-13 22.10.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/e33bd0d7-9763-686b-9ff0-270a1b8b3165.png)
## フローチャート 
![スクリーンショット 2023-12-13 22.20.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/94fcf124-ca45-5de2-1dd0-803b8a3d9f6f.png)
## 夫婦の紐付け
自分の訴えが相手にそのまま見えると書きづらいので、グループLINEに喧嘩裁判長を入れるという形ではなく、あくまで「個々に裁判長に相談する」という形を取ることにしました。
下記は各useridからメッセージがポストされた時どこのシートにいくかを示したリストです。
※このLINEBotでは各夫婦が1枚のシートにデータを記録していく形になっています。
![スクリーンショット 2023-12-13 23.04.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/91f04410-3017-7e37-ab6e-23ea9e5c69bb.png)

1. Aさんが友だち登録（AさんのLINEidを名前にしたシートが作成される）
1. Aさんが認証番号を発行
1. Bさんが友だち登録（BさんのLINEidを名前にしたシートが作成される）
1. Bさんが認証番号を送信
1. その番号でBさんがAさんのシートに紐付けされる(BさんのLINEidのシートは削除される）

Bさんが認証番号を送信したところの挙動としては、やや煩雑ですが下記です。
メッセージが5桁の数字であることからここに分岐します。
```javascript
    let digit = String(json.events[0].message.text).length;
    if (digit == 5) {
        //認証番号に合致する行を探す
      let row = searchredinumber(json.events[0].message.text);
      let sheetid = listsheet.getRange(row, 1).getValue();
      let partnername = listsheet.getRange(row, 2).getValue();
      let name = getUserDisplayName(userId);
      let partnerSheet = SpreadsheetApp.openById(masterid).getSheetByName(
        sheetid
      );
      let listLastRow = listsheet.getLastRow();
      listsheet.getRange(listLastRow + 1, 1).setValue(userId);
      listsheet.getRange(listLastRow + 1, 4).setValue(sheetid);
      partnerSheet.getRange(2, 4).setValue(userId);
      partnerSheet.getRange(3, 4).setValue(name);
      messages = [
        {
          type: "text",
          text:
            partnername +
            "さんのお相手に登録しました。（もし名前が異なる場合は初めからやり直してください）",
        },
      ];
      //メッセージ送信
      replyToLine(replyToken, messages)
      //Bさんのシート削除
      SpreadsheetApp.getActiveSpreadsheet().deleteSheet(sheet);
    }
```

## プロンプト
"Bさんが喧嘩に心当たりがない時にAさんの訴えを遠回しにBさんに訴える"、"片方の相談にのる"、"謝り方を提示する"など様々なところでChatGPTを利用しています。
例えば遠回しに伝えるところは下記のようなプロンプトになっています。
uttae, player1, player2はスプレッドシートから数値を取ってくる変数となっています。
```javascript
let content =
        "あなたは" +
        player1 +
        "さんと" +
        player2 +
        "さんの友人です。その2人はカップルあるいは夫婦です。" +
        player2 +
        "さんは" +
        uttae +
        "と訴えていますが、" +
        player1 +
        "さんは" +
        player2 +
        "さんが怒っている理由に心当たりがないようです。" +
        player1 +
        "さんの訴えを直接的に伝えるのではなく、遠回しに" +
        player1 +
        'さんの訴えを伝えてあげてください(description)。出力形式：{"description": description}、文字数:300字以内';
```
これを下記の関数に入れていきます。
ChatGPTに"description"という項目で書いてもらうよう指示し、LINEで受け取れるように成形します。
```javascript
function callOpenAI(sheet, content) {
  const url = "https://api.openai.com/v1/chat/completions";
  const options = {
    method: "post",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${OPEN_AI_API_KEY}`,
    },
    payload: JSON.stringify({
      model: "gpt-4",
      messages: [{ role: "user", content: content }],
    }),
  };
  const response = UrlFetchApp.fetch(url, options);
  const result = JSON.parse(response.getContentText());
  const text = result.choices[0].message.content;
  const modtext = JSON.parse(text.replace(/""/g, "'"));
  sheet.getRange("F12").setValue(modtext.description);
  return modtext.description;
}
```
## プッシュメッセージ通知
片方が仲裁を希望した時に、もう片方に通知がいく必要があるのでそこの実装について。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/c5747fed-2f7e-13fe-651c-15b9d999779f.png" width="300">
「仲裁して」の分岐の中を下記のようにします。
```javascript
messages = [
            {
              type: "text",
              text:
                "任せなさい！向こうにも言い分があればそれも聞いてジャッジするからね。",
            },
          ];
replyToLine(replyToken, messages);
sendtopartner(partnerid);
```
sendtopartnerは以下のように定義。クイックリプライを使用しています。
```javascript
function sendtopartner(partnerid) {
  const url = "https://api.line.me/v2/bot/message/push";

  const payload = {
    to: partnerid,
    messages: [
      {
        type: "text",
        text: "何かあった？",
        quickReply: {
          items: [
            {
              type: "action",
              action: {
                type: "message",
                label: "心当たりがあるので謝る",
                text: "今から謝ってきます。",
              },
            },
            {
              type: "action",
              action: {
                type: "message",
                label: "あった。",
                text: "あった。",
              },
            },
            {
              type: "action",
              action: {
                type: "message",
                label: "思い当たらない",
                text: "特に思い当たらない",
              },
            },
          ],
        },
      },
    ],
  };
  ```
  これでプッシュメッセージが通知されます。

  ## 感想求む
  ぜひ実際に使用された感想をお待ちしています！！