ちなみにLINE Messaging APIを始めるには、以下が参考になりました。
http://milk0824.hatenadiary.jp/entry/2016/10/01/211555
まずは、
LINE BOT APIのcallbackにAWS Lambdaを使ってみる
を直したのは、以下のような感じです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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を利用して電車遅延情報の送信を改良した
を直したのは、以下のような感じです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
そして、
LINE BOT APIを利用してGoogle Calendarの情報を通知する
を直したのは、以下のような感じです。
ちなみにキャンセルされた予定の処理を追加しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
最後に、
LINE BOT APIを利用して雨が降りそうな時は通知するようにしてみる
を直したのは、以下のような感じです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |