札幌Ruby会議02で発表しました。
ビデオを見返すと、かなり時間オーバーしてるんですね。反省します。
Mac OS Xでrvm
Mac OS XにふつうにRubyをインストールするときと同じで、readlineについて指定する必要がある感じです。twitterでぼやいていたら、kakutaniさんが教えてくれました!
rvm だと irb で日本語入力できてない…… #rvm
http://twitter.com/noplans/status/3597014333
@noplans -c でconfigureのオプションわたせそうな雰囲気でした
http://twitter.com/kakutani/status/3597037089
というわけで、
% rvm use ruby -v 1.9.1 -c --with-readline-dir=/opt/local
とかやって使えるようになりました。これでtermtterも大丈夫です。
TwitterのBot
gistから貼るのってどうやるのかわからないのでテストを兼ねて投稿します。便利なBOT - TwitterまとめWikiからボットを抜き出しているだけですー。
なんか見づらいなー。普通に貼った方が良いかもしれん。……配色のせいだった。配色を変えたら見やすくなった。
# twitter bots list require 'nokogiri' require 'open-uri' BASE = 'http://usy.jp/twitter/index.php?%E4%BE%BF%E5%88%A9%E3%81%AABOT' doc = Nokogiri::HTML(open(BASE)) list = doc.xpath('//a[@rel="nofollow"]') .map{|x| x['href']} .select{|link| %r|\Ahttps?://twitter\.com/| =~ link} bots = list.map{|link| link.gsub(%r|\Ahttps?://twitter\.com/(\w+)?/?\z|, '\1')}.sort
RubyKaigi2009行ってきた
日本Ruby会議2009(RubyKaigi2009)にスタッフ(KaigiFreaks)として参加しました。配信および録画が主な仕事です。そのため、担当の部屋以外の発表はまったく見ることができなかったのですが、IRCとtwitterでRubyKaigi2009への意見/不満をできるかぎりすくい取ろうとしてずっとモニタリングしていたため、会議の雰囲気は伝わってきた感じでした。Buzztter rocks!
札幌に戻ってきてから角谷さんの "Take the Red Pill" を観たのですが、これを生で観てたら後は仕事にならんかっただろうなー、と思います。それくらい私にとってはストライクな内容でした。
まだKaigiFreaksとしての仕事は終わってないので、これくらいで。
i_ogi さんと wakuteka さんと組んで仕事をしたのですが、みなさん素晴らしすぎて楽させていただきました。ほんとに i_ogi さんは god でした!
アップルストア札幌で話してきました
(広い意味での)環境ということについて話してきました。概要編です。時間配分を失敗しました。精進します。
日本PostgreSQLユーザ会北海道支部 / Ruby札幌合同セミナーで発表しました
しょぼい発表ですみませんでした。あとでコードも置いときます。
(追記2: ニコニコ動画の動画も貼りました(3/7))
(追記: コード置きました(3/1))
発表のときに見せてたコード
スライドの「実際作る」以降で使用したコードです。
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