解説書いてる時間がなかったのでサンプルコードだけ貼っておきます。そのうち書く。
LINEのmessage apiを使おうと思ってuse LWP::UserAgentとuse JSONでゴリゴリ書いてたら普通にPerlのSDKがあったときの顔をしていました。SDK充実しててすごい。
line/line-bot-sdk-perl: LINE: :API – SDK of the LINE Messaging API for Perl
私はWebhookのcallback先を自宅サーバ(Raspberry Pi 2)に設置してるのでIRKit Device HTTP APIを使用できます。というかInternet HTTP API使うのめんどくさいから自宅サーバをcallback先にしたというのもあります。
IBM BluemixとかHerokuとか使ってる人はInternet HTTP APIを使ってください。
アプリはhypnotoadとMojolicious::Liteで動かしていて、リバースプロキシに(無駄に)h2oを使ってるのですが、あまり意味は無いですね。
#!/usr/bin/perl
# 2017/01/26 ちょっと書き直した
use utf8;
use strict;
use warnings;
use LINE::Bot::API;
use LINE::Bot::API::Builder::SendMessage;
use LINE::Bot::API::Builder::TemplateMessage;
use LWP::UserAgent;
use Mojolicious::Lite;
my $ua = new LWP::UserAgent();
my $CHANNEL_ACCCESS_TOKEN = "xxx";
my $CHANNEL_SECRET="xxx";
# API認証情報
my $bot = LINE::Bot::API->new(
channel_secret => $CHANNEL_SECRET,
channel_access_token => $CHANNEL_ACCCESS_TOKEN,
);
app->config(
hypnotoad => {
listen => ['http://*:8092'],
},
);
# 当初いろんなリクエストを送る予定だった
sub call_api(){
my $url = shift;
my $method = shift;
my $headers = shift;
my $content = shift;
my $req = HTTP::Request->new($method, $url);
while (my ($key, $value) = each(%$headers)){
$req->header($key => $value);
}
$req->content($content);
return $ua->request($req);
}
# IRKitのAPIを呼び出す
sub call_irkit(){
my $content = shift;
my $IRKIT = "http://192.168.10.150/messages";
my %IRKIT_H = ("X-Requested-With" => "curl");
return &call_api($IRKIT, "POST", %IRKIT_H, $content);
}
get '/' => sub {
my $self = shift;
return $self->render(template => 'index', format => 'html');
} => 'index'; #別になくても良い
post '/callback' => sub {
my $self = shift;
# LINEから受信したリクエストボディ
my $source = $self->req->body;
# シグネチャ検証
unless ($bot->validate_signature($source, $self->req->headers->header('X-Line-Signature')) ) {
return $self->render(json => {'status' => "failed to validate signature"});
}
my $events = $bot->parse_events_from_json($source);
my $event = ${ $events }[0]; #多分先頭のイベントしか使わないので
unless($event->is_message_event && $event->is_text_message){
return $self->render(json => {'status' => "not text event"});
}
# 自分以外の人が操作できないようにする
unless($event->user_id eq "my LINE ID"){
return $self->render(json => {'status' => "You are not me."});
}
my $reply_text = $event->text;
if($reply_text eq "コマンド教えて"){ # carouselの動作確認も兼ねてヘルプ
my $carousel = LINE::Bot::API::Builder::TemplateMessage->new_carousel(
alt_text => 'コマンドを教えます',
);
my @commands = ("電気つけて", "電気消して", "エアコンつけて", "エアコン消して");
for my $i (@commands) { #carouselは5つまで
my $column = LINE::Bot::API::Builder::TemplateMessage::Column->new(
title => "commands",
text => "利用頻度の高いコマンドです",
)->add_message_action(
label => $i,
text => $i,
);
$carousel->add_column($column->build);
}
my $messages = LINE::Bot::API::Builder::SendMessage->new()->add_template($carousel->build);
$bot->reply_message($event->reply_token, $messages->build);
return $self->render(json => {'status' => "200OK"});
}
my $messages = LINE::Bot::API::Builder::SendMessage->new;
$messages->add_text( text => "命令を実行します!" );
$messages->add_text( text => $reply_text );
my $commands = {
"電気つけて" => '{"format":"raw","freq":38,"data":[18031,...]}',
"電気消して" => ...,
#etc...,
};
# 受け取ったメッセージに対応するJSONをIRKitに送信する
my $command = $commands->{$reply_text};
if ($command){
&call_irkit($command);
} else { # ここの挙動をヘルプにするのもありだと思います
$messages->add_text( text => "その命令は受け付けられません!" );
}
$bot->reply_message($event->reply_token, $messages->build);
return $self->render(json => {'status' => "200OK"});
} => 'callback';
app->start;