2017-04-04

LINE BOT APIを使っていたものをLINE Messaging APIに書き直す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
すごく今更ですが、以前LINE BOT APIを使ってみたものを、LINE Messaging APIに直したものを紹介します。

ちなみにLINE Messaging APIを始めるには、以下が参考になりました。
http://milk0824.hatenadiary.jp/entry/2016/10/01/211555

まずは、
LINE BOT APIのcallbackにAWS Lambdaを使ってみる
を直したのは、以下のような感じです。
var https = require('https');
exports.handler = function(event, context) {
console.log('Received event:', JSON.stringify(event, null, 2));
var reply_token = event.events[0].replyToken;
var data = JSON.stringify({
replyToken: reply_token,
messages:[
{
"type": "text",
"text": event.events[0].message.text
}
]
});
var opts = {
host: 'api.line.me',
path: '/v2/bot/message/reply',
headers: {
"Content-type": "application/json; charset=UTF-8",
"Authorization": " Bearer " + "Channel Access Token"
},
method: 'POST'
};
var req = https.request(opts, function(res){
res.on('data', function(chunk){
console.log(res.statusCode + chunk.toString());
}).on('error', function(e){
console.log('ERROR: '+ e.stack);
});
});
req.write(data);
req.end();
};

お次は、rubyで書いたものです。
ruby2.0以上ならば、line-bot-apiというgemがあり、こっちを使うと、もうちょっと楽にかけそうなのですが、以下はruby1.9でも動くことを前提としているのでline-bot-apiは使っていません。

rubyで書いたものの最初の、
LINE BOT APIを利用して電車遅延情報の送信を改良した
を直したのは、以下のような感じです。
# 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
TOKEN = "Channel Access Token"
TO = "送信先のID"
def self.send(msg)
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"Authorization" => "Bearer #{TOKEN}",
}
params = {
to: TO,
messages: [
{
type: "text",
text: msg,
}
]
}
RestClient.post "https://api.line.me/v2/bot/message/push", 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_chk3.rb hosted with ❤ by GitHub

そして、
LINE BOT APIを利用してGoogle Calendarの情報を通知する
を直したのは、以下のような感じです。
ちなみにキャンセルされた予定の処理を追加しています。
# coding: utf-8
require 'rest-client'
require 'json'
require 'date'
require 'gmail'
require 'yaml'
#google-api-clientはv0.6.4が必要です
require "google/api_client"
class MyMail
#GMail関連の設定
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
#LINE関連の設定
TOKEN = "Channel Access Token"
TO = "送信先のID"
def self.send(msg)
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"Authorization" => "Bearer #{TOKEN}",
}
params = {
to: TO,
messages: [
{
type: "text",
text: msg,
}
]
}
RestClient.post "https://api.line.me/v2/bot/message/push", params.to_json, headers
end
end
class GCal
def initialize(list)
@g_list = list
yaml_path = File.expand_path(".google-api.yaml",File.dirname(__FILE__))
oauth = YAML.load_file(yaml_path)
@client = Google::APIClient.new({:application_name => "line_bot_gcal",:application_version => "1.0"})
@client.authorization.client_id = oauth["client_id"]
@client.authorization.client_secret = oauth["client_secret"]
@client.authorization.scope = oauth["scope"]
@client.authorization.refresh_token = oauth["refresh_token"]
@client.authorization.access_token = oauth["access_token"]
if @client.authorization.refresh_token && @client.authorization.expired?
@client.authorization.fetch_access_token!
end
@service = @client.discovered_api('calendar', 'v3')
end
def get_gids
gcal_list = @client.execute(:api_method => @service.calendar_list.list)
gcal_ids = []
gcal_list.data.items.each do |c|
gcal_ids.push [c["summary"],c["id"]] if @g_list.include? c["summary"]
end
gcal_ids
end
def get_event(day)
@day = day
gcal_ids = get_gids
params = {}
params['timeMin'] = Time.utc(day.year, day.month, day.day, 0).iso8601
params['timeMax'] = Time.utc(day.year, day.month, day.day, 23, 59, 60).iso8601
@event = {}
gcal_ids.each do |gcal|
params['calendarId'] = gcal[1]
params.delete("pageToken") unless params["pageToken"].nil?
events = @client.execute(:api_method => @service.events.list,:parameters => params)
while true
events.data.items.each do |e|
@event[gcal[0]] = [] if @event[gcal[0]].nil?
@event[gcal[0]].push e
end
break if !(page_token = events.data.next_page_token)
params["pageToken"] = page_token
events = @client.execute(:api_method => @service.events.list,:parameters => params)
end
end
end
def make_msg
d = {}
d[:at] = {}
d[:from] = {}
d[:to] = {}
day = @day.strftime("%Y-%m-%d")
nday = (@day + 1).strftime("%Y-%m-%d")
@event.each do |k,v|
conf = []
canc = []
v.each do |e|
if e.status == "cancelled"
canc.push(e.recurringEventId)
else
conf.push(e.id)
end
end
ok = conf - canc
v.each do |e|
next if e.status == "cancelled"
next unless ok.include? e.id
if e.start.date.nil?
if e.recurrence.size == 0
next unless e.start.date_time.strftime("%Y-%m-%d") == day
end
d[:at][k] = [] if d[:at][k].nil?
msg = e.start.date_time.strftime("%H:%M")
msg = msg + " - "
if e.recurrence.size == 0
msg = msg + e.end.date_time.strftime("%m/%d ") unless e.end.date_time.strftime("%Y-%m-%d") == day
end
msg = msg + e.end.date_time.strftime("%H:%M")
msg = msg + " " + e.summary
d[:at][k].push msg
else
type = nil
case
when ((e.start.date == day) and (e.end.date == nday))
type = :at
when e.start.date == day
type = :from
when e.end.date == nday
type = :to
end
next if type.nil?
d[type][k] = [] if d[type][k].nil?
d[type][k].push e.summary
end
end
end
ret = nil
s = {:at => "",:from => "から",:to => "まで"}
["at" , "from" , "to"].each do |t|
t = t.to_sym
unless d[t].size == 0
ret = ret.nil? ? "" : ret + "\n"
ret = ret + day + s[t] + "の予定"
d[t].each do |k,v|
ret = ret + "\n [" + k + "]"
v.sort.each do |e|
ret = ret + "\n " + e
end
end
end
end
ret
end
end
#送信したいカレンダー名を列挙する
GCAL_LIST = [
"お仕事",
"記念日",
"遊び",
]
g = GCal.new(GCAL_LIST)
tmr = Date.today + 1
g.get_event(tmr)
msg = g.make_msg
unless msg.nil?
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} send event!\n"
else
print "#{Time.now.to_s} no event.\n"
end
view raw gcal_chk2.rb hosted with ❤ by GitHub

