twitter,protectedなfavを消すrubyスクリプト

2008-03-10 - えったん。BESTを尽くせ! - はてなグループ::ついったー部
要約すると、APIから他人のfavs取得するとprotectedなpostの内容も見えちゃう。


ばばばば、爆発しろ!!!
物凄く動揺しながらfav消すスクリプト書いた。問題が発覚してから一週間経ってるからまあ手遅れなんだが。


protectedなユーザのfavを消す。つかいかた:irbでロードして$tw_id,$tw_pwdを設定後、remove_favs 1,10,10とかやる。
パラメタは開始ページ、一度に処理するページ数、繰り返し回数。
削除したpostのuriはカレントディレクトリのremoved_favsにバックアップ。
最初はxmlで取得するAPI使ってたがそのうちAPI制限に引っかかる、rssに変更したがそのうち406(406?なぜ?)が返る、仕方ないのでスクレイピング
一応ウェイトは入れてる。

ソース先頭と末尾の{pull}{/pull}は削除してね。

[2008-03-17 09:15] ちびちび消せるようにした、open-uriやめてnet/httpにした(これで接続を使いまわせてるんだろうか?)
[2008-03-17 07:37] ちゃんと動くようにした

{pull:file path=~/src/removefav.rb last_sync=2008.03.17,09:14}
require 'open-uri'
require 'rubygems'
require 'hpricot'
require 'net/http'
Net::HTTP.version_1_2

$tw_id='your_name'
$tw_pwd='hogehoge'

def get_favs_in_page(http,page)
	begin
		h=Hpricot http.get("/#{$tw_id}/favorites?page="+page.to_s).body
	rescue
		sleep 1
		puts '(retry get_favs_in_page)'
		retry
	end
	return (h/'.hentry').map {|a|
		locked=!((a/'.entry-meta img[@alt=Icon_red_lock]').empty?)
		(a/'.entry-meta .entry-date')[0]['href'].match(/http:\/\/twitter.com\/(.*)\/statuses\/(\d+)/)
		{:user_name=>$1,:post_id=>$2,:locked=>locked}
	}
end

def remove_favs_in_pages(start_page,count)
	targets=[]
	Net::HTTP.start('twitter.com',80) {|http|
		for page in (start_page...start_page+count)
			sleep 1
			puts " ===== in page #{page} ====="
			x=get_favs_in_page http,page
			x.each{|fav|
				p [fav[:locked]?'x':' ',fav[:user_name],fav[:post_id]]
				targets.push fav if fav[:locked]
			}
		end
	}
	puts "targets total #{targets.length}"
	log=open('removed_favs','a')
	Net::HTTP.start('twitter.com',80) {|http|
		targets.each_with_index{|tgt,i|
			sleep 0.5
			target_uri= "twitter.com/#{tgt[:user_name]}/statuses/#{tgt[:post_id]}"
			p "[#{i+1}/#{targets.length}] #{target_uri}"
			req_get=Net::HTTP::Get.new('/favourings/destroy/'+tgt[:post_id].to_s)
			req_get.basic_auth $tw_id,$tw_pwd
			begin
				resp=http.request(req_get)
				resp.body
			rescue
				sleep 0.5
				p '(retry remove post)'
				retry
			end
			log.write target_uri
			log.write("\n")
		}
		log.close
	}
	return targets.length
end

def remove_favs(start_page,block_size,repeat_count)
	repeat_count.times {|i|
		puts " ***** iteration #{i+1} ***** "
		removed=remove_favs_in_pages(start_page,block_size)
		start_page=start_page+block_size-(removed/20)-(removed%20==0?0:1)
	}
end
{/pull}

動揺のあまり消しまくったものの、時既に遅しという気がしなくもない…… protectedでも気を緩めず、twitterとは発言が公開されるものだという認識を持って使うことが大事。