2016-04-30

LINE BOT APIを利用して電車遅延情報の送信を改良した

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
※サンプルをLINE BOT APIからLINE Messaging APIに書き換えたものを以下で公開しました。
https://kingyo-bachi.blogspot.jp/2017/04/line-bot-apiline-messaging-api.html

以前
LINE BOT APIを利用して電車遅延情報を送信する
というのを書いたのですが、ちょっと改造しました。

以下をできるようにしようと思います。
・祝日は通知しなくてよくしたい
・localで実行しているがIPアドレスが変わる可能性があるので送信できなかったときはメール通知をしたい

祝日に関してはholiday_jpというgemを使って判別することにしました。
https://github.com/komagata/holiday_jp

メール送信はGmailを利用しようと思います。以下が参考になりました。
http://qiita.com/nownabe/items/3a348c86b3c0a2c87ab0
http://grottad.com/blog/228


で、改良版の電車遅延情報を送信するものは以下のとおりです。

# coding: utf-8
require 'rest-client'
require 'json'
require 'date'
require 'holiday_jp'
require 'gmail'
class MyMail
ID = "GMail address"
PW = "GMail password"
TO = "mail send to address"
def self.send(sbj,msg)
gmail = Gmail.new(ID, PW)
message =
gmail.generate_message do
to TO
subject sbj
body msg
end
gmail.deliver(message)
gmail.logout
end
end
class LineBot
ID = "Channel ID"
SECRET = "Channel Secret"
MID = "MID"
TO = "送信先のID"
def self.send(msg)
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"X-Line-ChannelID" => ID,
"X-Line-ChannelSecret" => SECRET,
"X-Line-Trusted-User-With-ACL" => MID
}
params = {
to: [TO],
toChannel: "1383378250",
eventType: "138311608800106203",
content: {
contentType: 1,
toType: 1,
text: msg,
}
}
RestClient.post "https://trialbot-api.line.me/v1/events", params.to_json, headers
end
end
class TrainChk
@@cache = nil
def self.delay?(company,line)
if @@cache.nil?
begin
response = RestClient.get "https://rti-giken.jp/fhc/api/train_tetsudo/delay.json"
rescue => e
p e.response
return
end
json = JSON.parser.new(response.to_str)
hash = json.parse()
@@cache = hash
end
hash = @@cache
ret = false
hash.each do |h|
ret = true if h["company"] == company and h["name"] == line
end
ret
end
end
if HolidayJp.holiday?(Date.today)
print "#{Time.now.to_s} holiday!\n"
exit
end
ret = []
[
["JR東日本","山手線"],
["JR東日本","東海道線"],
["JR東日本","中央線快速電"],
["東京メトロ","丸ノ内線"],
["東京メトロ","東西線"],
].each do |a|
ret.push(a) if TrainChk.delay?(a[0],a[1])
end
unless ret.size == 0
msg = "電車遅延が発生しています。"
ret.each do |a|
msg = msg + "\n #{a[1]}"
end
begin
LineBot.send(msg)
rescue => e
print "#{Time.now.to_s} line bot error raise!\n"
MyMail.send "line bot error raise",e.response
exit
end
print "#{Time.now.to_s} delay train!\n"
else
print "#{Time.now.to_s} no delay train.\n"
end
view raw train_chk2.rb hosted with ❤ by GitHub


これを以下のような感じでcron設定して月曜から金曜までの出勤前の6:50に動作するようにしました。
50 6 * * 1,2,3,4,5 /usr/bin/ruby /home/hogehoge/ruby/line_bot/train_chk2.rb >> /home/hogehoge/ruby/line_bot/train_chk.log

2016-04-29

財布を買い換えてみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今まで以下の「エムピウ m+ 二つ折り財布」を使っていたのですが、だいぶボロになってきてしまいました。



買い換えるにあたり財布の中身を断捨離してコンパクトなものにしたいなぁと思ったわけです。
またキーホルダーもちょっとついでに買い換えたいなぁと思ったわけです。

