Skip to content

Instantly share code, notes, and snippets.

@dnpp73
Created April 7, 2011 05:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dnpp73/907105 to your computer and use it in GitHub Desktop.
Save dnpp73/907105 to your computer and use it in GitHub Desktop.
指定したscreen_nameのfollowingの色んな変更をチェックする感じ。
=begin
必要なもの
$ gem install rubytter
../oauth_yaml/#{Client}-#{App}.yaml ( TwitterOAuthの情報を格納したもの )
これはなに
指定したscreen_nameのfollowingの色んな変更をチェックする感じ。
つかいかた
$ crontab -e
で、こんな感じの追記をして
0 0 * * * /path/to/ruby /path/to/following-check.rb
後は適当な画面で
$ tail -f /path/to/log/#{Target}-following_activity.txt
$ tail -f /path/to/log/#{Target}-screen_name-log.txt
=end
require 'rubygems'
require 'rubytter'
require 'yaml'
require 'date'
require 'fileutils'
#設定用の定数など
DEBUG = false
Client = 'DNPP'
App = 'Ofuton'
Target = 'DNPP'
CDIR = File.dirname(File.expand_path(__FILE__))
OAuth_YAML = CDIR+'/../oauth_yaml/'+Client+'-'+App+'.yaml'
if DEBUG
Log = true
ELog = true
SleepWait = 0
Log_DIR = CDIR+'/'+'log-dev'
Data_DIR = CDIR+'/'+'data-dev'
RetryWait = 0
puts "---> DEBUG mode"
puts "---> Log = #{Log}"
puts "---> ELog = #{ELog}"
puts "---> SleepWait = #{SleepWait}"
puts "---> Log_DIR = #{Log_DIR}"
puts "---> Data_DIR = #{Data_DIR}"
puts "---> RetryWait = #{RetryWait}"
puts ""
else
Log = false
ELog = true
SleepWait = 5
Log_DIR = CDIR+'/'+'log'
Data_DIR = CDIR+'/'+'data'
RetryWait = 15
end
#YAMLへ保存しやすいように
def yaml_dump(contents,path)
open(path,'w') { |i| i << YAML.dump(contents) }
end
#ログ保存しやすいように
def log_dump(contents,path)
open(path,'a') { |i| i.puts contents }
end
#処理をまとめたclass
class FollowingActivityCheck
def initialize(screen_name)
#重要っぽい変数など
@screen_name = screen_name
@user = Hash.new
@following = Hash.new
@following_yaml = Data_DIR+'/'+@screen_name+'-'+'following_with_info.yaml'
@following_b = Hash.new
@following_b_yaml = Data_DIR+'/'+@screen_name+'-'+'following_with_info_before.yaml'
@following_bb = Hash.new
@screen_name_log_txt = Log_DIR+'/'+@screen_name+'-'+'screen_name-log.txt'
@other_log_txt = Log_DIR+'/'+@screen_name+'-'+'following_activity.txt'
@now = DateTime.now.strftime("%Y-%m-%d %a %H:%M")
@changes = false
#OAuth周りの認証処理
begin
oauth = YAML.load_file(OAuth_YAML)
rescue
puts "---! Can't open #{OAuth_YAML}"
exit
end
consumer = OAuth::Consumer.new(oauth['consumer_key'], oauth['consumer_secret'], :site => 'https://api.twitter.com')
token = OAuth::AccessToken.new(consumer, oauth['oauth_token'], oauth['oauth_token_secret'])
@t = OAuthRubytter.new(token)
#screen_nameから諸情報を取得
begin
puts "---> fetching @#{@screen_name} user info" if Log
@user = @t.user(@screen_name)
rescue
puts "---! Error in @t.user(\"#{@screen_name}\") retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
@user = @t.user(@screen_name)
rescue
puts "---! Error in @t.user(\"#{@screen_name}\")" if ELog
exit
end
end
end
#followingの取得
def get_following
puts "---> fetching @#{@screen_name}'s following" if Log
next_cursor = -1 ; friends_raw = Array.new
while next_cursor != 0
begin
puts "---> fetching @#{@screen_name}'s following cursor #{next_cursor}" if Log
tmp = @t.friends(@user[:id],:cursor=>next_cursor)
rescue
puts "---! Error in @t.friends(#{@user[:id]},:cursor=>#{next_cursor}) ( #{@user[:id]} = #{@screen_name} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
tmp = @t.friends(@user[:id],:cursor=>next_cursor)
rescue
puts "---! Error in @t.friends(#{@user[:id]},:cursor=>#{next_cursor}) ( #{@user[:id]} = #{@screen_name} )" if ELog
exit
end
end
friends_raw.concat([tmp])
next_cursor = tmp[:next_cursor]
sleep SleepWait
end
friends_raw.collect{|i| i[:users] }.flatten!.each {|j| @following[j[:id]] = j }
#前々回取得分があればロードする
if File.exist?(@following_b_yaml)
puts "---> load following_b_yaml into following_bb" if Log
@following_bb = YAML.load_file(@following_b_yaml)
end
#前回取得した分があればロードする
if File.exist?(@following_yaml)
puts "---> load following_yaml into following_b" if Log
@following_b = YAML.load_file(@following_yaml)
end
#Twitterが邪悪な結果を返してないかどうかを見る
def for_check(t_user)
id = t_user[:id]
screen_name = t_user[:screen_name]
name = t_user[:name].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' '),
description = t_user[:description].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' '),
location = t_user[:location].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' '),
ary = [id,screen_name,name,description,location]
return ary
end
u = Array.new
@following.each do |id,user|
if ( @following_b[id] && @following_bb[id] && for_check(user) == for_check(@following_bb[id]) && for_check(user) != for_check(@following_b[id]) )
puts "---> #{user[:screen_name]} の取得結果がおかしい可能性があるんで再取得するよ。" if ELog
begin
u << @t.user(id)
rescue
puts "---! Error in @t.user(#{id}) ( #{id} = #{user[:screen_name]} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
u << @t.user(id)
rescue
puts "---! Error in @t.user(#{id}) ( #{id} = #{user[:screen_name]} )" if ELog
next
end
end
sleep SleepWait
end
end
u.each {|k| @following[k[:id]] = k }
#今回取得した分のdumpと、前回取得分の退避
if File.exist?(@following_yaml)
puts "---> cp following_yaml following_b_yaml" if Log
FileUtils.cp(@following_yaml,@following_b_yaml)
end
puts "---> dump following into following_yaml" if Log
yaml_dump(@following,@following_yaml)
end
#アウトプットしやすいように
def output(contents_raw="",path=@other_log_txt,cron_mail=false)
contents = contents_raw.gsub(/\n+/,' \n ')
puts "---> #{contents}" if Log
puts contents if cron_mail
log_dump(@now+' '+contents,path)
@changes = true
end
#diffを取る
def take_diff
#前回取得した分が無いなら、とりあえず今回取得した分を代入する
if @following_b.empty?
puts "---> substitute following for following_b" if Log
@following_b = @following
end
#まず増減の確認
increase = Array.new ; decrease = Array.new
@following.each_key {|id| increase << id if !@following_b.has_key?(id) }
@following_b.each_key {|id| decrease << id if !@following.has_key?(id) }
increase.each do |id|
screen_name = @following[id][:screen_name]
contents = "< following + > @#{screen_name} http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
decrease.each do |id|
screen_name_before = @following_b[id][:screen_name]
begin
screen_name = @t.user(id)[:screen_name]
rescue
puts "---! Error in @t.user(#{id})[:screen_name] ( #{id} = #{screen_name_before} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
screen_name = @t.user(id)[:screen_name]
rescue
contents = "< Account deleted ? > @#{screen_name_before} is gone..."
self.output(contents,@screen_name_log_txt,true)
next
end
end
contents = "< following - > @#{screen_name} http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#各種情報のdiffを取ってoutput
@following.each do |id,user|
next if !@following_b[id]
#screen_name
screen_name = user[:screen_name].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
screen_name_before = @following_b[id][:screen_name].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
if ( screen_name_before && screen_name != screen_name_before )
contents = "< screen_name change > @#{screen_name_before} -> @#{screen_name} http://twitter.com/#{screen_name}"
self.output(contents,@screen_name_log_txt,true)
end
#name
name = user[:name].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
name_before = @following_b[id][:name].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
if ( name_before && name != name_before )
contents = "< @#{screen_name} name > \"#{name_before}\" -> \"#{name}\" http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#description
description = user[:description].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
description_before = @following_b[id][:description].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
if ( description_before && description != description_before )
contents = "< @#{screen_name} bio > \"#{description_before}\" -> \"#{description}\" http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#location
location = user[:location].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
location_before = @following_b[id][:location].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
if ( location_before && location != location_before )
contents = "< @#{screen_name} location > \"#{location_before}\" -> \"#{location}\" http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#url
url = user[:url].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
url_before = @following_b[id][:url].to_s.gsub(/\n+/,"\n").gsub(/\s+/,' ')
if ( url_before && url != url_before )
contents = "< @#{screen_name} url > #{url_before} -> #{url} http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#protected
protected = user[:protected]
protected_before = @following_b[id][:protected]
if ( protected_before && protected != protected_before )
contents = "< @#{screen_name} protected > #{protected_before} -> #{protected} http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#profile_image_url
profile_image_url = user[:profile_image_url]
profile_image_url_before = @following_b[id][:profile_image_url]
if ( profile_image_url_before && profile_image_url != profile_image_url_before )
contents = "< @#{screen_name} icon > #{profile_image_url_before} -> #{profile_image_url} http://twitter.com/#{screen_name}"
self.output(contents,@other_log_txt,false)
end
#profile_background_image_url
# profile_background_image_url = user[:profile_background_image_url]
# profile_background_image_url_before = @following_b[id][:profile_background_image_url]
# if ( profile_background_image_url_before && profile_background_image_url != profile_background_image_url_before )
# contents = "< @#{screen_name} bgimg > #{profile_background_image_url_before} -> #{profile_background_image_url} http://twitter.com/#{screen_name}"
# self.output(contents,@other_log_txt,false)
# end
end
end
#処理まとめ
def main
Dir.mkdir(Log_DIR) if !File.exist?(Log_DIR)
Dir.mkdir(Data_DIR) if !File.exist?(Data_DIR)
log_dump('',@screen_name_log_txt) if !File.exists?(@screen_name_log_txt)
log_dump('',@other_log_txt) if !File.exists?(@other_log_txt)
self.get_following
self.take_diff
puts "---> no changes detect on @#{@screen_name}'s following screen_names" if ( !@changes && Log )
end
end
#実行
puts "---> --- @#{Target} ---" if Log
FollowingActivityCheck.new(Target).main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment