砂上の考察

日々の考察を残し、できれば意見をもらい、また考察する。。。

Line BotのFlex Message制作~PythonでJSONを編集~

   この記事ではプログラミングほぼ初心者の筆者がLINE BotのMessage APIFlex Message(フレックスメッセージ)を作成・導入する方法を紹介しています。Pythonを少し勉強(classらへんまで)していればお好みでアレンジができると思います。以前書いたブログを改善させたものとなっているので、良ければ以下のブログも参照してみてください。

sajyounokousatu.hatenablog.com

 

1.Flex Messageとは

   Flex Messageとは文章あるいは写真、動画だけのメッセージではなく、それらを組み合わせた下図のような独自のレイアウトのメッセージです。

   以降ではレイアウトの作り方、コードに落とし込み・状況によって変更する方法、LINE Botで送信する方法を説明したいと思います。

 

2. Flex Messageのレイアウトの作り方

   Webデザインを少しやっとことがある人は、「小さくてもめんどくさいHTMLなどのコードを書かないといけないだろうな」と思ったかもしれませんが、実はLINE公式から簡単に作れるツールが提供されています。それが下のリンクのFlex Message Simulatorです。

Flex Message Simulator

   少し前まではLINE Bot Designerというツールが使われていたっぽく、少し古いブログではそのツールが紹介されているかもしれませんが、こちらは利用はできるようですが、2022年1月に開発が終了しており、Flex Messageの作成には先に紹介したFlex Message Simulatorが推奨されています。

Flex Message作成方法の簡単な説明

   Flex Messageにはおおまかに2種類あり、bubbleとそれを複数個横に並べたcarouselがあります。bubbleはあらかじめ上から順にheader、hero、body、footerの4つに分かれており、それぞれにboxを追加することでMessageに専用の枠ができます。boxの中にはboxにはimage、button、text、filler、separatorなどが追加でき、自由にアレンジできます。状況によってテキストなどを変えたい場合があると思いますが、それについては次の章で説明します。Flex Message SimulatorのShowcaseにいろいろなサンプルがあるので、いろんなサンプルの作り方を見ることで作りたいレイアウトが作れると思います。

 

3. PythonFlex Messageを送る方法

   先に必要なパッケージをインポートします。始めに紹介した以前書いたブログを参考にされた方はメインプログラムで、

from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

のようにしていると思いますが、ここにFlexSendMessageを追加して、

from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, FlexSendMessage
)

のようにします。他にも、FollowEvent、UnfollowEvent、PostbackEventなどのパッケージがあるので興味があれば調べて追加してみてください。筆者はボタンを押すとポストバックイベントが起きるようにしたので、PostbackEventもインポートしています。

   次に先ほど紹介したFlex Message Simulatorでレイアウトを作ったら、右上に「</>View as JSON」と書かれたボタンがあると思いますので、そのボタンを押すと長い文字列が出てきます。例として下の太字の文字列とボタンからなるFlex MessageのJSONデータを用いて説明します。

payload = {
  "type": "bubble",
  "body": {
    "type": "box",
    "layout": "vertical",
    "contents": [
      {
        "type": "text",
        "text": "Brown Cafe",
        "weight": "bold",
        "size": "xl"
      },
      {
        "type": "button",
        "action": {
          "type": "uri",
          "label": "button",
          "uri": "http://linecorp.com/"
        },
        "style": "primary"
      }
    ]
  }
}

扱いやすいように上記のようにpayloadという変数に代入します。ここで、レイアウトによってはエラーが出る場合があります。筆者が確認したものですと、valueがtrueやfalseとなっているところでエラーが表示されました。これは、Pythonでは真偽はTrue、Falseのように、先頭の文字を大文字で書く仕様となっているからなので、置換などを利用してすべて修正することでエラーがなくなります。先ほどインポートしたFlexSendMessageを用いて、

flex_message = FlexSendMessage(
  alt_text='this is alt_text',
  contents=payload
)

を実行し、送れる形式に変換します。ここで、alt_textとはFlex Messageをうまく表示できなかったときや、下の写真のように通知されたときに表示されるテキストです。

そして、応答メッセージにFlex Message送る場合は、

line_bot_api.reply_message(event.reply_token, flex_message)

とすることで送れます。

 

4. Flex Messageをコードで操作する方法

   先に例としてあげた変数payloadの型を下のコードで調べると、

type(payload)

「dict」と出力され、辞書型であることがわかります。辞書型は、keyとvalueの組み合わせのデータです。筆者はこれまで辞書型のデータを扱ったことがなかったので、あまり詳しくはないですが、Flex Messageを作るのに知っておくべきことは、追加した順になること、valueに変数を代入できること、そして辞書型の変数の結合方法です。valueに変数を代入できることは、

x = 1
dic = {"a":"0", "b":x}
print(dic)

を実行すると、代入されることが確認できると思います。また、

dic1 = {"1":"apple", "2":"orange"}
dic2 = {"3":"peach"}
dic3 = {**dic1, **dic2}
print(dic3)

を実行すると辞書型の変数が追加した順に結合されることがわかります。これらを利用してFlex Messageを変えていきます。

   先に紹介したFlex Messageの例のJSONの6~22行目の"content"のvalueを見ると、辞書型のデータを要素に持つリストになっています。このリストの要素を見ると、太字のテキストとボタンが入っていることがわかります。つまり、このcontentのvalueを変数にし、状況によって変わるようにコーディングすることで簡単に変えることができます。例として下のような関数を作ると、引数に取った文字列strが表示されたボタンが引数のn個並ぶFlex MessageのJSONデータが表示できます。

def make_flex(str, n):
  temp = [
      {
        "type": "text",
        "text": "Brown Cafe",
        "weight": "bold",
        "size": "xl"
      }
  ]
  for i in range(n):
    temp.append(
      {
        "type": "button",
        "action": {
          "type": "uri",
          "label": str,
          "uri": "http://linecorp.com/"
        },
        "style": "primary"
      }
    )
  payload = {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "contents": temp
    }
  }
  return payload

print(make_flex("test", 3))

改行がなく、わかりづらい方は3章で紹介した方法で実際に送信してみると、下図のようにうまくできていることが確認できると思います。

レイアウトが複雑にだったりして、変数が増えると、わかりづらい関数となることがあるので、header、hero、body、footerごとに関数を作って、最後に先に紹介した辞書型の結合を利用して結合するのが良いと思います。あらかじめレイアウトを作るときにboxでいい感じに分けておくと、JSONデータは長くなるが、わかりやすくなり、変更が簡単になったりするので、レイアウトを見直すことも重要だと思います。

 

5. 制作したFlex Message

  実際に作ったものを下図の右のようなFlex Messageで、以前はコマンドを入力する必要があり、SPカードもSPカードの番号を送信する必要があり、間違えやすく、めんどうであったが、ボタンにすることでコマンドを覚えなくても遊べるようにできました。少し縦長なのが気になりますが、どうしようもないかなと思ってます。。。

 

6. おまけ(postbackイベントとリッチメニュー)

postbackイベント

   ボタンのアクションには指定したサイトに飛ぶuri、日時を選択するdatetimepicker、指定したメッセージを送るmessage、そしてポストバックイベントを発生させるpostbackの4つが選択できます。postbackを選択すると、表示された文字列と異なるデータをサーバー側で受け取れます。先ほど紹介した筆者の制作物では、「Draw Best」などのSPカードのボタンを押すとpostbackイベントが発生します。始めに紹介した以前書いたブログとそこで紹介したコードを見てもらえるとわかると思いますが、SPカードの番号でいくつかの関数が動くようになっており、それを直すのがめんどうだったので、ユーザにはSPカードの名前が表示され、サーバには数字が届くというような要求をちょうど満たすpostbackをアクションとして選択しました。

   では、どのように実装するかは、ほぼ初心者の自分はすぐにはわからず、

line-bot-sdk-python/README.rst at master · line/line-bot-sdk-python · GitHub

このGitHub上のドキュメントを眺めていると、WebhookHandlerの項目を見ると新たにhandlerをたす必要があることがわかり、3章で述べたようにPostbackEventをインポートし、

@handler.add(PostbackEvent)
def on_postback(event):

    reply_token = event.reply_token
    user_id = event.source.user_id
    postback_msg = event.postback.data
    message_to_user = []
    
    if postback_msg == '012':
        message_to_user.append(TextSendMessage(text='hello'))
  
    
    # ユーザーに送信するメッセージが存在しない場合
    if len(message_to_user) == 0:
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text='invalid message'),
        )
    # メッセージが存在する場合は送信
    else:
        line_bot_api.reply_message(
            event.reply_token,
            message_to_user,
        )

をメインより前に追加することで、下図のFlex Message Simulatorのdataに指定した文字列がサーバに送られ、届いたpostback_msgによって異なる挙動をするようにプログラムできます。他のWebhookイベントについても同様にインポートしhandlerを追加することで扱えます。

リッチメニュー

   リッチメニューとは何か、どうつくるのかについては公式のマニュアルにわかりやすく書いてあるので、興味ある方は下記のリンクを見てみてください。

LINE公式アカウント (LINE Official Account Manager) リッチメニューを作成するマニュアル|LINE for Business

   一応実際に作ったものを紹介します。下図が制作したもので、写真を用意していないのとデザインのセンスがないので、久しぶりに開いても困らないように必要なコマンドが押すと送信される単純なリッチメニューを作りました。

 

7. 今後について

   LINE Botについては満足いくものができたので、これで完成にしたいと思っています。他にも機械学習系やVR系のことも勉強しているので、面白い発見などがあればブログにしたいと思います。特にVRに関してはUnityのCardboardを利用して簡単に作れることはわかったが、作りたいものがなかったため中断したので、なにか案があればぜひコメントしていただきたいです。