最初に気になったのは、以下の「薄いマネークリップ abrAsus (アブラサス)」と「小さい小銭入れ abrAsus (アブラサス)」の組み合わせです。



ですが、本当にこのサイズでいけるのかが不安であったりもします。いざ買ってみてちょっと合わなかった場合を考えるとちょっとお高めな感じもします。
なのでもうちょっとお安く同じようなものがないか探して見ました。

「小さい小銭入れ abrAsus (アブラサス)」の代わりになるものは、なかかなか見つからなかったのですが以下を見つけました。





「薄いマネークリップ abrAsus (アブラサス)」の方は、お安めのマネークリップがそこそこありました。
その中で以下を選んで見ました。断捨離実行に弱気になってカードがそこそこ入るのがポイントです。


そしてカードを断捨離しきれなかった保険として以下も買いました。


とりあえず入れ替えてみた結果、以下のような感じになりました。


カードの断捨離を全然していないのでトータルの厚みは増えてしまっています。
そのうち断捨離するとして、とりあえず違う場所にしまえるようになったので、まぁよしとします。

ちょっと使ってみた感想としては、もともと財布を入れていた場所がマネークリップだけになっているので軽い感じにはなっています。
あとキーホルダーと小銭要れが一緒になったので軽い買い物は、これだけでいけるのも便利です。

今まで一つの財布に入っていたものが分かれてしまっている、ちょっとまだどこに何を入れたかがあやふやだったり、場合によっては二つ出さないといけないので戸惑いはありますが、きっとなれていくことでしょう。





2016-04-27

LINE BOT APIを利用して電車遅延情報を送信する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LINE BOT APIを利用してメッセージを送信するには、以下のような感じでできます。

# coding: utf-8
require 'rest-client'
require 'json'
ID = "Channel ID"
SECRET = "Channel Secret"
MID = "MID"
TO = "送信先のID"
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"X-Line-ChannelID" => ID,
"X-Line-ChannelSecret" => SECRET,
"X-Line-Trusted-User-With-ACL" => MID
}
params = {
to: [TO],
toChannel: "1383378250",
eventType: "138311608800106203",
content: {
contentType: 1,
toType: 1,
text: "てすとbot",
}
}
p params.to_json
begin
RestClient.post "https://trialbot-api.line.me/v1/events", params.to_json, headers
rescue => e
p e.response
exit
end
p "send ok"
view raw send_msg.rb hosted with ❤ by GitHub


ローカル環境で利用することを前提にしています。
送信先IDはcallbackを設定してなんとか事前に取得しておく必要があります。

これでメッセージは送信できたのですが、せっかくなので役に立つ機能を作りたいものです。
なので電車が遅延していたら通知するbotを作ってみます。
適当な時間に自動実行できるようにさせたら便利な気がします。

電車遅延情報の取得は
鉄道遅延情報のjson(https://rti-giken.jp/fhc/api/train_tetsudo/)
を使わせていただきます。

以下のような感じです。

# coding: utf-8
require 'rest-client'
require 'json'
class LineBot
ID = "Channel ID"
SECRET = "Channel Secret"
MID = "MID"
TO = "送信先のID"
def self.send(msg)
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"X-Line-ChannelID" => ID,
"X-Line-ChannelSecret" => SECRET,
"X-Line-Trusted-User-With-ACL" => MID
}
params = {
to: [TO],
toChannel: "1383378250",
eventType: "138311608800106203",
content: {
contentType: 1,
toType: 1,
text: msg,
}
}
begin
RestClient.post "https://trialbot-api.line.me/v1/events", params.to_json, headers
rescue => e
p e.response
return
end
end
end
class TrainChk
@@cache = nil
def self.delay?(company,line)
if @@cache.nil?
begin
response = RestClient.get "https://rti-giken.jp/fhc/api/train_tetsudo/delay.json"
rescue => e
p e.response
return
end
json = JSON.parser.new(response.to_str)
hash = json.parse()
@@cache = hash
end
hash = @@cache
ret = false
hash.each do |h|
ret = true if h["company"] == company and h["name"] == line
end
ret
end
end
ret = []
[
["JR東日本","山手線"],
["JR東日本","東海道線"],
["JR東日本","中央線快速電"],
["東京メトロ","丸ノ内線"],
["東京メトロ","東西線"],
].each do |a|
ret.push(a) if TrainChk.delay?(a[0],a[1])
end
msg = "電車遅延は発生していません"
unless ret.size == 0
msg = "電車遅延が発生しています。"
ret.each do |a|
msg = msg + "\n #{a[1]}"
end
end
LineBot.send(msg)
view raw train_chk.rb hosted with ❤ by GitHub


遅延を確認したい電車情報の部分は、
鉄道遅延情報のjson(https://rti-giken.jp/fhc/api/train_tetsudo/)
を見ながら適当に変更します。

なんとなく便利そうな気がします。


LINE BOT APIを使ってみた感想としては、まだトライアルで機能が少ないので機能追加を期待したいところです。
個人的には以下のような改善されるとうれしいなぁと思うしだいです。
・グループチャットにbotから送信ができるようになってほしい
・callbackがなくてもフレンドリストなどを取得できるようになってほしい
・IPのホワイトリストは、めんどくさいのでなくしてもらいたいなぁ

LINE BOT APIのcallbackにAWS Lambdaを使ってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
※サンプルをLINE BOT APIからLINE Messaging APIに書き換えたものを以下で公開しました。
https://kingyo-bachi.blogspot.jp/2017/04/line-bot-apiline-messaging-api.html

LINE BOT APIを試すにはcallbackを設定しないと試せることがほとんどないことがわかったのでcallbackを設定できるようにします。

VPSとかすでに持っているのならば簡単なのでしょうが、残念ながら私はお手軽に使えるものを持っていません。

他の方の例などを見るとAWS LambdaにAPI Gatewayを組み合わせるとお手軽な気配だったのでやってみました。

ちなみにLambdaとかで何ができるかと、ちっともわかってなかったのですが、以下が参考になりました。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/getting-started.html

試してみた結論としては、お手軽に動作を見るにはLambdaはよい感じなのですが、ずっとcallbackとして利用するにはIPアドレスが変わってしまうので使い続けることは現実的ではなさそうでした。

ずっと使うには向いてないかもしれないですが、お手軽に試すにはよかったのでLambdaでLINE BOT APIを使う方法を紹介します。


Lambdaの画面でCreate a Lambda Functionをクリック



ここはSKIPを選択します。



適当にName欄に名前をつけて、RuntaimeにNode.js 0.10を選択します。



コードを記載します。


記載するコードは以下のような感じです。
var https = require('https');
exports.handler = function(event, context) {
console.log('Received event:', JSON.stringify(event, null, 2));
var msg = event.result[0];
console.log('Message To', msg.content.from.toString());
var data = JSON.stringify({
to: [msg.content.from.toString()],
toChannel: 1383378250,
eventType: "138311608800106203",
content: msg.content
});
var url ='https://trialbot-api.line.me/v1/events';
var opts = {
host: 'trialbot-api.line.me',
path: '/v1/events',
headers: {
"Content-type": "application/json; charset=UTF-8",
"X-Line-ChannelID": "Channel ID",
"X-Line-ChannelSecret": "Channel Secret",
"X-Line-Trusted-User-With-ACL": "MID"
},
method: 'POST'
}
var req = https.request(opts, function(res){
res.on('data', function(chunk){
console.log(chunk.toString())
}).on('error', function(e){
console.log('ERROR: '+ e.stack);
})
})
req.write(data)
req.end();
};



RoleをそれっぽいものにしてNextをクリック



Create functionをクリック



これでLambdaファンクションはできあがります。なんとなくTestをクリックします



Save and testをクリック



下の方にtestの結果が表示されます。エラーはでますが、Log outputにとりあえず受け取ったイベントが表示されているのでよしとします。



作成したLambdaファンクションにAPI Gatewayを設定します。
API endpointsタブを選択してAdd API endpointをクリック



API nameを適当につけて
MethodをPOST
SecurityをOpen
にしてSubmitをクリック



API Gatewayが設定されました
API endpoint URLをコピーします。



LINEのcallback設定ページにいって上記のURLをペーストします。その際に443を追加します。


しばらくしてから(10分後ぐらいには使えました)、LINEでbotにメッセージを送ります。
ですが、botのIPをホワイトリストに登録してないので何も返答がありません。
またlambdaの方に戻ります。
Monitoringタブを選択して、View logs in CloudWatchをクリック



logの中にLINEにはじかれたIPアドレスが表示されているので確認します。



そのIPアドレスをLINEの方のホワイトリストに登録します


これで再度LINEからbotにメッセージを送ると同じメッセージをbotが返してくれるようになります。
そしてlogの方でもうまくいったことが確認できます。
そしてlogに自分のLINEアカウントのIDを記録するようにしたので、それも確認できます。




以下のページが参考になりました。
http://dev.classmethod.jp/cloud/build-line-bot-api-using-lambda/
http://qiita.com/teyosh/items/567ee416c94c2af2fe91
http://shunirr.hatenablog.jp/entry/2016/04/13/164902

2016-04-26

LINE BOT APIをまずはできるところまで試す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LINE BOT APIが利用できるようになり、いろんな方が試しているようなので試してみることにしました。

利用を開始する手順は以下が参考になりました。
https://www.panzee.biz/archives/9115
(今は上限に達して登録はできないようです)

APIを利用するためにはメッセージを受け取るcallbackの設定が必要なのですが、インターネットで受け取れるようなサーバを持っていないので、callbackの設定なしで自分のローカル環境だけでできるところまでやってみることにします。

私がやりたいなぁと思っていることは、なんらかの情報をグループチャットに通知するだけで、BOTでよくある対話的なことは、まぁ後でもよいかなぁと思っているのでcallbackなしでいろいろできると便利です。

ただ結論から言うとcallbackを用意しないと自分のプロファイルを取得することしかできなかったです。なのでとりあえず利用できるということが確認できることぐらいしか今はできないようです。

以下のような感じで試せます。

まずはAPIをたたくもとのIPアドレスをホワイトリストに登録が必要なので以下などでIPアドレスを調べてホワイトリストに登録します。
https://www.cman.jp/network/support/go_access.cgi

ここまで準備できて、linuxを利用できるならばcurlで以下のようにすれば、とりあえず確認ができます。

curl -H "X-Line-ChannelID: 自分のChannel_ID" -H "X-Line-ChannelSecret: 自分のChannel _Secret" -H "X-Line-Trusted-User-With-ACL: 自分のMID" -XGET https://trialbot-api.line.me/v1/profiles?mids=自分のMID

rubyでたたくならば以下のような感じです。

# coding: utf-8
require 'rest-client'
require 'json'
ID = "Channel ID"
SECRET = "Channel Secret"
MID = "MID"
response = RestClient::Request.execute(
:method => :get,
:url => "https://trialbot-api.line.me/v1/profiles?mids=#{MID}",
:headers => {"X-Line-ChannelID" => ID,
"X-Line-ChannelSecret" => SECRET,
"X-Line-Trusted-User-With-ACL" => MID}
)
json = JSON.parser.new(response.to_str)
hash = json.parse()
p hash
puts hash["contacts"][0]["displayName"]

以下が参考になりました。
http://ola.kironono.com/entry/2016/04/09/205251

できるのがこれだけだと寂しいのでcallbackできるものを準備できるようにしようと思います。