誰でも簡単、GUIでMessaging APIの「リッチメニュー」作りませんか?

# 概要
1. Messaging APIでリッチメニューを作るのって難しいよね。[こちら](#はじめに)
2. リッチメニューってこういうものです。[こちら](#リッチメニューの構造)
3. エディタないかなー。ないなら作ろう。[こちら](#リッチメニューを作ってみよう)
4. ~~3日で~~作ったのでぜひどうぞ([こちら](https://richmenu.app.e-chan.me/))

https://richmenu.app.e-chan.me/

# はじめに
はじめまして。いーちゃんです。
高校生になりました。が、コロナ禍で入学式も延期、1回も高校には行けていません...。
記事執筆の経験もなく拙い文章ですがどうか最後までお付き合いいただければ...。

それはさておき、LINEの公式アカウントでは、個人チャットの画面下部に「リッチメニュー」を表示できます。
最新情報を表示するためのボタンだったり、クーポンを表示するためのボタンだったり、あるいはWebページを表示するためのボタンだったり。

例えばこんな感じ。
![例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/d1c018e5-c8c6-a81d-6aad-eba9a66098bb.png)
(新型コロナウイルス感染症情報 厚生労働省 アカウントより)

アカウントを使う人は、そこにあるボタンを押すだけでBotの持つ様々な機能にアクセスでき、とても便利です。
一方で、作る側としては少々敷居が高く感じる人もいるのではないでしょうか。

リッチメニューの作成には、大きく2通り、

- LINE Official Account Manager を使って作成する方法(かんたん!)
- Messaging API を使って作成する方法(むずかしい!)

の2種類があります。
この記事では、後者 Messaging API を使って作成する方法について紹介します。
> Official Account Manager と Messaging API では、使用可能なアクション(ボタンを押したときに起こせるもの)が異なります。
> お店の公式アカウント等、クーポンを表示できるのは Official Account Manager を利用した場合のみなので、注意してください。

# リッチメニューの構造
リッチメニューを作るためには、

- 背景画像
- メニューの名前(管理用)
- メニューを開くボタンに表示されるテキスト
- メニューをはじめから開いておくか
- 押すとなにか起きる範囲
    - 範囲の大きさ
    - 押すと起こること

の項目について明確にしておく必要があります。
それをAPIが理解できる形に表すとこうなります。

> ```json:リッチメニューオブジェクトの例
{
  "size": {
    "width": 2500,
    "height": 1686
  },
  "selected": false,
  "name": "Nice richmenu",
  "chatBarText": "Tap to open",
  "areas": [
    {
      "bounds": {
        "x": 0,
        "y": 0,
        "width": 2500,
        "height": 1686
      },
      "action": {
        "type": "postback",
        "data": "action=buy&itemid=123"
      }
    }
  ]
}
```
> [Messaging API リファレンス](https://developers.line.biz/ja/reference/messaging-api/#rich-menu-object)より

このJSONファイルにはざっくり

- 2500 x 1686 のメニューを作るよー
- はじめは閉じた状態にするよー
- 管理用に "Nice Richmenu" っていう名前をつけるよー
- メニューを開くボタンは "Tap to open"って書いてあるよー
- 押すとなにか起きる範囲はー...
    - X座標 0px, Y座標 0pxから右に2500px、下に1686px分の領域を作るよー
        - 押すとポストバックアクションが起きるよー
        - ボタンが押されたら"action=buy&itemid=123" っていう文字を返してねー

なんてことが書いてあります。まだボタンが1個なので長さは短いですが、押せる領域が2つ,3つ, ... と増えていくとどんどん長くなっていきます。
また、リッチメニューは実際にAPIで登録・表示の設定をしなければ動きを試すこともできません。さらに、例えば指定する領域がずれていた時。それを修正することもできません。そんなこともあり、Messaging API を使ったリッチメニューの実装は少し難しく感じるかもしれません。

## アクションとは...?
先程例に出した厚生労働省のアカウントの場合、「最新情報」ボタンを押すと、厚生労働省や内閣官房へのリンクが書かれたメッセージが届きます。このように、「あの範囲を押したら〇〇をしてねー」の〇〇にあたるのがアクションです。
Messaging APIのリッチメニューで使えるアクションには、こんなものがあります。(雑で申し訳ないです)
![message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/fc521ad9-730e-4a21-6d09-69a03846070a.png)
メッセージアクション。一番想像が容易かもしれません。
使う人がボタンを押すと、その人自身の発言としてBOTに普通のメッセージが送られます。
![postback.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/6880d68d-c0c7-79d9-af2b-48e03d45cb25.png)
一方のポストバックアクションも、使う人が押すと何かがBOTに返されるという点では同じです。こちらは、使う人にはあまり見せたくないような内部の情報をこっそり送り返すような場合に便利です。
![uri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/20cc3bbe-b345-2111-8ce9-81a3a286fa1d.png)
URIアクションでは、http(s)://、line://(非推奨)、tel: で始まるURIを登録することで、ボタンを押したときにブラウザを開いたり、電話をかけたりすることができます。
![datetimepicker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/18d257c0-c1cc-681b-fc4b-15a7c0436a2d.png)
最後の日時選択アクションは、カレンダーなどの画面を表示して、使う人に日付や時間、あるいはその両方を選んでもらうことができます。

# リッチメニューを作ってみよう
では、リッチメニューを作ってみましょう。と言って、いきなりJSONを書き出すのはかなり難しいかと思います。JSONを書いたところで、

- APIに登録しないと表示テストすらできない
- APIに1回登録すると、再作成しなければ内容が編集できない。
- 画像も同じく1回登録した後は変更不可。

と、高いハードルがそこには立ちはだかります。
「リッチメニューを簡単に編集できて、プレビューもできるツールないかなー」なんて思った土曜日から3日間、私はあるコードを書き続けました。
その成果物がこちらです。

https://richmenu.app.e-chan.me/

![localhost_3000_(2K Display (Retina)) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151384/cdb121a0-567a-958b-5877-4de794cd5de9.png)

そうです。エディタ作ってしまいました。

このエディタでは、難しいことを気にせずに

- [リッチメニューオブジェクト](https://developers.line.biz/ja/reference/messaging-api/#rich-menu-object)の作成
- 画像配置とアクションのプレビュー
- JSONファイル形式でのインポート&エクスポート
- リッチメニューの公式アカウントとの紐付け
- 既存のリッチメニューのダウンロード
- リッチメニューの削除

までできます。~~自分で言うのもなんですが、優れものです。~~
JSONファイルのフォーマットは公式のリッチメニューオブジェクトの仕様に則っているため、ご自分でAPIを呼び出していただくことも可能です。
[APIリファレンス](https://developers.line.biz/ja/reference/messaging-api/#rich-menu-object)等を参考に気軽に触ってみてください。(APIの利用に必要なチャンネルアクセストークンはあらかじめ取得しておいてくださいね。)

# エディタ作成の技術
~~このページは、[Nuxt.js](https://ja.nuxtjs.org/)で作成、[Vercel](https://vercel.com/)(元のnow.shという名前ならご存知でしょうか)に無料でデプロイしています。
また、デザインはフレームワークを一切使わず、手作業で組みきりました。(一部サイトからコピーさせていただきましたが)
エディタ表示には[Prism](https://prismjs.com/)、スマホ枠表示には[Devices.css](https://picturepan2.github.io/devices.css/)をそれぞれ利用しています。~~ 
Nuxt.jsをNext.jsに、フレームワークにMaterial-UI(現MUI)を利用して書き換えました。エディタ表示はmonaco-editor、スマホ枠は手書きCSSに変更しています。


## ボタンの装飾
基本色を枠と文字色に入れ、`:focus`時に色を反転するようになっています。
中でも、ファイル選択ボタンの装飾には少々コツが必要で、

```html
<label>
  ボタンに表示する中身
  <input type="file" ... >
</label>
```

とした上で、

```scss
label {
  // ボタンと共通のCSS(@extends)
  input {
    display: none
  }
}
```

のように、`input`要素を消して`label`要素にスタイルを当てる必要がありました。

また、機能を大量につける関係で、複数のボタンをつなげるボタングループのスタイルも書きました。この実装は、`:first-child`の右側(スマホ表示では下側)の角丸めを解除、`:last-child`の左側(スマホ表示では上側)の角丸めを解除、どちらにも当てはまらないものはすべての角を、... と言うような簡単な実装で実現できるので、ぜひ試してみてください。

## APIが呼び出せない。
APIの呼び出しもクライアントサイドで完結できないかな...? と思い、Fetch API で~~適当に~~実装したのですが、CORSに引っかかり目的を果たせませんでした。そのため、サーバーサイドのNode.jsを介してAPIに接続するようなシステムに作り変えました。

# 感想
> Nuxt.jsを使ったり、スタイルを0から組むなど、初めての経験も多くありました。その反面、試行錯誤を重ねて様々な機能を実装できて、とても勉強になりました。
普段はBootstrapだったりBulmaだったりフレームワークを使ってばかりでしたが、CSS(SCSSを使いましたが)の練習になったり、結果としてサイトの軽量化にもなった(?)のでよかったと思います。

初期バージョンからさらに技術を大きく刷新し、これらに加えてまた多くの学びを得ることができました。

これからもいろいろなサービスを生み出していけたら...。と思うので、なにかアイデア等あればお気軽にお寄せいただければ嬉しいです！

# 終わりに
念の為もう一度エディタのURL貼っておきます。
[https://richmenu.app.e-chan.me/](https://richmenu.app.e-chan.me/)
リッチメニュー実装にぜひお役立てください!

[Github](https://github.com/e-chan1007/line-richmenu-editor)でソースも公開していますので興味がありましたらご覧ください。

この記事の感想、あるいはご指摘等ありましたらぜひコメントよろしくお願いします!