[LINE Bot] LIFFとリッチメニューでも管理画面が作りたい! 2 -リッチメニュー切替-

この記事はこの記事の続きです
[[LINE Bot] LIFFとリッチメニューでも管理画面が作りたい! 1 -グループ管理-]()

# リッチメニューを作る
さて、前回はグループへの招待・退会で管理メンバーの追加・削除をできるようにしました。
その際にリッチメニューをユーザ用と管理者用に切り替えます。
今回はそのリッチメニューを作ります。

今回はユーザー用を 3 x 1 (1200 x 405)
管理者用を 3 x 2 (1200 x 810) のメニューを作ります。
動作確認のため、上の段はユーザと同じものにします


## Line Messaging APIでリッチメニューを作る
Line Account Managerで作成したリッチメニューは残念ながらAPIでは使えません。
画像を準備し、APIで作成する必要があります。
画像はpngかjpgで1MB以内です。

pythonで適当に書いたので、ライブラリをインストールします。

```bash
pip install line-bot-sdk
pip install pyyaml
pip install boto3
```

botのシークレットキーなどは、serverless.ymlで環境変数として読み込んでいるymlをそのまま読み込みます。

```yaml:conf/line-dev.yml
CHANNEL_SECRET: "シークレット"
CHANNEL_TOKEN: "トークン"
ADMIN_GROUP_ID: "前回作成した管理部屋のグループID"
```

#### ソースコード
お作法としては
- デフォルトのリッチメニューを解除する
- 全てのリッチメニューを削除する
- ユーザ用リッチメニューを作成する
- 管理者用のリッチメニューを作成する
のようになります。
既存のリッチメニューを削除しておかないと、1000件までの上限にそのうち引っかかります。

```python:richmenu.py
#!/usr/bin/env python3

import sys
import requests
import yaml
import boto3
from linebot import (
    LineBotApi
)
from linebot.models import (
    RichMenu, RichMenuArea, RichMenuSize, RichMenuBounds,
    PostbackAction, URIAction,
)


def main():

    with open('conf/line-'+env+'.yml') as file:
        yml = yaml.safe_load(file)

    admin_group_id = yml['ADMIN_GROUP_ID']
    access_token = yml['CHANNEL_TOKEN']

    // botを作成する
    line_bot_api = LineBotApi(access_token)

    // デフォルトのリッチメニューを解除する
    cancel_richmenu(line_bot_api)
    line_bot_api.cancel_default_rich_menu()

    // 既存のリッチメニューを削除する
    delete_richmenu(line_bot_api)

    // ユーザ用メニューを作成する
    id = create_user_richmenu(line_bot_api)
    upload_user_richmenu_image(line_bot_api)

    // 全てのユーザにユーザ用メニューをデフォルトに設定する
    line_bot_api.set_default_rich_menu(id)

    // 管理者用メニューを作成する
    id = create_staff_richmenu(line_bot_api)
    upload_staff_richmenu_image(line_bot_api, id)

    // 管理者に管理者用リッチメニューを設定する
    set_staff_richmenu(line_bot_api, id )

// 全てのリッチメニューを削除する
def delete_richmenu(line_bot_api):
    print("delete user richmenu")
    menu_list = line_bot_api.get_rich_menu_list()

    for richmenu in menu_list:
        print("delete user richmenu "+richmenu.rich_menu_id)
        line_bot_api.delete_rich_menu(richmenu.rich_menu_id)

// ユーザ用リッチメニュー
def create_user_richmenu(line_bot_api, chara_name):
    print("create user richmenu")
    user_menu = RichMenu(
        size=RichMenuSize(width=1200, height=405),
        selected=True,
        name="minarai-chan user menu",
        chat_bar_text="お店情報・ご注文",
        areas=[
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=0,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=PostbackAction(
                    label='何ができるの?',
                    displayText='何ができるの?',
                    data="how_to_use",
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=400,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='shop',
                    uri='ユーザ向けLIFFのURL',
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=800,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='order',
                    uri='ユーザ向けLIFFのURL',
                ),
            ),
        ]
    )
    id = line_bot_api.create_rich_menu(rich_menu=user_menu)
    print("user richmenu id = "+id)
    return id

def upload_user_richmenu_image(line_bot_api, id):
    print("update user richmenu "+ id)
    with open('script/image/richmenu/user.png', 'rb') as f:
        line_bot_api.set_rich_menu_image(id, 'image/png', f)

# 3 x 2 のリッチメニュー。上3段はユーザ用と同じ
def create_staff_richmenu(line_bot_api, chara_name):
    print("create staff richmenu")
    user_menu = RichMenu(
        size=RichMenuSize(width=1200, height=810),
        selected=False,
        name="minarai-chan user menu",
        chat_bar_text="管理メニュー",
        areas=[
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=0,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=PostbackAction(
                    label='何ができるの?',
                    displayText='何ができるの?',
                    data="how_to_use",
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=400,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='shop',
                    uri='ユーザ向けLIFFのURL',
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=800,
                    y=0,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='order',
                    uri='ユーザ向けLIFFのURL',
                ),
            ),
            # 下の段
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=0,
                    y=405,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='staff_nanika',
                    uri='LIFFのURL',
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=400,
                    y=405,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='staff_hoge',
                    uri='LIFFのURL',
                ),
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=800,
                    y=405,
                    width=400,
                    height=405,
                ),
                action=URIAction(
                    label='staff_order',
                    uri='LIFFのURL',
                ),
            ),
        ]
    )
    id = line_bot_api.create_rich_menu(rich_menu=admin_menu)
    print("admin richmenu id = "+id)
    return id

# 管理者用画像アップロード
def upload_staff_richmenu_image(line_bot_api, id):
    print("update staff richmenu "+ id)
    with open('script/image/richmenu/admin.png', 'rb') as f:
        line_bot_api.set_rich_menu_image(id, 'image/png', f)

# 管理者用のリッチメニュー
def set_staff_richmenu(line_bot_api, id):
    // DBから管理者のユーザIDを取得しておく
    ...

    line_bot_api.link_rich_menu_to_user('管理者のユーザID', id)
    return


```

## リッチメニューを切り替える
管理部屋に招待・退会した時のイベント処理は前回書きましたが、
そこにリッチメニューの切り替え処理を書きます。

リッチメニューのIDは環境変数にしています。

```go:line/user.go
func (r *Line) LinkRichMenu(users []string) {
    // Line Messaging API リッチメニューを複数ユーザに紐付ける
	_ = r.bot.BulkLinkRichMenu(r.richMenuID, users...)
}

func (r *Line) UnlinkRichMenu(users []string) {
    // Line Messaging API リッチメニューを複数ユーザから解除する
	_, _ = r.bot.BulkUnlinkRichMenu(users...).Do()
}
```

これで、リッチメニューの切り替えは完了です!

#### 次回、LIFFとAPIで管理者認証を行う。
LIFFからアクセストークンを取得し、サーバー側でユーザIDに変換し、管理者であるかどうかを認証します。
[[LINE Bot] LIFFとリッチメニューでも管理画面が作りたい! 3 -認証編-](https://qiita.com/alivelime/items/7d67149a34342493a0a5)