日本PostgreSQLユーザ会北海道支部 / Ruby札幌合同セミナーで発表しました
しょぼい発表ですみませんでした。あとでコードも置いときます。
(追記2: ニコニコ動画の動画も貼りました(3/7))
(追記: コード置きました(3/1))
「日本PostgreSQLユーザ会北海道支部 / Ruby札幌 合同セミナー 2008-02-16」 dara さんの公開マイリスト - ニコニコ動画 に動画も上がる予定です。
発表のときに見せてたコード
スライドの「実際作る」以降で使用したコードです。
tumblr
一応、その前で説明してた
- ActiveRecord
- Pit
- WWW::Mechanize
- Hpricot
を使用するコードになってます。
- 私をフォローしてくれてる人たち(followers)の中に、
- 私がフォローしていない人たちがいるので、それをフォローする
プログラムを書きました。
User モデルのテーブルはこんな感じ。名前と URL、follow してるかどうかのフィールドがあります。
class Migration < ActiveRecord::Migration def self.up create_table :users do |t| t.column :name, :string t.column :url, :string t.column :following, :boolean end end def self.down drop_table :users end end
User モデルは下のような感じです。
class User < ActiveRecord::Base validates_uniqueness_of :name def self.find_by_name_or_create(name) self.find_by_name(name) || self.create(:name => name) unless name.empty? end def before_save self.following ||= :false end end
tumblr クラスを作りました。当日の発表では説明してません。#follow あたりはかなり決め打ちです。
class Tumblr class LoginError < Exception; end class Following < Array def initialize(array=[]) self.replace array end end @@base_url = "http://www.tumblr.com" def initialize(user, pass) @ua = WWW::Mechanize.new env = ENV['http_proxy'] || ENV['HTTP_PROXY'] if env http_proxy = URI(env) @ua.set_proxy http_proxy.host, http_proxy.port end login(user, pass) end def set_proxy(host, port) @ua.set_proxy host, port end def dashboard(num=0) @ua.get("#{@@base_url}/dashboard/#{num}") end def following url = "#{@@base_url}/following" doc = Hpricot(@ua.get(url).body) t = Tumblr::Following.new(pickup(doc)).each do |user| user.following = :true user.save end t end def followers url = "#{@@base_url}/followers" doc = Hpricot(@ua.get(url).body) t = Tumblr::Following.new(pickup(doc)) end def follow(user=nil) if user name = user.name url = user.url page = @ua.get(url) f = page.iframes.first link = f.src page = @ua.get(link) f = page.forms.first @ua.submit(f) puts "Now you follow #{name}: #{url}." user.following = :true user.save end end def login(user, pass) page = @ua.get("#{@@base_url}/login") f = page.forms.first f.email, f.password = user, pass result = @ua.submit f raise Tumblr::LoginError, "wrong username or password" if result.forms.size > 0 end private def pickup(doc) a = [] (doc/"#following"/"div.username"/"a").each do |element| user = User.find_by_name_or_create(element.inner_html) user.url = element.get_attribute("href") user.save a << user end a end end
実際に動かすコードです。
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => 'db/development.sqlite3', :timeout => 5000 ) user_account = Pit.get("tumblr.com", :require => { :login => 'E-mail address', :password => 'Password'}) t = Tumblr.new(user_account[:login], user_account[:password]) following = t.following followers = t.followers followers.each do |follower| unless following.include? follower puts "#{follower.name} (#{follower.url}) さんをまだフォローしてません。" puts "フォローしますか? (y/n)" line = gets if /\AY|y\Z/ =~ line.chomp t.follow follower end end end
twitter の方は twitter4R 使いました、というだけのコードです。あとはこれを RubyCocoa から使う感じです。
class Client def initialize @twitter = Twitter::Client.new(Pit.get("twitter.com")) @last_updated = 10.minutes.ago.utc end def message(text='') puts "posted: #{text}" unless text.empty? @twitter.status(:post, text) unless text.empty? end def timeline_diff diff = nil begin diff = @twitter.timeline_for(:friends, :since => @last_updated) @last_updated = Time.now.utc rescue Twitter::RESTError => re case re.code when '304' puts re.to_s end @last_updated = Time.now.utc rescue Timeout::Error => re pp re end diff || [] end end