Class: ExTwitter

Inherits:
Twitter::REST::Client
  • Object
show all
Defined in:
lib/ex_twitter.rb

Overview

extended twitter

Constant Summary collapse

MAX_RETRIES =
1
WAIT =
false
AUTO_PAGINATE =

CACHE_EXPIRES_IN = 300

true
MAX_PAGINATES =
3

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ExTwitter

Returns a new instance of ExTwitter.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/ex_twitter.rb', line 19

def initialize(options = {})
  self.logger = Logger.new(STDOUT)
  self.logger.level = Logger::DEBUG

  self.auto_paginate = AUTO_PAGINATE
  self.max_retries = MAX_RETRIES
  self.wait = WAIT
  self.max_paginates = MAX_PAGINATES

  # self.cache_expires_in = (config[:cache_expires_in] || CACHE_EXPIRES_IN)
  # self.cache = ActiveSupport::Cache::FileStore.new(File.join(Dir::pwd, 'ex_twitter_cache'),
  #   {expires_in: self.cache_expires_in, race_condition_ttl: self.cache_expires_in})

  super
end

Instance Attribute Details

#auto_paginateObject

Returns the value of attribute auto_paginate.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def auto_paginate
  @auto_paginate
end

#cacheObject

Returns the value of attribute cache.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def cache
  @cache
end

#cache_expires_inObject

Returns the value of attribute cache_expires_in.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def cache_expires_in
  @cache_expires_in
end

#loggerObject

Returns the value of attribute logger.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def logger
  @logger
end

#max_paginatesObject

Returns the value of attribute max_paginates.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def max_paginates
  @max_paginates
end

#max_retriesObject

Returns the value of attribute max_retries.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def max_retries
  @max_retries
end

#waitObject

Returns the value of attribute wait.



11
12
13
# File 'lib/ex_twitter.rb', line 11

def wait
  @wait
end

Instance Method Details

#collect_with_cursor(method_name, *args, &block) ⇒ Object

cursorを使って自動ページングを行う



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/ex_twitter.rb', line 122

def collect_with_cursor(method_name, *args, &block)
  options = args.extract_options!
  logger.info "#{method_name}, #{args.inspect} #{options.inspect}"

  max_paginates = options.delete(:max_paginates) || MAX_PAGINATES
  last_response = send(method_name, *args, options).attrs
  data = last_response[:users] || last_response[:ids]

  if auto_paginate
    num_retries = 0
    (max_paginates - 1).times do
      next_cursor = last_response[:next_cursor]
      break if !next_cursor || next_cursor == 0

      options[:cursor] = next_cursor

      begin
        last_response = send(method_name, *args, options).attrs
        logger.info "#{method_name}, #{args.inspect} #{options.inspect}"
      rescue Twitter::Error::TooManyRequests => e
        if num_retries <= MAX_RETRIES
          if WAIT
            sleep e.rate_limit.reset_in
            num_retries += 1
            retry
          else
            logger.warn "retry #{e.rate_limit.reset_in} seconds later, #{e.inspect}"
          end
        else
          logger.warn "fail. num_retries > MAX_RETRIES(=#{MAX_RETRIES}), #{e.inspect}"
        end
      rescue => e
        if num_retries <= MAX_RETRIES
          logger.warn "retry till num_retries > MAX_RETRIES(=#{MAX_RETRIES}), #{e.inspect}"
          num_retries += 1
          retry
        else
          logger.warn "fail. num_retries > MAX_RETRIES(=#{MAX_RETRIES}), something error #{e.inspect}"
        end
      end

      if block_given?
        yield(data, last_response)
      else
        items = last_response[:users] || last_response[:ids]
        data.concat(items) if items.is_a?(Array)
      end
    end
  end

  data
end

#collect_with_max_id(method_name, *args, &block) ⇒ Object

max_idを使って自動ページングを行う



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/ex_twitter.rb', line 65

def collect_with_max_id(method_name, *args, &block)
  options = args.extract_options!
  logger.info "#{method_name}, #{args.inspect} #{options.inspect}"

  max_paginates = options.delete(:max_paginates) || MAX_PAGINATES
  data = []
  last_response = send(method_name, *args, options)
  if block_given?
    last_response = yield(data, last_response)
  else
    data.concat(last_response) if last_response.is_a?(Array)
  end

  if auto_paginate
    num_retries = 0
    (max_paginates - 1).times do
      break if last_response.blank?

      options[:max_id] = last_response.last[:id] - 1

      begin
        last_response = send(method_name, *args, options)
        logger.info "#{method_name}, #{args.inspect} #{options.inspect}"
      rescue Twitter::Error::TooManyRequests => e
        if num_retries <= MAX_RETRIES
          if WAIT
            sleep e.rate_limit.reset_in
            num_retries += 1
            retry
          else
            logger.warn "retry #{e.rate_limit.reset_in} seconds later, #{e.inspect}"
          end
        else
          logger.warn "fail. num_retries > MAX_RETRIES(=#{MAX_RETRIES}), #{e.inspect}"
        end
      rescue => e
        if num_retries <= MAX_RETRIES
          logger.warn "retry till num_retries > MAX_RETRIES(=#{MAX_RETRIES}), #{e.inspect}"
          num_retries += 1
          retry
        else
          logger.warn "fail. num_retries > MAX_RETRIES(=#{MAX_RETRIES}), something error #{e.inspect}"
        end
      end

      if block_given?
        last_response = yield(data, last_response)
      else
        data.concat(last_response) if last_response.is_a?(Array)
      end
    end
  end

  data
