Twitterでつぶやく
Twitterのアクセストークンを作成する
まずTwitterのサイトで下準備をします。
https://dev.twitter.com/apps からTwitterアカウントでサインインし、「Create a new application」ボタンをクリックして新しいアプリケーションを作成します。
アプリケーションを作成したらSettingsタブを開き、Application TypeのAccess項目で「Read and Write」を選択し、ページ下部の「Update this Twitter application's settings」ボタンをクリックします。
Detailsタブを開き、ページ下部の「Create my access token」ボタンをクリックするとAccess tokenが表示されます。
Access tokenが表示されない場合はページをリロードしてみてください。ページに表示されているConsumer key、Consumer secret、Access token、Access token secretの4つの情報を下のプログラムで使います。
プログラムの作成
ntwitterモジュールをインストールします。
$ npm install ntwitter
以下のプログラムでつぶやきを送信できます。CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRETはそれぞれ先ほど取得した値に置き換えてください。
twitter = require "ntwitter"
twit = new twitter
consumer_key : "CONSUMER_KEY"
consumer_secret : "CONSUMER_SECRET"
access_token_key : "ACCESS_TOKEN"
access_token_secret: "ACCESS_TOKEN_SECRET"
# つぶやく
twit.updateStatus "CoffeeScriptからこんにちは!", (err, data) ->
if err
console.log "error: #{err.message}"
else
console.log "updated"
重複する内容のつぶやきを連続で送信しようとすると「Status is a duplicate」というエラーが返ってきます。その場合は、内容を変更してつぶやいてみてください。
簡単なTwitter botを作る
「今何時?」というつぶやきに対して時刻を返信するTwitter botを作ってみます。「今何時」以外のつぶやきが来た場合は返信しません。
twitter = require "ntwitter"
twit = new twitter
consumer_key : "CONSUMER_KEY"
consumer_secret : "CONSUMER_SECRET"
access_token_key : "ACCESS_TOKEN"
access_token_secret: "ACCESS_TOKEN_SECRET"
# 自分のTwitter IDを取得する
twit.verifyCredentials (err, data) ->
if err then throw err
user_id_str = data.id_str
# userストリームに接続する
twit.stream "user", (stream) ->
console.log "ready"
stream.on "data", (data) -> # 新しいデータが来た
if data.in_reply_to_user_id_str is user_id_str # @付きのつぶやきが来た
console.log "new mention from @#{data.user.screen_name}: #{data.text}"
# 本文から@usernameを取り除く
text = data.text.replace /^@\w+\S+/, ""
reply = null
if /今何時/.test text
d = new Date
reply = "#{d.getHours()}時#{d.getMinutes()}分だよ"
if reply?
reply = "@#{data.user.screen_name} #{reply}"
console.log "update: #{reply}"
# つぶやく
twit.updateStatus reply, {
in_reply_to_status_id: data.id_str
}, (err, data) ->
if err
console.log "update error: #{err}"
else
console.log "update success"
天気予報を取得する
まずrequestモジュールをインストールします。
$ npm install request
Livedoorお天気Webサービスを使って、簡単に天気予報を取得できます。
request = require "request"
# cityId一覧: http://weather.livedoor.com/forecast/rss/primary_area.xml
cityId = "130010" # 東京
apiUrl = "http://weather.livedoor.com/forecast/webservice/json/v1?city=#{cityId}"
# URLにアクセスしてデータを取得する
request apiUrl, (err, response, body) ->
if err # プログラムエラー
throw err
if response.statusCode is 200 # 取得成功
# JSONとして解釈する
try
json = JSON.parse body
catch e
console.log "JSON parse error: #{e}"
# 直近の予報データを取得
forecast = json.forecasts[json.forecasts.length-2]
# 文を作る
weather = "#{json.location.city}の#{forecast.dateLabel}の天気は#{forecast.telop}"
if forecast.temperature.max? # 気温情報がある場合
weather += "、最高気温は#{forecast.temperature.max.celsius}度、" + \
"最低気温は#{forecast.temperature.min.celsius}度"
weather += "です。"
console.log weather
else # APIレスポンスエラー
console.log "Response error: #{response.statusCode}"
【実行結果】
東京の明日の天気は晴のち曇、最高気温は35度、最低気温は26度です。
各地の天気予報を返信するTwitter botを作る
上記の手法を組み合わせると、「東京の天気」や「札幌の天気」というつぶやきに反応して各地の直近の天気予報を返信してくれるTwitter botを作ることができます。
twitter = require "ntwitter"
request = require "request"
twit = new twitter
consumer_key : "CONSUMER_KEY"
consumer_secret : "CONSUMER_SECRET"
access_token_key : "ACCESS_TOKEN"
access_token_secret: "ACCESS_TOKEN_SECRET"
# cityId一覧
cityIds =
"稚内": "011000"
"旭川": "012010"
"留萌": "012020"
"網走": "013010"
"北見": "013020"
"紋別": "013030"
"根室": "014010"
"釧路": "014020"
"帯広": "014030"
"室蘭": "015010"
"浦河": "015020"
"札幌": "016010"
"岩見沢": "016020"
"倶知安": "016030"
"函館": "017010"
"江差": "017020"
"青森": "020010"
"むつ": "020020"
"八戸": "020030"
"盛岡": "030010"
"宮古": "030020"
"大船渡": "030030"
"仙台": "040010"
"白石": "040020"
"秋田": "050010"
"横手": "050020"
"山形": "060010"
"米沢": "060020"
"酒田": "060030"
"新庄": "060040"
"福島": "070010"
"小名浜": "070020"
"若松": "070030"
"水戸": "080010"
"土浦": "080020"
"宇都宮": "090010"
"大田原": "090020"
"前橋": "100010"
"みなかみ": "100020"
"さいたま": "110010"
"熊谷": "110020"
"秩父": "110030"
"千葉": "120010"
"銚子": "120020"
"館山": "120030"
"東京": "130010"
"大島": "130020"
"八丈島": "130030"
"父島": "130040"
"横浜": "140010"
"小田原": "140020"
"新潟": "150010"
"長岡": "150020"
"高田": "150030"
"相川": "150040"
"富山": "160010"
"伏木": "160020"
"金沢": "170010"
"輪島": "170020"
"福井": "180010"
"敦賀": "180020"
"甲府": "190010"
"河口湖": "190020"
"長野": "200010"
"松本": "200020"
"飯田": "200030"
"岐阜": "210010"
"高山": "210020"
"静岡": "220010"
"網代": "220020"
"三島": "220030"
"浜松": "220040"
"名古屋": "230010"
"豊橋": "230020"
"津": "240010"
"尾鷲": "240020"
"大津": "250010"
"彦根": "250020"
"京都": "260010"
"舞鶴": "260020"
"大阪": "270000"
"神戸": "280010"
"豊岡": "280020"
"奈良": "290010"
"風屋": "290020"
"和歌山": "300010"
"潮岬": "300020"
"鳥取": "310010"
"米子": "310020"
"松江": "320010"
"浜田": "320020"
"西郷": "320030"
"岡山": "330010"
"津山": "330020"
"広島": "340010"
"庄原": "340020"
"下関": "350010"
"山口": "350020"
"柳井": "350030"
"萩": "350040"
"徳島": "360010"
"日和佐": "360020"
"高松": "370000"
"松山": "380010"
"新居浜": "380020"
"宇和島": "380030"
"高知": "390010"
"室戸岬": "390020"
"清水": "390030"
"福岡": "400010"
"八幡": "400020"
"飯塚": "400030"
"久留米": "400040"
"佐賀": "410010"
"伊万里": "410020"
"長崎": "420010"
"佐世保": "420020"
"厳原": "420030"
"福江": "420040"
"熊本": "430010"
"阿蘇乙姫": "430020"
"牛深": "430030"
"人吉": "430040"
"大分": "440010"
"中津": "440020"
"日田": "440030"
"佐伯": "440040"
"宮崎": "450010"
"延岡": "450020"
"都城": "450030"
"高千穂": "450040"
"鹿児島": "460010"
"鹿屋": "460020"
"種子島": "460030"
"名瀬": "460040"
"那覇": "471010"
"名護": "471020"
"久米島": "471030"
"南大東": "472000"
"宮古島": "473000"
"石垣島": "474010"
"与那国島": "474020"
# cityIdに対応する天気予報を取得する
getWeatherByCity = (cityId, callback) ->
apiUrl = "http://weather.livedoor.com/forecast/webservice/json/v1?city=#{cityId}"
request apiUrl, (err, response, body) ->
if err
callback err
return
if response.statusCode is 200
try
json = JSON.parse body
catch e
callback new Error "JSON parse error"
return
forecast = json.forecasts[json.forecasts.length-2] # 直近の予報データ
weather = "#{json.location.city}の#{forecast.dateLabel}の天気は#{forecast.telop}"
if forecast.temperature.max? # 気温情報がある場合
weather += "、最高気温は#{forecast.temperature.max.celsius}度、" + \
"最低気温は#{forecast.temperature.min.celsius}度"
weather += "です。"
callback null, weather
else
callback new Error "Response error: #{response.statusCode}"
# textに対する返信文を作成する
getReply = (text, callback) ->
if (match = /(\S+)の天気/.exec text)?
city = match[1]
if cityIds[city]?
getWeatherByCity cityIds[city], callback
else
callback null, "#{city}の天気はわかりません…。"
else
callback null, null
twit.verifyCredentials (err, data) ->
if err then throw err
user_id_str = data.id_str
twit.stream "user", (stream) ->
console.log "ready"
stream.on "data", (data) ->
if data.in_reply_to_user_id_str is user_id_str
console.log "new mention from @#{data.user.screen_name}: #{data.text}"
text = data.text.replace /^@\w+\S+/, ""
# 返信文を作成
getReply text, do (data) -> (err, reply) ->
if err
console.log "getReply error: #{err}"
return
if reply?
reply = "@#{data.user.screen_name} #{reply}"
console.log "update: #{reply}"
# つぶやく
twit.updateStatus reply, {
in_reply_to_status_id: data.id_str
}, (err, resp) ->
if err
console.log "update error: #{err}"
else
console.log "update success"