LINE Messaging APIがグループ内でユーザーを認識できるようになったので、前から作りたかったグループにBot入れとけばトーク全部保存しといてくれて、後から2016年度とかの区切りでトークをまとめてリアルなアルバムにして郵送してくれるようなサービスのデモを作ってみました。
Botの準備
ググれば情報出てくるので適当に。または拙著「LINE BOTを作ろう! Messaging APIを使ったチャットボットの基礎と利用例」を見て下さい。
実装
こんな感じ。暗号化やってないので適宜。
// 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は管理画面でグループに参加できるよう設定しておきましょう。
また、被招待側はグループへの参加と共にBotと友だちになっておく必要があります。ユーザーIDは友達になっていなくても取れるのですが、これがないとユーザー名やプロフィール画像等のProfile取ろうとしてもNot Foundになります。適当にトークします。
アルバムのプレビューをしたい時はコマンド送ります。
プレビューが表示され、アルバムの注文ボタンが。タップすると印刷されたアルバムが郵送されます。背景とかレイアウトいじれるといいでしょうね。
まとめ
相変わらずとても使いやすいAPIなので色々夢が広がります!アイディア色々あるので引き続き色々作ります。