最後に、
LINE BOT APIを利用して雨が降りそうな時は通知するようにしてみる
を直したのは、以下のような感じです。
# coding: utf-8
require 'rest-client'
require 'json'
require 'date'
require 'holiday_jp'
require 'gmail'
require 'rexml/document'
class MyMail
#GMail関連の設定
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
#LINE関連の設定
TOKEN = "Channel Access Token"
TO = "送信先のID"
def self.send(msg)
headers = {
"Content-Type" => "application/json; charser=UTF-8",
"Authorization" => "Bearer #{TOKEN}",
}
params = {
to: TO,
messages: [
{
type: "text",
text: msg,
}
]
}
RestClient.post "https://api.line.me/v2/bot/message/push", params.to_json, headers
end
end
class RainChk
#降水確率を取得したい地域情報
#以下を確認して設定する
#http://www.drk7.jp/weather/
#以下は東京の例
PREF = "http://www.drk7.jp/weather/xml/13.xml"
AREA = "東京地方"
def self.get_info(day,limit)
begin
response = RestClient.get PREF
rescue => e
p e.response
end
doc = REXML::Document.new response.to_str
day = day.strftime("%Y/%m/%d")
ret = {}
ret[:rain] = false
ret[:info] = []
doc.elements.each("weatherforecast/pref/area[@id='#{AREA}']/info[@date='#{day}']/rainfallchance/period") do |element|
next if element.attributes["hour"] == "00-06"
ret[:info].push [element.attributes["hour"],element.text + "%"]
ret[:rain] = true if element.text.to_i >= limit
end
ret
end
end
if HolidayJp.holiday?(Date.today)
print "#{Time.now.to_s} holiday!\n"
exit
end
#確認したい日付と降水確率が何%以上で雨を降るとみなすかの閾値を渡す
ret = RainChk.get_info Date.today,50
if ret[:rain]
msg = "雨が降るかもしれません。"
ret[:info].each do |a|
msg = msg + "\n #{a[0]} #{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} rainy day!\n"
else
print "#{Time.now.to_s} sunny day.\n"
end
view raw rain_chk2.rb hosted with ❤ by GitHub