0

HubotでYoのwebhookを受信する

Yoは最近はダッシュボードからbotアカウントを作れるようになっていて、俺もいくつか作って使っている。

botがYoを受信するとあらかじめ指定しておいたコールバックURLにHTTP-GETでwebhookしてくれる。

https://自分のhubot.herokuapp.com/yo/webhook?token=kazudon とか指定しておくといい。GETのパラメータでusername, user_ip, tokenが来る。


Hubotで受信するとしたらこんな感じ。Hubotにはexpressが内蔵されていてrobot.routerで使える。
環境変数YO_WEBHOOK_TOKENを設定する必要がある。

本当にYoのサーバーからのリクエストかを確かめるのにコールバックURLにtokenを含めるのと、HTTPSを使う。
誰でもYoからプログラム実行できても困るので、許可するYoユーザーをあらかじめ持っておく。

# Description:
# YoのWebhookを受信して何かする
#
# Author:
# @shokai

module.exports = (robot) ->

unless process.env.YO_WEBHOOK_TOKEN
robot.logger.error 'ENV var "YO_WEBHOOK_TOKEN" is missing'
return

yo_users = ['SHOKAI', 'user1', 'user2'] # Yo許可するユーザー

robot.router.get '/yo/webhook', (req, res) ->
ip = req.query.user_ip

unless who = req.query.username
return res.status(400).end 'invalid request'
if yo_users.indexOf(who) < 0
res.status(400).end "bad user: #{who}"
robot.send {room: "#general"}, "不正なユーザー #{who}(#{ip})がYoしてきました"
return
if req.query.token isnt process.env.YO_WEBHOOK_TOKEN
res.status(400).end "bad token"
robot.send {room: "#general"}, "#{who}(#{ip})が不正なtoken#{req.query.token}でYoしてきました"
return

res.end 'ok'
robot.send {room: "#general"}, "#{who}(#{ip})がYoしてきました"
## 〜〜ここで何か処理〜〜 ##

0

Jawbone Up24のpubsub APIを受信する

Jawbone Up24を買った。Apple Storeで売ってた。
前のUpと比べてbluetoothで同期できるので楽というのもあるが、webhookによるサーバープッシュAPIの方が気になってて買った。

UP for Developers: Pub Sub


通知

oauthで認証してもらったユーザーが寝たり・起きたり・活動したりすると、約10秒後に自作のwebアプリにjsonでwebhookが通知される。
jawbone up—(bluetooth)—>スマホ—(HTTP)—>jawboneのサーバー—(HTTP webhook)—>自作webアプリ
と通知がリレーされていくわけです。

最近色々とまともなAPIのあるガジェットは増えてるけど、出力側ばっかりで、入力というかトリガー側(センサー)になるやつはあまり無い。


ソースコード

前に作ったJawbone UpのAPIで睡眠時間などを取得するを少し改造した。

https://github.com/shokai/jawbone-up-api-study


設定

アプリケーションの設定にpubsubのURLを書くだけで通知が来るようになる。


プログラム

post ‘/pubsub’を追加した。あとAPIのscopeを色々追加した。move_readが無いと運動した時に空の通知が来てしまっていたので。

https://github.com/shokai/jawbone-up-api-study/tree/master/auth
def app_root
"#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
end

def oauth_client
@client ||= OAuth2::Client.new(CLIENT_ID, APP_SECRET,
:site => 'https://jawbone.com',
:authorize_url => '/auth/oauth2/auth',
:token_url => '/auth/oauth2/token')
end

get '/' do
unless session[:oauth_token]
@mes = %Q{<p><a href="/login">login</a></p>}
else
@mes = %Q{<p><a href="/logout">logout</a></p>
<p>your token : #{session[:oauth_token]}</p>}
end
end

get '/login' do
scope = "basic_read extended_read mood_read move_read sleep_read generic_event_read"
redirect oauth_client.auth_code.authorize_url(:scope => scope,
:redirect_uri => "#{app_root}/auth")
end

get '/auth' do
code = params["code"]
halt 400, 'code missing' unless code
begin
session[:oauth_token] = oauth_client.auth_code.get_token(code).token
puts "TOKEN : "+session[:oauth_token]
rescue => e
STDERR.puts e.message
end
redirect "/"
end

get '/logout' do
session.delete :oauth_token
redirect "/"
end

post '/pubsub' do
request.body.rewind
puts request.body.read
"ok"
end


こういうのがpushされてくる
{"events": [{"action": "enter_sleep_mode", "timestamp": 1396797071, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA"}], "notification_timestamp": 1396797074}
{"events": [{"action": "exit_sleep_mode", "timestamp": 1396797115, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA"}], "notification_timestamp": 1396797117}
{"events": [{"action": "creation", "timestamp": 1396797240, "user_xid": "gvT5W2FhlrHsB3r9Wq_unA", "type": "move", "event_xid": "mD99tHyRBx4xNT7HoSCUmA"}], "notification_timestamp": 1396798341}