---
# System prepended metadata

title: AI LINE Bot練功坊-L12 Rich Menu
tags: [Python, Line Bot]

---

AI LINE Bot練功坊-L12 Rich Menu
===
### 什麼是 Rich Menu？
> Rich Menu 是位於聊天室畫面下方的選單，可以讓使用者在聊天視窗中直接點擊按鈕，進行操作或獲取資訊。

### Rich Menu的優點
> Rich Menu，這個版位有絕佳的曝光度，每次用戶不管是因為推播或其他互動打開您的官方帳號時，都能看到這個版位。有了圖文選單區塊，不只曝光，更能幫您24小時導流做互動，讓您的服務不間斷！

# 設定 Rich Menu？
> 要建立圖文選單有兩種方式，第一種進入 Line@ 後台有功能可以使用，第二種透過 Messaging API 的程式端去建立

## Line官方帳號管理器

1. 在主頁裡點選「圖文選單」，再點選建立即可新增圖文選單
![image](https://hackmd.io/_uploads/B1Hrm7MmA.png)
![image](https://hackmd.io/_uploads/SJFwmmfX0.png)

2. 設定頁面各個項目，設定完成後點選「儲存」

* 顯示設定：
    * 設定標題名稱：管理圖文選單，此設定不會對用戶顯示
    ![image](https://hackmd.io/_uploads/rknjmXM7A.png)
    * 可以設定在用戶裝置上的圖文選單以及顯示時間
    * 選單欄中顯示的文字設定欄
    
    * 預設顯示方式：設定顯示時，當用戶進入聊天室，會直接顯示圖文選單；反之，設定隱藏時，用戶需要點選選單欄才會顯示圖文選單

* 內容設定： 
    * 選擇版型
        Line官方有給參考的大小範例，可以參考使用
        
        ![image](https://hackmd.io/_uploads/Hy3ZBXfQR.png)
    
        ![image](https://hackmd.io/_uploads/S19YE7fQ0.png)
    
        ![image](https://hackmd.io/_uploads/HkJSSXfm0.png)
    
    * 設定圖文選單的圖片
        ![image](https://hackmd.io/_uploads/SkpDSmGQC.png)
    
        ![image](https://hackmd.io/_uploads/HybjSXGQC.png)
    
        選擇剛剛下載好的模板
        
        ![image](https://hackmd.io/_uploads/ryzyLXfQC.png)
    
        按下套用
        ![image](https://hackmd.io/_uploads/r13-I7zQR.png)
    * 根據模板的對應部分中設定動作
        ![image](https://hackmd.io/_uploads/S1vXUQf7R.png)
        選擇文字
        ![image](https://hackmd.io/_uploads/HkB8L7GXR.png)
        並在下方輸入文字內容
        ![image](https://hackmd.io/_uploads/BJbtU7GQ0.png)

>Reference：https://tw.linebiz.com/manual/line-official-account/oa-manager-richmenu/

## Ｍessaging API

* 更加客製化
* 可以在 rich menu 設定 postback action 和 datetime picker
* 可以設定切換 rich menu 的標籤

在開始之前，我們要先準備 rich menu 的圖片(下圖為範例圖片，可以到前面的設計規範下載)
![richmenu-template-guide-01](https://hackmd.io/_uploads/SkUdbtXQR.png)

使用 Linebot Designer 設計圖文選單，並複製產生的 json 檔

![image](https://hackmd.io/_uploads/Sk1eGY7mA.png)

![image](https://hackmd.io/_uploads/HJNGMF7mC.png)

![image](https://hackmd.io/_uploads/ryjmMFXXR.png)

![image](https://hackmd.io/_uploads/Bk8HMtQ7C.png)

:::success
**注意事項**
* 每個 richmenu 最多可以設置20個可點選區塊
* 可以設置多個 richmenu 可按照情境作切換
* 最多可以同時有1000個 richmenu
* 可以為不同的 User 指定不同的 richmenu
:::

使用的套件
```python
from linebot.v3.messaging import (
    MessagingApi,
    MessagingApiBlob,
    RichMenuSize,
    RichMenuRequest,
    RichMenuArea,
    RichMenuBounds,
    MessageAction
)
```

### 使用物件的方式

1. 利用 RichMenuArea 和 RichMenuBounds 兩個套件去建立 action 範圍的物件
    (物件的範圍根據 Linebot Designer 設計出的範圍填寫)
```python
areas = [
    RichMenuArea(
        bounds=RichMenuBounds(
            x=0,
            y=0,
            width=833,
            height=843
        ),
        action=MessageAction(text='A')
    ),
    RichMenuArea(
        bounds=RichMenuBounds(
            x=834,
            y=0,
            width=833,
            height=843
        ),
        action=MessageAction(text='B')
    ),
    RichMenuArea(
        bounds=RichMenuBounds(
            x=1663,
            y=0,
            width=834,
            height=843
        ),
        action=MessageAction(text='C')
    ),
    RichMenuArea(
        bounds=RichMenuBounds(
            x=0,
            y=843,
            width=833,
            height=843
        ),
        action=MessageAction(text='D')
    ),
    RichMenuArea(
        bounds=RichMenuBounds(
            x=834,
            y=843,
            width=833,
            height=843
        ),
        action=MessageAction(text='E')
    ),
    RichMenuArea(
        bounds=RichMenuBounds(
            x=1662,
            y=843,
            width=834,
            height=843
        ),
        action=MessageAction(text='F')
    )
]
```

2. 利用 RichMenuRequest 去製作整個 richmenu 的基本設定
    * richmenu 圖片的大小
    * 圖文選單的名稱
    * 圖文選單縮小欄位的文字標籤
    * areas 的物件(action 的設定)

```python
rich_menu_to_create = RichMenuRequest(
    size=RichMenuSize(
        width=2500,
        height=1686,
    ),
    selected=True,
    name="圖文選單1",
    chat_bar_text="查看更多資訊",
    areas=areas
)
```

3. 取得 richmenu id

```python
rich_menu_a_id = line_bot_api.create_rich_menu(
    rich_menu_request=rich_menu_to_create
).rich_menu_id
```

4. 設定 richmenu 到 Linebot 上

```python
with open('./public/richmenu-a.png', 'rb') as image:
    line_bot_blob_api.set_rich_menu_image(
        rich_menu_id=rich_menu_a_id,
        body=bytearray(image.read()),
        _headers={'Content-Type': 'image/png'}
    )
```

完整的程式碼 :

```python
def create_rich_menu_1():
    with ApiClient(configuration) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_blob_api = MessagingApiBlob(api_client)

        areas = [
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=0,
                    y=0,
                    width=833,
                    height=843
                ),
                action=MessageAction(text='A')
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=834,
                    y=0,
                    width=833,
                    height=843
                ),
                action=MessageAction(text='B')
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=1663,
                    y=0,
                    width=834,
                    height=843
                ),
                action=MessageAction(text='C')
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=0,
                    y=843,
                    width=833,
                    height=843
                ),
                action=MessageAction(text='D')
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=834,
                    y=843,
                    width=833,
                    height=843
                ),
                action=MessageAction(text='E')
            ),
            RichMenuArea(
                bounds=RichMenuBounds(
                    x=1662,
                    y=843,
                    width=834,
                    height=843
                ),
                action=MessageAction(text='F')
            )
        ]

        rich_menu_to_create = RichMenuRequest(
            size=RichMenuSize(
                width=2500,
                height=1686,
            ),
            selected=True,
            name="圖文選單1",
            chat_bar_text="查看更多資訊",
            areas=areas
        )

        rich_menu_id = line_bot_api.create_rich_menu(
            rich_menu_request=rich_menu_to_create
        ).rich_menu_id

        with open('./public/richmenu-a.png', 'rb') as image:
            line_bot_blob_api.set_rich_menu_image(
                rich_menu_id=rich_menu_id,
                body=bytearray(image.read()),
                _headers={'Content-Type': 'image/png'}
            )

        line_bot_api.set_default_rich_menu(rich_menu_id)
```



#### 使用json的方式

1. 複製前面用 Linebot Designer 設計好的 json，並放在 `body` 中
![image](https://hackmd.io/_uploads/Bk8HMtQ7C.png)

    `headers`放的是 CHANNEL_ACCESS_TOKEN

```python
headers = {
    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
    'Content-Type': 'application/json'
}
body = {
    "size": {
        "width": 2500,
        "height": 1686
    },
    "selected": True,
    "name": "圖文選單 1",
    "chatBarText": "查看更多資訊",
    "areas": [
        {
            "bounds": {
                "x": 0,
                "y": 0,
                "width": 833,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "A"
            }
        },
        {
            "bounds": {
                "x": 834,
                "y": 0,
                "width": 833,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "B"
            }
        },
        {
            "bounds": {
                "x": 1663,
                "y": 0,
                "width": 834,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "C"
            }
        },
        {
            "bounds": {
                "x": 0,
                "y": 843,
                "width": 833,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "D"
            }
        },
        {
            "bounds": {
                "x": 834,
                "y": 843,
                "width": 833,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "E"
            }
        },
        {
            "bounds": {
                "x": 1662,
                "y": 843,
                "width": 838,
                "height": 843
            },
            "action": {
                "type": "message",
                "text": "F"
            }
        }
    ]
}
```

2. 取得 richmenu id

```python
response = requests.post(
    'https://api.line.me/v2/bot/richmenu',
    headers=headers,
    data=json.dumps(body).encode('utf-8')
)
response = response.json()
print(response)
rich_menu_id = response["richMenuId"]
```

3. 上傳 richmenu 圖片
```python
        with open('static/richmenu-1.jpg', 'rb') as image:
            line_bot_blob_api.set_rich_menu_image(
                rich_menu_id=rich_menu_id,
                body=bytearray(image.read()),
                _headers={'Content-Type': 'image/jpeg'}
            )
```

4. 其他 richmenu 操作
    * 查看所有richmenuID
    ```python
    from linebot.v3.messaging import MessagingApi
    # 查看所有的richmenu
    line_bot_api = MessagingApi('Channel Access Token')
    rich_menu_list = line_bot_api.get_rich_menu_list()
    for rich_menu in rich_menu_list:
        print(rich_menu.rich_menu_id)
    ```
    
    * 刪除所有richmenuID
    ```python
    from linebot.v3.messaging import MessagingApi
    #刪除richmenu
    for rich_menu in rich_menu_list:
        line_bot_api = MessagingApi('Channel Access Token')
        line_bot_api.delete_rich_menu(rich_menu.rich_menu_id)
    ```

完整程式碼
```python
def create_rich_menu_2():
    with ApiClient(configuration) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_blob_api = MessagingApiBlob(api_client)

        # Create rich menu
        headers = {
            'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
            'Content-Type': 'application/json'
        }
        body = {
            "size": {
                "width": 2500,
                "height": 1686
            },
            "selected": True,
            "name": "圖文選單 1",
            "chatBarText": "查看更多資訊",
            "areas": [
                {
                    "bounds": {
                        "x": 0,
                        "y": 0,
                        "width": 833,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "A"
                    }
                },
                {
                    "bounds": {
                        "x": 834,
                        "y": 0,
                        "width": 833,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "B"
                    }
                },
                {
                    "bounds": {
                        "x": 1663,
                        "y": 0,
                        "width": 834,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "C"
                    }
                },
                {
                    "bounds": {
                        "x": 0,
                        "y": 843,
                        "width": 833,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "D"
                    }
                },
                {
                    "bounds": {
                        "x": 834,
                        "y": 843,
                        "width": 833,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "E"
                    }
                },
                {
                    "bounds": {
                        "x": 1662,
                        "y": 843,
                        "width": 838,
                        "height": 843
                    },
                    "action": {
                        "type": "message",
                        "text": "F"
                    }
                }
            ]
        }

        response = requests.post(
            'https://api.line.me/v2/bot/richmenu',
            headers=headers,
            data=json.dumps(body).encode('utf-8')
        )
        response = response.json()
        print(response)
        rich_menu_id = response["richMenuId"]
        
        # Upload rich menu image
        with open('static/richmenu-1.jpg', 'rb') as image:
            line_bot_blob_api.set_rich_menu_image(
                rich_menu_id=rich_menu_id,
                body=bytearray(image.read()),
                _headers={'Content-Type': 'image/jpeg'}
            )

        line_bot_api.set_default_rich_menu(rich_menu_id)
```


>Reference：https://developers.line.biz/en/docs/messaging-api/using-rich-menus/

Youtube 課程影片
---
<iframe width="560" height="315" src="https://www.youtube.com/embed/kF1RVtKqzV4?si=Uibs7ZMAukkKdaqb" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

{%hackmd @ntuebigdata/about %}

## 相關教材連結

<div style="display: flex; justify-content:space-between;">
  <div>
    <a class="btn btn-warning" href="https://hackmd.io/@ntuebigdata/quick-reply" style="color:white;width:300px;text-overflow:ellipsis;overflow:hidden">◀◀◀ L11 Quick Reply ◀◀◀</a>
  </div>
  <div>
    <a class="btn btn-info" href="https://hackmd.io/@ntuebigdata/deploy-linebot" style="color:white;width:300px;text-overflow:ellipsis;overflow:hidden">▶▶▶ L13 LineBot 部屬 ▶▶▶</a>
  </div>
</div>