Help us understand the problem. What is going on with this article?

LINE Messaging APIがグループ内でユーザーを認識できるようになったのでトーク管理&アルバム化Bot作ってみた

More than 3 years have passed since last update.

IMG_1341.PNG

LINE Messaging APIがグループ内でユーザーを認識できるようになったので、前から作りたかったグループにBot入れとけばトーク全部保存しといてくれて、後から2016年度とかの区切りでトークをまとめてリアルなアルバムにして郵送してくれるようなサービスのデモを作ってみました。

Botの準備

ググれば情報出てくるので適当に。または拙著「LINE BOTを作ろう! Messaging APIを使ったチャットボットの基礎と利用例」を見て下さい。

book.png

実装

こんな感じ。暗号化やってないので適宜。

index.php
// Composerでインストールしたライブラリを一括読み込み
require_once __DIR__ . '/vendor/autoload.php';

define('TABLE_NAME_MESSAGES', 'messages');

// アクセストークンを使いCurlHTTPClientをインスタンス化
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN'));
// CurlHTTPClientとシークレットを使いLINEBotをインスタンス化
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('CHANNEL_SECRET')]);
// LINE Messaging APIがリクエストに付与した署名を取得
$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];

// 署名が正当かチェック。正当であればリクエストをパースし配列へ
// 不正であれば例外の内容を出力
try {
  $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
  error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
  error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
  error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
  error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}

// 配列に格納された各イベントをループで処理
foreach ($events as $event) {
  // MessageEventクラスのインスタンスでなければ処理をスキップ
  if (!($event instanceof \LINE\LINEBot\Event\MessageEvent)) {
    error_log('Non message event has come');
    continue;
  }

  if(!$event->isGroupEvent()) {
    $bot->replyText($event->getReplyToken(), 'Add this Bot to Group.');
    continue;
  }

  if ($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage) {

    if($event->getText() == 'cmd_album') {
      replyMultiMessage($bot, $event->getReplyToken(),
        new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("以下のリンクをクリックするとトークのアルバムをプレビューできます。"),
        new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("http://" . $_SERVER["HTTP_HOST"] . "/album/" . $event->getGroupId())
      );
      continue;
    }

    appendMessage($event->getUserId(), $event->getGroupId(), $event->getTimestamp(), $event->getMessageId(), $event->getMessageType(), $event->getText());
  } else if($event instanceof \LINE\LINEBot\Event\MessageEvent\ImageMessage) {

    $response = $bot->getMessageContent($event->getMessageId());
    $fileUrl = uploadImageToCloudAppThenGetUrl($response->getRawBody());
    appendMessage($event->getUserId(), $event->getGroupId(), $event->getTimestamp(), $event->getMessageId(), $event->getMessageType(), $fileUrl);

  } else if($event instanceof \LINE\LINEBot\Event\MessageEvent\StickerMessage) {
    appendMessage($event->getUserId(), $event->getGroupId(), $event->getTimestamp(), $event->getMessageId(), $event->getMessageType(), json_encode(array('packageID' => $event->getPackageId(), 'stickerId' => $event->getStickerId())));
  } else {
    $bot->replyText($event->getReplyToken(), '未対応のメッセージ形式');
  }
}

function appendMessage($userId, $groupId, $timestamp, $messageid, $messageType, $messageBody) {
  $dbh = dbConnection::getConnection();
  $sql = 'insert into '. TABLE_NAME_MESSAGES .' (userid, groupid, timestamp, messageid, messagetype, messagebody) values (?, ?, ?, ?, ?, ?) ';
  $sth = $dbh->prepare($sql);
  $sth->execute(array($userId, $groupId, $timestamp, $messageid, $messageType, $messageBody));

}

function uploadImageToCloudAppThenGetUrl($rawBody) {
  \Cloudinary::config(array(
    "cloud_name" => "xxxxxxxxx",
    "api_key" => "0123456789123",
    "api_secret" => "xxxxxxxxxxxxxxxxxx"
  ));

  $im = imagecreatefromstring($rawBody);
  $resultString = "";
  if ($im !== false) {
      $filename = uniqid();
      $directory_path = "tmp";
      if(!file_exists($directory_path)) {
        if(mkdir($directory_path, 0777, true)) {
            chmod($directory_path, 0777);
        }
      }
      imagejpeg($im, $directory_path. "/" . $filename . ".jpg", 75);
  } else {
      error_log("fail to create image.");
  }

  $path = dirname(__FILE__) . '/' . $directory_path. "/" . $filename . ".jpg";
  $result = \Cloudinary\Uploader::upload($path);
  error_log('result : ' . var_export($result, true));

  return $result['url'];
}

データベース

DBを作ってユーザーID、グループID、タイムスタンプ、メッセージタイプ、メッセージの内容を格納できるテーブル作っときます。

格納

Eventから内容取ってDBに入れてくだけ。スタンプとか絵文字とかの処理は面倒なので後回し。

画像のみアップロードしてURLを格納しとく。

画像のアップロード

Herokuだと普通に保存しといてもデプロイする度に画像消えるのでCloudinaryのアドオン使いました。ある程度は無料でめちゃ簡単。

プレビューページ

グループID受け取ってDBなめてトーク取り出して表示するだけ。

デモ

グループに作って、家族とBotを招待します。Botは管理画面でグループに参加できるよう設定しておきましょう。

IMG_1338.PNG

また、被招待側はグループへの参加と共にBotと友だちになっておく必要があります。ユーザーIDは友達になっていなくても取れるのですが、これがないとユーザー名やプロフィール画像等のProfile取ろうとしてもNot Foundになります。適当にトークします。

IMG_1339.PNG

アルバムのプレビューをしたい時はコマンド送ります。

IMG_1340.PNG

プレビューが表示され、アルバムの注文ボタンが。タップすると印刷されたアルバムが郵送されます。背景とかレイアウトいじれるといいでしょうね。

pureview.png

まとめ

相変わらずとても使いやすいAPIなので色々夢が広がります!アイディア色々あるので引き続き色々作ります。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした