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"