end

#follower_ids(*args) ⇒ Object



205
206
207
208
# File 'lib/ex_twitter.rb', line 205

def follower_ids(*args)
  options = {count: 5000}.merge(args.extract_options!)
  collect_with_cursor(:old_follower_ids, *args, options)
end

#followers(*args) ⇒ Object



193
194
195
196
# File 'lib/ex_twitter.rb', line 193

def followers(*args)
  options = {count: 200, include_user_entities: true}.merge(args.extract_options!)
  collect_with_cursor(:old_followers, *args, options)
end

#friend_ids(*args) ⇒ Object



199
200
201
202
# File 'lib/ex_twitter.rb', line 199

def friend_ids(*args)
  options = {count: 5000}.merge(args.extract_options!)
  collect_with_cursor(:old_friend_ids, *args, options)
end

#friends(*args) ⇒ Object



187
188
189
190
# File 'lib/ex_twitter.rb', line 187

def friends(*args)
  options = {count: 200, include_user_entities: true}.merge(args.extract_options!)
  collect_with_cursor(:old_friends, *args, options)
end

#get_mentions(screen_name) ⇒ Object

mentions_timeline is to fetch the timeline of Tweets mentioning the authenticated user get_mentions is to fetch the Tweets mentioning the screen_name’s user



254
255
256
# File 'lib/ex_twitter.rb', line 254

def get_mentions(screen_name)
  search("to:#{screen_name}")
end

#old_follower_idsObject



204
# File 'lib/ex_twitter.rb', line 204

alias :old_follower_ids :follower_ids

#old_followersObject



192
# File 'lib/ex_twitter.rb', line 192

alias :old_followers :followers

#old_friend_idsObject



198
# File 'lib/ex_twitter.rb', line 198

alias :old_friend_ids :friend_ids

#old_friendsObject



186
# File 'lib/ex_twitter.rb', line 186

alias :old_friends :friends

#old_searchTwitter::SearchResults

Note:

Please note that Twitter’s search service and, by extension, the Search API is not meant to be an exhaustive source of Tweets. Not all Tweets will be indexed or made available via the search interface.

Returns tweets that match a specified query.

Parameters:

  • q (String)

    A search term. (from|to):hello min_retweets:3 OR min_faves:3 OR min_replies:3, #nhk @hello (in|ex)clude:retweets twitter.com/search-advanced

  • options (Hash)

    A customizable set of options.

Returns:

  • (Twitter::SearchResults)

    Return tweets that match a specified query with search metadata

Raises:

  • (Twitter::Error::Unauthorized)

    Error raised when supplied user credentials are not valid.

See Also:



242
# File 'lib/ex_twitter.rb', line 242

alias :old_search :search

#old_user_timelineObject



175
# File 'lib/ex_twitter.rb', line 175

alias :old_user_timeline :user_timeline

#old_usersObject



210
# File 'lib/ex_twitter.rb', line 210

alias :old_users :users

#search(*args) ⇒ Object



243
244
245
246
247
248
249
250
# File 'lib/ex_twitter.rb', line 243

def search(*args)
  options = {count: 100, result_type: 'recent'}.merge(args.extract_options!)
  collect_with_max_id(:old_search, *args, options) do |data, last_response|
    statuses = last_response.attrs[:statuses]
    data.concat(statuses)
    statuses
  end
end

#search_japanese_tweets(str) ⇒ Object



258
259
260
# File 'lib/ex_twitter.rb', line 258

def search_japanese_tweets(str)
  search(str, {lang: 'ja'})
end

#search_tweets_except_rt(str) ⇒ Object



262
263
264
# File 'lib/ex_twitter.rb', line 262

def search_tweets_except_rt(str)
  search("#{str} exclude:retweets")
end

#user_photos(*args) ⇒ Object



181
182
183
184
# File 'lib/ex_twitter.rb', line 181

def user_photos(*args)
  tweets = user_timeline(*args)
  tweets.select{|t| t.media? }.map{|t| t.media }.flatten
end

#user_timeline(*args) ⇒ Object



176
177
178
179
# File 'lib/ex_twitter.rb', line 176

def user_timeline(*args)
  options = {count: 200, include_rts: true}.merge(args.extract_options!)
  collect_with_max_id(:old_user_timeline, *args, options)
end

#users(ids, options = {}) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/ex_twitter.rb', line 211

def users(ids, options = {})
  ids_per_worker = ids.each_slice(100).to_a
  processed_users = []

  Parallel.each_with_index(ids_per_worker, in_threads: ids_per_worker.size) do |ids, i|
    _users = {i: i, users: old_users(ids, options)}
    processed_users << _users
  end

  processed_users.sort_by{|p| p[:i] }.map{|p| p[:users] }.flatten
end