しりとりLINE Bot ~Flex Messageを添えて~

本投稿は TECOTEC Advent Calendar 2020 の21日目の記事です。

決済認証開発システム事業部の鈴木です。

さて、しりとりは古い護法、魔除けの一種とされてきました。
この度はそんな「しりとりをするLINE Bot」を、Laravelで作成してみましたので、その際に使用した以下二つのライブラリについて簡単にご紹介したいと思います。

  1. phpQueryによるWebスクレイピング
  2. LINE Messaging API SDKによるFlex Messageの送信

しりとりLINE Bot

1. phpQuery

導入と使用方法

参考にさせて頂きました。

zipファイルをダウンロードする方法が広く紹介されているようですが、今回はcomposer経由でインストールしたかったため、以下のコマンドを実行します。

$ composer require electrolinux/phpquery

インストール後は、use phpQuery;と指定することにより、このライブラリを使用できるようになります。

use phpQuery;

class SampleClass 
{
    public function execute()
    {
        // 指定したURLのDOM情報を取得する
        $phpQuery = phpQuery::newDocumentFile('対象WebページのURL');

        // Webページ内のh1タグのテキスト情報を取得
        $h1Text = $phpQuery->find('h1')->text();
    }
}

phpQueryはjQueryがベースとなっているため、セレクタ(取得対象要素)の指定方法も概ね同じです。

注意点

phpQueryでは、PHP: PHP 7.4.x で推奨されなくなる機能 - Manualにある「波括弧を使った、配列や文字列のオフセットへのアクセス」が使用されています。
そのため、PHP7.4以上でphpQueryを使用した場合にはArray and string offset access syntax with curly braces is deprecated ~というエラーが発生するおそれがありますこと、ご注意ください(2020/12/21時点)。

2. LINE Messaging API SDK

導入と使用方法

参考にさせて頂きました。

本投稿にて特筆すべきことはございませんので、割愛致します。

Flex Messageの作成

Flex Messageに関する公式ドキュメントは以下にございます。 developers.line.biz

デザインを決める

Flex Message Simulatorを使用して、レイアウトをカスタマイズします。
今回は文字情報だけなのであまり面白味がありませんが、画像やボタンなど、多様な要素を設定できるようです。

Flex Simulator

右上にある</>View as JSONボタンを押下すると、Simulatorが作成してくれたjsonの内容を確認できます。こちらを元に、LaravelでFlex Messageを送信できるようにしていきます。

FlexMessageBuilder を作成する

メッセージを返信するために使用するのが、以下のメソッドです。

replyMessage( string $replyToken, LINE\LINEBot\MessageBuilder $messageBuilder)

第二引数が返信内容となりますが、こちらにLINE\LINEBot\MessageBuilderインターフェイスを適用したクラスを設定するよう指定されています。
Flex Messageの場合は、最終的にLINE\LINEBot\MessageBuilder\FlexMessageBuilderを作成することになります。最終的に、と記載した通り少々段階を踏む必要がありますので、焦らず慌てず進めて参りましょう。

「小さな要素を大きな箱に詰めていく」

今回対象とするjson(抜粋版)は、以下の通りです。

{
  "type": "bubble", // ③
  "header": {
    "type": "box", // ②
    "layout": "vertical",
    "contents": [
      {
        "type": "text", // ①
        "text": "て‐こ【×梃子/×梃】",
        "weight": "bold",
        "wrap": true
      }
    ],
    "paddingBottom": "sm",
    "paddingTop": "xl"
  },
  "body": {
  …省略…
  },
  "footer": {
  …省略…
  }
}

見出しに「小さな要素を大きな箱に詰めていく」と記載した通り、①(text)→②(box)→③(bubble)の順に作成した結果がこちらです。

// ①header、contents内のテキスト要素を作成
$headerText = new LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\TextComponentBuilder('て‐こ【×梃子/×梃】');
$headerText->setWeight('bold');
$headerText->setWrap(true);

// ②header用のBoxComponentBuilderを作成
$headerBox = new LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\BoxComponentBuilder('vertical', [$headerText]); // ①で作成したテキスト要素を詰める
$headerBox->setPaddingBottom('sm');
$headerBox->setPaddingTop('xl');

// body、footerも同様

// ③BubbleContainerBuilder生成
$container = new LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\BubbleContainerBuilder();
$container->setHeader($headerBox); // ②で作成したheaderを詰める

// bodyはsetBody、footerはsetFooterで詰める

①テキストを作り、②そのテキストを詰めたboxを作り、③一番大きな箱に作ったboxをヘッダーとして詰める、という流れですね。body、footer部分を省略しておりますが、実施手順は同様です。
もっと他にスマートな方法もありそうですが、時には愚直であった方がよいこともあるかもしれません。

この状態で、Simuratorが用意してくれたjsonと同等の内容を作成することができた、ということになります。
肝心のFlexMessageBuilderがまだありませんので、早速そちらに作った要素を詰めましょう。

// 第二引数に、作成したBubbleContainerBuilderを詰める
$flexMessage = new LINE\LINEBot\MessageBuilder\FlexMessageBuilder('て‐こ【×梃子/×梃】', $container);

$flexMessage->buildMessage();を呼び出すと、Messaging APIリファレンス | LINE Developers に記載のあるjsonと同じような構成になっていることが確認できるかと思います。
あとは先にお示ししていたreplyMessageにのせるだけですね。

$bot->replyMessage($replyToken, $flexMessage);

※$bot(LINEBotクラス)の生成や、$replyTokenの取得に関しては、参考記事をご覧ください。

一度に複数メッセージを返信する

今回は一度の返信で複数メッセージを送信したかったため、更に大きな箱(MultiMessageBuilder)を使用しました。

$multiMessageBuilder = new LINE\LINEBot\MessageBuilder\MultiMessageBuilder();

// 作成したFlex Messageを詰める
$multiMessageBuilder->add($flexMessage);

// Flex Message以外も詰められます
$multiMessageBuilder->add(new LINE\LINEBot\MessageBuilder\TextMessageBuilder('普通のテキストメッセージです'));

作成したMultiMessageBuilderクラスのオブジェクトをreplyMessageの第二引数に指定することで、複数メッセージの送信が実現できます。

おわりに

私「しりとり」
bot ( ・`ω・´)「りゅうさん」
bot ( ˘ω˘ ) 「最後の文字が「ん」になったため、しりとりを終了します」

私「林檎飴」
bot ( ・`ω・´) 「メチシリンたいせいおうしょくブドウきゅうきん!」
bot ( ˘ω˘ ) 「最後の文字が「ん」になったため、しりとりを終了します 」

こちらは実際に発生した、私としりとりbotのやり取りです。
「返却対象には『ん』で終わる言葉も含める」というのは仕様通りの挙動なのですが、よもや二連続で開始直後に自爆するぽんこつになろうとは、予想しておりませんでした。今後手を加えることがあるならば、「botが負ける確率を調整する」は必須対応となるでしょう。

なお、LINE Messaging APIについては、以前コンテンツ開発事業部の江田さんがご作成くださった記事がございますので、是非ご覧ください。

tec.tecotec.co.jp

江田さんとは、つい最近ご縁があり、私が携わっている案件において大変なお力添えを賜りました。
テコテックはそのような部署の垣根を越えた知見の共有、柔軟なサポートの実現を図っている会社です。

www.tecotec.co.jp