Skip to content

Instantly share code, notes, and snippets.

@dnpp73
Created February 10, 2011 19:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dnpp73/821189 to your computer and use it in GitHub Desktop.
Save dnpp73/821189 to your computer and use it in GitHub Desktop.
followingとかfollowersとかlistedの上下を監視する感じ。
#!/usr/bin/env ruby
=begin
必要なもの
$ gem install rubytter
./target.yaml ( screen_nameの配列の形になってるもの )
../oauth_yaml/#{Client}-#{App}.yaml ( TwitterOAuthの情報を格納したもの )
これはなに
指定したscreen_nameの人の、following・followers・listedの上下をチェックする感じ。
りむったー的に使えるかなと思って書いてたんだけど、どうせならfollowingとlistedも付けて、自分以外の人のも見られるようにしようとしたら、こんなんが出来ました。
listの削除とかにも対応してるのでちゃんと見られると思います。
垢削除されるとどうしようもないけど、とりあえずidだけ表示出来ると思います。
つかいかた
$ crontab -e
で、こんな感じの追記をして
0 * * * * /path/to/ruby /path/to/activity-check.rb
後は適当な画面で
$ tail -f /path/to/log/*-log.txt
=end
require 'rubygems'
require 'rubytter'
require 'yaml'
require 'date'
require 'fileutils'
#設定用の定数など
DEBUG = false
Client = 'hoge'
App = 'fuga'
CDIR = File.dirname(File.expand_path(__FILE__))
OAuth_YAML = CDIR+'/../oauth_yaml/'+Client+'-'+App+'.yaml'
if DEBUG
Log = true
ELog = true
Sleep = false
SleepWait = 3
Log_DIR = CDIR+'/'+'log-dev'
Data_DIR = CDIR+'/'+'data-dev'
Target_YAML = CDIR+'/'+'target-dev.yaml'
RetryWait = 5
ListedWait = 5
UserWait = 5
puts "---> DEBUG mode"
puts "---> Log = #{Log}"
puts "---> ELog = #{ELog}"
puts "---> Sleep = #{Sleep}"
puts "---> SleepWait = #{SleepWait}"
puts "---> Log_DIR = #{Log_DIR}"
puts "---> Data_DIR = #{Data_DIR}"
puts "---> Target_YAML = #{Target_YAML}"
puts "---> RetryWait = #{RetryWait}"
puts "---> ListedWait = #{ListedWait}"
else
Log = false
ELog = false
Sleep = true
SleepWait = 50
Log_DIR = CDIR+'/'+'log'
Data_DIR = CDIR+'/'+'data'
Target_YAML = CDIR+'/'+'target.yaml'
RetryWait = 20
ListedWait = 10
UserWait = 10
end
#YAMLへ保存しやすいように
def yaml_dump(contents,path)
open(path,'w') { |i| i << YAML.dump(contents) }
#open(path[0,path.length-5]+'-'+DateTime.now.strftime("%Y%m%d%H%M")+'.yaml','w') { |i| i << YAML.dump(contents) }
end
#ログ保存しやすいように
def log_dump(contents,path)
open(path,'a') { |i| i.puts contents }
end
#Twitterからのレスポンスの差の回収のため…
def isids(t)
begin
t = t[:ids] if t.has_key?(:ids)
rescue
t
end
return t
end
#処理をまとめたclass
class ActivityCheck
def initialize(screen_name)
#重要っぽい変数など
@screen_name = screen_name.to_s
@user = Hash.new
@following = Array.new
@followers = Array.new
@listed = Array.new
@user_yaml = Data_DIR+'/'+@screen_name+'-'+'user.yaml'
@following_yaml = Data_DIR+'/'+@screen_name+'-'+'following.yaml'
@followers_yaml = Data_DIR+'/'+@screen_name+'-'+'followers.yaml'
@listed_yaml = Data_DIR+'/'+@screen_name+'-'+'listed.yaml'
@user_before = Hash.new
@following_before = Array.new
@followers_before = Array.new
@listed_before = Array.new
@cancel = false
@following_cancel = false
@followers_cancel = false
@listed_cancel = false
@log_txt = Log_DIR+'/'+@screen_name+'-'+'log.txt'
@now = DateTime.now.strftime("%Y-%m-%d %a %H:%M")
@suffixTime = DateTime.now.strftime("%Y-%m%d-%H%M")
@user_yaml_bak = Data_DIR+'/'+@screen_name+'-'+'user'+'-'+@suffixTime+'.yaml'
@following_yaml_bak = Data_DIR+'/'+@screen_name+'-'+'following'+'-'+@suffixTime+'.yaml'
@followers_yaml_bak = Data_DIR+'/'+@screen_name+'-'+'followers'+'-'+@suffixTime+'.yaml'
@listed_yaml_bak = Data_DIR+'/'+@screen_name+'-'+'listed'+'-'+@suffixTime+'.yaml'
@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
@cancel = true
puts "---! @cancel = true (\"#{@screen_name}\")"
end
puts "---> Successfully in retry @t.user(\"#{@screen_name}\")" if (!@cancel && Log)
end
if !@cancel && File.exist?(@user_yaml)
puts "---> backing up user yaml" if Log
FileUtils.cp(@user_yaml,@user_yaml_bak)
puts "---> load user_yaml into user_before" if Log
@user_before = YAML.load_file(@user_yaml)
puts "---> dump user in yaml" if Log
yaml_dump(@user,@user_yaml)
elsif !@cancel && !File.exist?(@user_yaml)
puts "---> substitute user for user_before" if Log
@user_before = @user
puts "---> dump user in yaml" if Log
yaml_dump(@user,@user_yaml)
end
end
#followingの取得と格納と、失敗した場合のフラグ
def get_following
begin
puts "---> fetching @#{@screen_name}'s following" if Log
@following = @t.friends_ids(@user[:id])
rescue
puts "---! Error in @t.friends_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
@following = @t.friends_ids(@user[:id])
rescue
puts "---! Error in @t.friends_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} )" if ELog
@following_cancel = true
end
puts "---> Successfully in retry @t.friends_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} )" if (!@following_cancel && Log)
end
if !@following_cancel && File.exist?(@following_yaml)
puts "---> backing up following yaml" if Log
FileUtils.cp(@following_yaml,@following_yaml_bak)
puts "---> load following_yaml into following_before" if Log
@following = isids(@following)
@following_before = isids(YAML.load_file(@following_yaml))
puts "---> dump following in yaml" if Log
yaml_dump(@following,@following_yaml)
elsif !@following_cancel && !File.exist?(@following_yaml)
puts "---> substitute following for following_before" if Log
@following = isids(@following)
@following_before = @following
puts "---> dump following in yaml" if Log
yaml_dump(@following,@following_yaml)
end
end
#followersの取得と格納と、失敗した場合のフラグ
def get_followers
begin
puts "---> fetching @#{@screen_name}'s followers" if Log
@followers = @t.followers_ids(@user[:id])
rescue
puts "---! Error in @t.followers_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
begin
@followers = @t.followers_ids(@user[:id])
rescue
puts "---! Error in @t.followers_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} )" if ELog
@followers_cancel = true
end
puts "---> Successfully in retry @t.followers_ids(#{@user[:id]}) ( #{@user[:id]} = #{@screen_name} )" if (!@followers_cancel && Log)
end
if !@followers_cancel && File.exist?(@followers_yaml)
puts "---> backing up followers yaml" if Log
FileUtils.cp(@followers_yaml,@followers_yaml_bak)
puts "---> load followers_yaml into followers_before" if Log
@followers = isids(@followers)
@followers_before = isids(YAML.load_file(@followers_yaml))
puts "---> dump followers in yaml" if Log
yaml_dump(@followers,@followers_yaml)
elsif !@followers_cancel && !File.exist?(@followers_yaml)
puts "---> substitute followers for followers_before" if Log
@followers = isids(@followers)
@followers_before = @followers
puts "---> dump followers in yaml" if Log
yaml_dump(@followers,@followers_yaml)
end
end
# listedの取得と格納と、失敗した場合のフラグ
def get_listed
ary = [];next_cursor = -1
begin
while next_cursor != 0
puts "---> fetching @#{@screen_name}'s listed cursor #{next_cursor}" if Log
r = @t.lists_followers(@user[:id],:cursor=>next_cursor)
ary.concat r[:lists]
next_cursor = r[:next_cursor]
sleep ListedWait
end
rescue
puts "---! Error in @t.lists_followers(#{@user[:id]},:cursor=>#{next_cursor}) ( #{@user[:id]} = #{@screen_name} )" if ELog
@listed_cancel = true
end
ary.each { |i| @listed << [ i[:user][:id], i[:id], i[:full_name] ] } if !@listed_cancel
if !@listed_cancel && File.exist?(@listed_yaml)
puts "---> backing up listed yaml" if Log
FileUtils.cp(@listed_yaml,@listed_yaml_bak)
puts "---> load listed_yaml into listed_before" if Log
@listed_before = YAML.load_file(@listed_yaml)
puts "---> dump listed in yaml" if Log
yaml_dump(@listed,@listed_yaml)
elsif !@listed_cancel && !File.exist?(@listed_yaml)
puts "---> substitute listed for listed_before" if Log
@listed_before = @listed
puts "---> dump listed in yaml" if Log
yaml_dump(@listed,@listed_yaml)
end
end
#アウトプットしやすいように
def output(contents,path)
puts "---> #{contents}" if Log
log_dump(@now+' '+contents,path)
@changes = true
end
#follow関係のdiffを取る
def diff_follow(b,n,c)
def ch_screen_name(t,v,c)
t.each do |m|
begin
screen_name = @t.user(m)[:screen_name]
sleep UserWait
rescue
begin
puts "---! Error in @t.user(#{m}) ( @#{@screen_name}/#{c} ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
screen_name = @t.user(m)[:screen_name]
rescue
puts "---! Error in @t.user(#{m}) ( @#{@screen_name}/#{c} )" if ELog
screen_name = '_(id: '+m.to_s+' )_'
end
end
contents = "< #{c} #{v} > @#{screen_name} http://twitter.com/#{screen_name}"
self.output(contents,@log_txt)
end
end
begin
mns = b - n
rescue
puts "---! Error in diff_follow line:294" if Log
begin
mns = b[:ids] - n[:ids]
rescue
puts "---! Error in diff_follow line:298" if Log
begin
mns = b - n[:ids]
rescue
puts "---! Error in diff_follow line:302" if Log
mns = b[:ids] -n
end
end
end
ch_screen_name(mns,'-',c) if mns
begin
pls = n - b
rescue
puts "---! Error in diff_follow line:312" if Log
begin
pls = n[:ids] - b[:ids]
rescue
puts "---! Error in diff_follow line:316" if Log
begin
pls = n - b[:ids]
rescue
puts "---! Error in diff_follow line:320" if Log
pls = n[:ids] -b
end
end
end
ch_screen_name(pls,'+',c) if pls
end
#listed関係のdiffを取る
def diff_listed
def ch_listed(t,v)
t.each do |m|
begin
list_full_name = @t.list(m[0],m[1])[:full_name]
rescue
begin
puts "---! Error in @t.list(#{m[0]},#{m[1]})[:full_name] ( @#{@screen_name}/lists/memberships ) retry after #{RetryWait} seconds..." if Log
sleep RetryWait
list_full_name = @t.list(m[0],m[1])[:full_name]
rescue
puts "---! Error in @t.list(#{m[0]},#{m[1]})[:full_name] ( @#{@screen_name}/lists/memberships )" if ELog
list_full_name = m[2]
end
end
contents = "< listed #{v} > #{list_full_name} http://twitter.com/#{list_full_name[1,list_full_name.length]}"
self.output(contents,@log_txt)
end
end
mns = @listed_before - @listed
ch_listed(mns,'-') if mns
pls = @listed - @listed_before
ch_listed(pls,'+') if pls
end
#処理まとめ。デバッグの時は先頭に#とか付けてコメントアウト出来て便利
def run
log_dump('',@log_txt) if !File.exists?(@log_txt)
self.get_following
self.get_followers
self.get_listed
self.diff_follow(@following_before,@following,'following') if !@following_cancel
self.diff_follow(@followers_before,@followers,'followers') if !@followers_cancel
self.diff_listed if !@listed_cancel
puts "---> no changes detect on @#{@screen_name}" if ( !@changes && Log )
end
#initializeで調べた感じ、無効なscreen_nameでないっぽいなら run
def main
self.run if !@cancel
end
end
#ターゲット情報の格納と、出力先ディレクトリの確認して無いなら作成
begin
target = YAML.load_file(Target_YAML)
rescue
puts "---! Can't open #{Target_YAML}"
exit
end
Dir.mkdir(Log_DIR) if !File.exist?(Log_DIR)
Dir.mkdir(Data_DIR) if !File.exist?(Data_DIR)
#実行
target.each do |t|
puts "\n---> --- @#{t} ---" if Log
ActivityCheck.new(t).main
puts "---> sleep #{SleepWait} secsonds..." if ( Log && Sleep )
sleep SleepWait if Sleep
end
consumer_key: hoge
consumer_secret: fuga
oauth_token: nyaa
oauth_token_secret: uguu
---
- DNPP
- target_screen_name_1
- target_screen_name_2
- target_screen_name_3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment