【LINEでパーティーゲーム】リッチメニューの画面で宝探し！【GAS】

### はじめに
忘年会・新年会の時期ですね（これを書いているのは2022年で、まだまだ飲み会を積極的にできる雰囲気にはありませんが・・・）。
飲み会の時、ちょこっと景品のついたゲームがあると楽しくないですか？
ということで、スマホのLINEがあれば参加できるゲームを作りました。

### 名付けて「リッチメニューで宝探し」
ルールは簡単、リッチメニューのどこかに宝（当たり）が隠されているので、参加者は当たりが出るまでリッチメニュー をぽちぽち押す→誰かが当たりを出したら終了、というシンプルなゲームです。

### 骨組み
1. リッチメニュー作成
1. スプレッドシートを準備する
1. GoogleAppsScriptで実装

### ①リッチメニュー作成
・リッチメニュー用の画像を用意する
[Canva](https://www.canva.com/)で作成すると便利です。テンプレートも豊富です。
次に出てくるリッチメニュー エディターで好きな領域にアクションを割り当てられるので、サイズだけ守れば(1MB超えると作成できない）どんな画像でも構いません。
ちなみに私は↓のような画像にしました。絶対押すなよ、えっふり？？ってやつです。

![赤色 白色 パターン クリスマス セール LINEリッチメニュー (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/b91ee1f0-5442-90d5-a409-c2859346b777.png)

・[リッチメニューエディター](https://richmenu.app.e-chan.me/)で当たり・はずれの領域を決める
LINEの公式の方からだと決まった数・形のリッチメニューしか作成できないので、いつもリッチメニューエディターを使用しています。上の画像の中の左下の松ぼっくりの部分だけを当たりにしました（だいぶ領域狭いと思いましたが、意外とすぐに当たりが出ました）。参加者が楽しめるように、当たりの近くには「惜しい！」と送信されるアクションをつけました。

### ②スプレッドシートを準備する
今回のスプレッドシートの役割は、
・当たりの人の記録
・当たりが出たらゲームが終了するためのしかけ
の大きく２つです。

おまけとして、ゲームスタートする前にフライングした人がいるかのチェックができるようにしておきました笑。

準備したスプレッドシートのどこかのセルに半角で1を入れておいてください。スプレッドシートに関しては、前もってやるのはこれだけです。

![スクリーンショット 2022-12-19 0.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653579/1103432a-c87f-b504-d3ce-9901d15054f7.png)

### ③GAS(GoogleAppsScript)で実装
スプレッドシートの拡張機能からGASを開きます。
GASってなに？って方は[こちらの記事](https://qiita.com/cog1t0/items/0d121ee6d48a8c1634fc)でオウム返しの実装からやってみることをオススメします。

コードとしては、
・「はずれ」か「惜しい」の場合は、励ましのリプライメッセージを返す
・「当たり」の場合は、
    　　　当たった旨と賞品URL（SNSギフト）を送る
    　　　スプレッドシートの1を2にする
    　　　全員に「○○さんが当たりました。」のメッセージを送る
    　　　スプレッドシートの数字が2の場合は、何が来ても「ゲームは終了しました。」を返す
というルールを実装していきます。
（つまり、userからメッセージが来たら、①スプレッドシートの数字で分岐②userからのメッセージで分岐となります。）

## 全体
```javascript
const CHANNEL_ACCESS_TOKEN =
  "LINEアカウントで発行したチャンネルアクセストークン";
const line_endpoint = "https://api.line.me/v2/bot/message/reply";
const line_endpoint_profile = "https://api.line.me/v2/bot/profile";
// 特に理由はないのですがlogsheetに1を書いたので、logとmainの2シートになっています。
const logsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("log");
const mainsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("main");
// スプレッドシートの1の部分を確認
let col;
col = logsheet.getRange("D1").getValue();

function doPost(e) {
  let json = JSON.parse(e.postData.contents);
  let user_id = json.events[0].source.userId;
  // 当選者発表のためLINEでのdisplay nameを取得
  let name = getUserDisplayName(user_id);

  let reply_token = json.events[0].replyToken;
  if (typeof reply_token === "undefined") {
    return;
  }

  if (json.events[0].type == "message") {
    // スプレッドシートの数字が1でなくなっていればゲームは終了
    if (col != 1) {
      messages = [
        {
          type: "text",
          text: "ゲームは終了となりました。",
        },
        {
          type: "text",
          text: "ご参加いただきありがとうございます！",
        },
      ];
    } else {
      const usermessage = json.events[0].message.text;
      if (usermessage == "あたり！！") {
        // 当たりならスプレッドシートの1を2に
        logsheet.getRange("D1").setValue(col + 1);
        // 当たりの人の名前をスプレッドシートに記録（セルはどこでもよい）
        mainsheet.getRange(8, 7).setValue(name);
        messages = [
          {
            type: "text",
            text:
              "プレゼントが当たりました！下のURLから受け取りの手続きをしてください。",
          },
          {
            type: "text",
            text:
              "賞品のURL",
          },
        ];
        // 全員にブロードキャストメッセージを送る
        UrlFetchApp.fetch("https://api.line.me/v2/bot/message/broadcast", {
          method: "post",
          headers: {
            "Content-Type": "application/json",
            Authorization: "Bearer " + CHANNEL_ACCESS_TOKEN,
          },
          payload: JSON.stringify({
            messages: [
              {
                type: "text",
                text: name + "さんがプレゼントをGETしました！！！！",
              }
            ],
          }),
        });
      } else {
        // ここの部分はなくても成立する。はずれや惜しいの場合にスプレッドシートに記録される
        let lastRow = mainsheet
          .getRange(1, 1)
          .getNextDataCell(SpreadsheetApp.Direction.DOWN)
          .getRow();
        mainsheet.getRange(lastRow + 1, 1).setValue(usermessage);
        mainsheet.getRange(lastRow + 1, 2).setValue(name);

        // はずれや惜しいの場合に送るメッセージを作る
        messages = [
          {
            type: "text",
            text: "頑張って当たりを探してください！",
          },
        ];
      }
    }
  }
  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 " + CHANNEL_ACCESS_TOKEN,
    },
    method: "post",
    payload: JSON.stringify({
      replyToken: reply_token,
      messages: message,
    }),
  });
}

// この関数でLINEのdisplay nameが取得できる
function getUserDisplayName(user_id) {
  let res = UrlFetchApp.fetch(line_endpoint_profile + "/" + user_id, {
    headers: {
      "Content-Type": "application/json; charset=UTF-8",
      Authorization: "Bearer " + CHANNEL_ACCESS_TOKEN,
    },
    method: "get",
  });
  return JSON.parse(res).displayName;
}
```

### おわりに
大勢でやると同じタイミングで当たりが出てしまったらうまくいかないかもしれませんが（私は12人くらいでやりました。）、簡単にできるのでぜひ遊んでみてください。