こんにちは、ミナピピン(@python_mllover)です!
今回は仕事でLINEのAPIを使って表示されるリッチメニューをユーザーごとに分けてほしいという依頼を頂いてその調査結果をメモとしてまとめておこうと思います。
具体的にはGoogle先生で「line api リッチメニュー python」みたいなワードでググると以下のサイトがヒットするのですが、か書かれたのが2017年で情報が古くコードが動かなくなっていたのでAPIドキュメントを見て書き直しました。
参考サイト:https://qiita.com/uezo/items/2dd9db3046ef7b28ed2e
前提となるAPIのチャンネルの作成やアクセストークンやシークレットトークンの確認方法については特に変わっていないので、上の記事や以下の参考書籍を参考にしてください。
クラス定義&初期設定
まずはクラス定義の部分で、APIのURLとかリクエスト形式が変わっていて実行するとエラーを吐いていたので書き直して、追加で今回の作業に最低限必要な機能だけ関数として付け加えました。
class RichMenu: def __init__(self, name, chat_bar_text, size_full=True, selected=False): self.size = {"width": 2500, "height": 1686} if not size_full: self.size["height"] = 843 self.selected = selected self.name = name self.chat_bar_text = chat_bar_text self.areas = [] def add_area(self, x, y, width, height, action_type, payload): bounds = {"x": x, "y": y, "width": width, "height": height} action = {"type": action_type} if action_type == "postback": if isinstance(payload, list): action["data"] = payload[0] if len(payload) > 1: action["text"] = payload[1] else: action["data"] = payload elif action_type == "uri": action["uri"] = payload else: action["text"] = payload self.areas.append({"bounds": bounds, "action": action}) def to_json(self): dic = {"size": self.size, "selected": self.selected, "name": self.name, "chatBarText": self.chat_bar_text, "areas": self.areas} return json.dumps(dic) class RichMenuManager: def __init__(self, channel_access_token, verify=True): self.headers = {"Authorization": "Bearer {%s}" % channel_access_token} self.verify = verify def register(self, rich_menu, image_path=None): url = "https://api.line.me/v2/bot/richmenu" res = requests.post(url, headers=dict(self.headers, **{"content-type": "application/json"}), data=rich_menu.to_json(), verify=self.verify).json() print(res) if image_path: up_res = self.upload_image(res["richMenuId"], image_path) if up_res == {}: print(up_res,'画像をアップロードに成功しました!') return res def upload_image(self, rich_menu_id, image_path): url = "https://api-data.line.me/v2/bot/richmenu/%s/content" % rich_menu_id image_file = open(image_path, "rb") headers=dict(self.headers, **{"content-type": "image/jpeg"}) print('json',headers) return requests.post(url, headers=headers, data=image_file, verify=self.verify).json() def download_image(self, richmenu_id, filename=None): url = "https://api.line.me/v2/bot/richmenu/%s/content" % richmenu_id res = requests.get(url, headers=self.headers, verify=self.verify) print('dl',res) if filename: with open(filename, "wb") as f: f.write(res.content) else: return res.content def get_list(self): url = "https://api.line.me/v2/bot/richmenu/list" return requests.get(url, headers=self.headers, verify=self.verify).json() def remove(self, richmenu_id): url = "https://api.line.me/v2/bot/richmenu/%s" % richmenu_id return requests.delete(url, headers=self.headers, verify=self.verify).json() def remove_all(self): menus = self.get_list() for m in menus["richmenus"]: self.remove(m["richMenuId"]) def apply(self, user_id, richmenu_id): url = "https://api.line.me/v2/bot/user/%s/richmenu/%s" % (user_id, richmenu_id) print(url) return requests.post(url, headers=self.headers, verify=self.verify).json() def set_default(self, richmenu_id): url = "https://api.line.me/v2/bot/user/all/richmenu/%s" % (richmenu_id) print(url) return requests.post(url, headers=self.headers, verify=self.verify).json() def get_default(self): url = "https://api.line.me/v2/bot/user/all/richmenu" return requests.get(url, headers=self.headers, verify=self.verify).json() def detach(self, user_id): url = "https://api.line.me/v2/bot/user/%s/richmenu" % user_id return requests.delete(url, headers=self.headers, verify=self.verify).json() def get_applied_menu(self, user_id): url = "https://api.line.me/v2/bot/user/%s/richmenu" % user_id return requests.get(url, headers=self.headers, verify=self.verify).json()
ここからはコードを実行してAPI経由でリッチメニューを設定していきます。
# 初期設定&インスタンス作成 channel_access_token = "自分のアクセストークン" rmm = RichMenuManager(channel_access_token)
とりあえず4分割画面のリッチメニューを設定します。
rm = RichMenu(name="Test menu", chat_bar_text="Open this menu") rm.add_area(0, 0, 1250, 843, "message", "質問があります") rm.add_area(1250, 0, 1250, 843, "uri", "http://imoutobot.com") rm.add_area(0, 843, 1250, 843, "postback", "data1=from_richmenu&data2=as_postback") rm.add_area(1250, 843, 1250, 843, "postback", ["data3=from_richmenu_with&data4=message_text", "ポストバックのメッセージ"]) # リッチメニューの画像を登録する res = rmm.register(rm, r"path/to/〇〇.jpg") richmenu_id = res["richMenuId"] print("Registered as " + richmenu_id)
リッチメニューに登録する画像はサイズ制限やピクセル制限・アスペクト比制限があるのでそれらをクリアするものにしてください。
そしてレスポンスでリッチメニューIDが返ってきています。このIDを使ってデフォルト表示のリッチメニューやユーザーごとの個別リッチメニューを設定していきます。
ユーザーごとに個別のリッチメニューの設定する
いよいよ本題のユーザーごとのリッチメニュー設定に入っていきます。まずデフォルトのリッチメニューの設定は以下のコードを実行するだけです。
# デフォルトのリッチメニューを設定する rmm.set_default(richmenu_id)
そして、ユーザーごとのリッチメニュー設定は以下のコードになります。
# ユーザーごとに個別のリッチメニューを設定する user_id = "ユーザーの内部ID" rmm.apply(user_id, richmenu_id)
ここで注意なのはLINEのアプリに表示されているユーザIDを指定すると{‘message’: “The value for the ‘userId’ parameter is invalid”}というエラーが返ってくるので、引数のユーザーIDはLINEのアプリ上に表示されるIDではなく内部ID(mid)と呼ばれる16進数のユニークな数字ないといけないという点。正直コード作成よりもこの内部ユーザーIDの把握に手間取りました。
内部ユーザーIDの確認方法についてはherokuでwebhook URL用のサーバーを立ち上げてそこに送られてくるレスポンスで確認するしかないと思うのですが、結構手間が掛かるので別記事で紹介したいと思います。では~
関連記事:
コメント