https://twitter.com/yurumin_の実装をまとめておく。
コード
#coding: utf-8 Process.daemon(true) if not $DEBUG STDERR.reopen("/home/lastcat/for_yurumin/error.txt") require 'rubygems' require 'user_stream' require 'twitter' require 'pp' require 'highline' require 'mime-types' require 'net/smtp' require 'geocoder_jp' require 'open-uri' require 'RMagick' include Magick consumer_key = 'hogehoge' consumer_secret = 'fufafuga' oauth_token = 'foofoo' oauth_token_secret = 'hoehoe' Twitter.configure do |config| config.consumer_key = consumer_key config.consumer_secret = consumer_secret config.oauth_token = oauth_token config.oauth_token_secret = oauth_token_secret end client = Twitter::Client.new def save_file(url) filename = File.basename(url) open(filename, 'wb') do |file| open(url) do |data| file.write(data.read) end end s = File::stat(filename) File.rename(filename, "/home/lastcat/for_yurumin/sv.png") end #処理 #begin loop do #緯度、経度の整数乱数を生成して、streetviewを取得 latitude = rand(180) - rand(90) lagtitude = rand(360) - rand(180) url = "http://maps.googleapis.com/maps/api/streetview?size=600x300&location=#{latitude},#{lagtitude}&heading=1708&pitch=-0.76&sensor=false" #puts url save_file(url) s = File::stat("/home/lastcat/for_yurumin/sv.png") #null画像ならループ飛ばしてもう一回 今のところサイズで判定 if s.size==4868 then # raise next end #住所取得 #geo = GeocoderJP.get("#{latitude},#{lagtitude}") #address = geo["google_maps"] #画像合成 img1 = ImageList.new("/home/lastcat/for_yurumin/sv.png") img2 = ImageList.new("/home/lastcat/for_yurumin/yurumin.png") img3 = img1.composite(img2, CenterGravity, 50, 50, OverCompositeOp) img3.write("/home/lastcat/for_yurumin/composit.png") if latitude <= 0 then lat = "南緯#{-latitude}" else lat = "北緯#{latitude}" end if lagtitude <= 0 then lag = "西経#{-lagtitude}" else lag = "東経#{lagtitude}" end client.update_with_media("ゆるミンは#{lat},#{lag}地点まできています。", File.open("/home/lastcat/for_yurumin/composit.png")) sleep 1800 end #rescue => notfound # retry # end
仕様(やりたかったこと)
世界を旅して記念写真を撮ってつぶやいてくれるbot
具体的には、
①ランダムに緯度、経度を生成
↓
②ストリートビューで画像を取ってくる
↓
③ゆるミン画像を合成する
↓
④現在座標とともにつぶやく
という感じ。
実現例
ゆるミンは北緯136,東経24地点まできています。 twitter.com/yurumin_/statu…
— 世界を一人で旅するゆるミンさん (@yurumin_) 2013年4月21日
実装解説
①
- 90~90,-180~180の範囲で乱数生成 しかし何かがおかしい。気づいているが直さない。今度直します。
②
Google streetview はクエリが入ったURLを投げれば、(その場所のストリートビュー画像を返してくれる)
例:
http://maps.googleapis.com/maps/api/streetview?size=600x300&location=46.414382,10.013988&heading=151.78&pitch=-0.76&sensor=false
とりあえず座標を生成して画像を取ってくる。エラー画像の弾き方は手抜きなサイズ比較。
URLを指定して帰ってくる画像を保存してくれるメソッドがあるのでそれを使う。
参考URL:http://d.hatena.ne.jp/gan2/20080531/1212227507
使ってる所
def save_file(url) filename = File.basename(url) open(filename, 'wb') do |file| open(url) do |data| file.write(data.read) end end s = File::stat(filename) File.rename(filename, "/home/lastcat/for_yurumin/sv.png") end (url) s = File::stat("/home/lastcat/for_yurumin/sv.png") #null画像ならループ飛ばしてもう一回 今のところサイズで判定 if s.size==4868 then # raise next end
あまり賢いとは言えない。いずれ改善。
③
#画像合成 img1 = ImageList.new("/home/lastcat/for_yurumin/sv.png") img2 = ImageList.new("/home/lastcat/for_yurumin/yurumin.png") img3 = img1.composite(img2, CenterGravity, 50, 50, OverCompositeOp) img3.write("/home/lastcat/for_yurumin/composit.png")
画像合成はrmagickというgemのなんか便利そうな奴を使った。
これをlinuxに入れると多分かなりの確率でエラーが出る。検索候補に出るレベル。
(多分)参考(にした)URL:http://qiita.com/items/6b1c6c7257042a159cc9
こっちは使い方のほう。正直中身は完全にブラックボックスとして使ってて恥ずかしい。
URL:http://d.hatena.ne.jp/SandRiver/20090422/1240358615
かなり画像扱うの便利そうだしいずれはちゃんと理解したい。どっかにドキュメントあるだろ有名そうだし。
④
そのまんま。当初画像付きpostするのにtwipicを使おうとしててAPI全部動かんしなんか他もロクなんないしで腐っててここに多分一番時間使った。
普通に公式(たぶん)のruby用APIにあったというオチ。ググっても出てこないの罠っぽい。
勘を働かせて調べてみるべきだった。
レファレンスがあったというオチ:http://route477.net/w/?RubyTwitterJa
今後の展望
加えたい機能
住所を言わせたい
一応、
#住所取得 #geo = GeocoderJP.get("#{latitude},#{lagtitude}") #address = geo["google_maps"]
参考URL:https://github.com/yukinoraru/geocoder_jp
これである程度は引っ張ってこれる ただ、ストリートビュー存在のフィルターをくぐり抜けてもnotfoundを返す座標が合って二つ通すのめんどくさくてあきらめた。
上手く使えば多分できるのでまたのちのち 最悪jsonパースすればよい(偉そうに言ってるけどぜんぜんできない)。
参考URL:https://developers.google.com/maps/documentation/geocoding/?hl=ja
mapsで軌跡を追いたい。
ゆるミン管理用のサイトを作ってそこにいままでいった所とかでピン立てたりするんかな、多分。
前準備が出来たら簡単そうだけどサイト作るの…ウッ
移動を連続的にしたい
今のままではワープなので連続移動にしたい。
ただ、海をどう超えるんだろって感じ。多分たまにワープする感じになると思われる。
アーブダークション
リプに反応してその場所に行くとかやりたい
できるんかな、知らん。
メインの放浪との兼ね合いが不明。けど結構やりたい。
課題
範囲乱数おかしい
できるだけすぐ直します…
googleにリクエスト投げすぎて一日のアクセス限界超えて怒られる
要するに、もうちょいまともな所を選んで行くようにしろ、と言う話。常識的なことを言ってるようでアルゴリズムがあんまり思いつかない(世界範囲を前提にした場合の話ね)。
ブラックボックスすぎ
折を見て大事そうなやつはソース読む(読まない)。
えーぴーあいとじぇむってすごいですね!!!!!!!!!
くらいかなぁ…
まぁ頑張ります。
追記 Gemfile.lock
GEM remote: http://rubygems.org/ specs: activesupport (3.2.13) i18n (= 0.6.1) multi_json (~> 1.0) faraday (0.8.7) multipart-post (~> 1.1) geocoder_jp (0.0.1) activesupport (~> 3.2.8) hashie (1.2.0) highline (1.6.18) i18n (0.6.1) mime-types (1.23) multi_json (1.7.2) multipart-post (1.2.0) nestful (1.0.1) oauth (0.4.7) rmagick (2.13.2) simple_oauth (0.2.0) twitter (4.6.2) faraday (~> 0.8, < 0.10) multi_json (~> 1.0) simple_oauth (~> 0.2) userstream (1.3.0) hashie (~> 1.2.0) oauth (~> 0.4.7) yajl-ruby (~> 1.1.0) yajl-ruby (1.1.0) PLATFORMS ruby DEPENDENCIES geocoder_jp highline i18n mime-types nestful oauth rmagick twitter userstream _json (~> 1.0) simple_oauth (~> 0.2) userstream (1.3.0) hashie (~> 1.2.0) oauth (~> 0.4.7) yajl-ruby (~> 1.1.0) yajl-ruby (1.1.0)
ゆるミン元画像。