twitter_with_auto_pagination 0.8.12 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/twitter_with_auto_pagination/analysis/api.rb +9 -0
- data/lib/twitter_with_auto_pagination/{rest/uncategorized.rb → analysis/timelines.rb} +2 -2
- data/lib/twitter_with_auto_pagination/cache.rb +78 -0
- data/lib/twitter_with_auto_pagination/caching_and_logging.rb +80 -0
- data/lib/twitter_with_auto_pagination/client.rb +57 -0
- data/lib/twitter_with_auto_pagination/collector.rb +18 -0
- data/lib/twitter_with_auto_pagination/log_subscriber.rb +59 -26
- data/lib/twitter_with_auto_pagination/logger.rb +10 -0
- data/lib/twitter_with_auto_pagination/parallel.rb +25 -0
- data/lib/twitter_with_auto_pagination/rate_limit.rb +56 -0
- data/lib/twitter_with_auto_pagination/rest/api.rb +16 -14
- data/lib/twitter_with_auto_pagination/rest/extension/friends_and_followers.rb +0 -7
- data/lib/twitter_with_auto_pagination/rest/favorites.rb +13 -7
- data/lib/twitter_with_auto_pagination/rest/friends_and_followers.rb +33 -70
- data/lib/twitter_with_auto_pagination/rest/lists.rb +10 -9
- data/lib/twitter_with_auto_pagination/rest/search.rb +16 -6
- data/lib/twitter_with_auto_pagination/rest/timelines.rb +13 -26
- data/lib/twitter_with_auto_pagination/rest/users.rb +27 -40
- data/lib/twitter_with_auto_pagination/rest/utils.rb +29 -149
- data/lib/twitter_with_auto_pagination/serializer.rb +27 -0
- data/lib/twitter_with_auto_pagination.rb +2 -38
- data/spec/helper.rb +167 -36
- data/spec/twitter_with_auto_pagination/cache_spec.rb +71 -0
- data/spec/twitter_with_auto_pagination/client_spec.rb +7 -145
- data/spec/twitter_with_auto_pagination/parallel_spec.rb +23 -0
- data/spec/twitter_with_auto_pagination/rest/favorites_spec.rb +58 -0
- data/spec/twitter_with_auto_pagination/rest/friends_and_followers_spec.rb +161 -0
- data/spec/twitter_with_auto_pagination/rest/lists_spec.rb +39 -0
- data/spec/twitter_with_auto_pagination/rest/search_spec.rb +42 -0
- data/spec/twitter_with_auto_pagination/rest/timelines_spec.rb +82 -0
- data/spec/twitter_with_auto_pagination/rest/users_spec.rb +143 -0
- data/twitter_with_auto_pagination.gemspec +1 -1
- metadata +28 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed91eaf1cf67bef358dda37cdd3886003fa80c0c
|
4
|
+
data.tar.gz: e91e410326935bb838a8c9c7d29f678d129b2417
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97ad05cdd642560bb57e5ef28f2d1b7fdbb492e9112dfdd0af8688fd7a3735f799a0d99957d97a28e7699d158724a14dccd57c3424b9b5964e68ead8990af020
|
7
|
+
data.tar.gz: f342f1131df4b7fe0410e5ad9b61879bb88a07077d08a4414e07828dea0fcb1a3ba6cec6ee9c638de382fb36b72dce4d36344e99d7a94562dfdf9d7c1eba3197
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
require 'twitter_with_auto_pagination/serializer'
|
5
|
+
|
6
|
+
module TwitterWithAutoPagination
|
7
|
+
class Cache
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
attr_reader :serializer, :client
|
11
|
+
|
12
|
+
def_delegators :@client, :clear, :cleanup
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@serializer = Serializer
|
16
|
+
|
17
|
+
path = File.join('tmp', 'twitter_cache')
|
18
|
+
Dir.mkdir(path) unless File.exists?(path)
|
19
|
+
@client = ActiveSupport::Cache::FileStore.new(path, expires_in: 1.hour, race_condition_ttl: 5.minutes)
|
20
|
+
end
|
21
|
+
|
22
|
+
def fetch(method, user, options = {}, &block)
|
23
|
+
key = normalize_key(method, user, options.except(:args))
|
24
|
+
|
25
|
+
block_result = nil
|
26
|
+
fetch_result =
|
27
|
+
@client.fetch(key) do
|
28
|
+
block_result = yield
|
29
|
+
serializer.encode(block_result, args: options[:args])
|
30
|
+
end
|
31
|
+
|
32
|
+
block_result ? block_result : serializer.decode(fetch_result, args: options[:args])
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
DELIM = ':'
|
38
|
+
|
39
|
+
def normalize_key(method, user, options = {})
|
40
|
+
identifier =
|
41
|
+
case
|
42
|
+
when method == :search then "query#{DELIM}#{user}"
|
43
|
+
when method == :friendship? then "from#{DELIM}#{user[0]}#{DELIM}to#{DELIM}#{user[1]}"
|
44
|
+
when method == :list_members then "list_id#{DELIM}#{user}"
|
45
|
+
when user.nil? && options[:hash].present? then "token-hash#{DELIM}#{options[:hash]}"
|
46
|
+
else user_identifier(user)
|
47
|
+
end
|
48
|
+
|
49
|
+
"#{method}#{DELIM}#{identifier}#{DELIM}#{options_identifier(options)}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def user_identifier(user)
|
53
|
+
case
|
54
|
+
when user.kind_of?(Integer) then "id#{DELIM}#{user}"
|
55
|
+
when user.kind_of?(String) then "screen_name#{DELIM}#{user}"
|
56
|
+
when user.kind_of?(Array) && user.empty? then 'The_#users_is_called_with_an_empty_array'
|
57
|
+
when user.kind_of?(Array) && user[0].kind_of?(Integer) then "ids#{DELIM}#{user.size}-#{hexdigest(user.join(','))}"
|
58
|
+
when user.kind_of?(Array) && user[0].kind_of?(String) then "screen_names#{DELIM}#{user.size}-#{hexdigest(user.join(','))}"
|
59
|
+
else raise "#{__method__}: No matches #{user.inspect}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def options_identifier(options)
|
64
|
+
options = options.except(:hash, :call_count, :call_limit, :super_operation)
|
65
|
+
str =
|
66
|
+
if options.empty?
|
67
|
+
'empty'
|
68
|
+
else
|
69
|
+
options.map { |k, v| "#{k}#{DELIM}#{v}" }.join(',')
|
70
|
+
end
|
71
|
+
"options#{DELIM}#{str}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def hexdigest(str)
|
75
|
+
Digest::MD5.hexdigest(str)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module TwitterWithAutoPagination
|
2
|
+
module CachingAndLogging
|
3
|
+
%i(
|
4
|
+
verify_credentials
|
5
|
+
user?
|
6
|
+
user
|
7
|
+
users
|
8
|
+
blocked_ids
|
9
|
+
home_timeline
|
10
|
+
user_timeline
|
11
|
+
mentions_timeline
|
12
|
+
search
|
13
|
+
favorites
|
14
|
+
friendship?
|
15
|
+
friend_ids
|
16
|
+
follower_ids
|
17
|
+
memberships
|
18
|
+
list_members
|
19
|
+
).each do |name|
|
20
|
+
define_method(name) do |*args|
|
21
|
+
options = args.extract_options!
|
22
|
+
|
23
|
+
Instrumenter.api_call(name, options) do
|
24
|
+
do_request =
|
25
|
+
proc { Instrumenter.perform_request(name, options) { options.empty? ? super(*args) : super(*args, options) } }
|
26
|
+
|
27
|
+
if Utils.cache_disabled?(options)
|
28
|
+
do_request.call
|
29
|
+
else
|
30
|
+
user = name == :friendship? ? args[0, 2] : args[0]
|
31
|
+
cache.fetch(name, user, options.merge(args: [name, options], hash: credentials_hash), &do_request)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Cached in #users
|
38
|
+
%i(friends followers friends_and_followers).each do |name|
|
39
|
+
define_method(name) do |*args|
|
40
|
+
options = args.extract_options!
|
41
|
+
Instrumenter.api_call(name, options) { super(*args, options) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Instrumenter
|
46
|
+
|
47
|
+
module_function
|
48
|
+
|
49
|
+
def api_call(operation, options)
|
50
|
+
payload = {operation: operation}.merge(options)
|
51
|
+
ActiveSupport::Notifications.instrument('api_call.twitter', payload) { yield(payload) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def perform_request(caller, options, &block)
|
55
|
+
payload = {operation: 'request', args: [caller, options]}
|
56
|
+
ActiveSupport::Notifications.instrument('request.twitter', payload) { yield(payload) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module Utils
|
61
|
+
|
62
|
+
module_function
|
63
|
+
|
64
|
+
def cache_disabled?(options)
|
65
|
+
options.is_a?(Hash) && options.has_key?(:cache) && !options[:cache]
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_mash(obj)
|
69
|
+
case
|
70
|
+
when obj.kind_of?(Array)
|
71
|
+
obj.map {|o| to_mash(o)}
|
72
|
+
when obj.kind_of?(Hash)
|
73
|
+
Hashie::Mash.new(obj.map {|k, v| [k, to_mash(v)]}.to_h)
|
74
|
+
else
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'twitter_with_auto_pagination/logger'
|
4
|
+
require 'twitter_with_auto_pagination/cache'
|
5
|
+
require 'twitter_with_auto_pagination/log_subscriber'
|
6
|
+
require 'twitter_with_auto_pagination/analysis/api'
|
7
|
+
require 'twitter_with_auto_pagination/rest/api'
|
8
|
+
require 'twitter_with_auto_pagination/rate_limit'
|
9
|
+
require 'twitter_with_auto_pagination/parallel'
|
10
|
+
|
11
|
+
module TwitterWithAutoPagination
|
12
|
+
class Client
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
attr_reader :cache, :twitter
|
16
|
+
|
17
|
+
def_delegators :@twitter, :perform_get, :access_token, :access_token_secret, :consumer_key, :consumer_secret
|
18
|
+
|
19
|
+
include TwitterWithAutoPagination::RateLimit
|
20
|
+
include TwitterWithAutoPagination::Parallel
|
21
|
+
include TwitterWithAutoPagination::REST::API
|
22
|
+
include TwitterWithAutoPagination::Analysis::API
|
23
|
+
|
24
|
+
def initialize(*args)
|
25
|
+
options = args.extract_options!
|
26
|
+
|
27
|
+
@cache = TwitterWithAutoPagination::Cache.new
|
28
|
+
Logging.logger = logger = TwitterWithAutoPagination::Logger.new(options)
|
29
|
+
|
30
|
+
unless subscriber_attached?
|
31
|
+
@@subscriber_attached = true
|
32
|
+
if logger.debug?
|
33
|
+
# Super slow
|
34
|
+
TwitterWithAutoPagination::AllLogSubscriber.attach_to :twitter
|
35
|
+
TwitterWithAutoPagination::ASLogSubscriber.attach_to :active_support
|
36
|
+
elsif logger.info?
|
37
|
+
TwitterWithAutoPagination::ApiCallLogSubscriber.attach_to :twitter
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@twitter = Twitter::REST::Client.new(options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.logger
|
45
|
+
Logging.logger
|
46
|
+
end
|
47
|
+
|
48
|
+
def subscriber_attached?
|
49
|
+
@@subscriber_attached ||= false
|
50
|
+
end
|
51
|
+
|
52
|
+
# Deprecated
|
53
|
+
def call_count
|
54
|
+
-1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module TwitterWithAutoPagination
|
2
|
+
module Collector
|
3
|
+
|
4
|
+
def collect_with_max_id(collection = [], max_id = nil, &block)
|
5
|
+
tweets = yield(max_id)
|
6
|
+
return collection if tweets.nil?
|
7
|
+
collection += tweets
|
8
|
+
tweets.empty? ? collection.flatten : collect_with_max_id(collection, tweets.last.id - 1, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def collect_with_cursor(collection = [], cursor = nil, &block)
|
12
|
+
response = yield(cursor)
|
13
|
+
return collection if response.nil?
|
14
|
+
collection += (response.attrs[:ids] || response.attrs[:users] || response.attrs[:lists]) # TODO to_a
|
15
|
+
response.attrs[:next_cursor].zero? ? collection.flatten : collect_with_cursor(collection, response.attrs[:next_cursor], &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,57 +1,90 @@
|
|
1
1
|
module TwitterWithAutoPagination
|
2
|
-
|
2
|
+
module Logging
|
3
|
+
def truncated_payload(payload)
|
4
|
+
return payload.inspect if !payload.has_key?(:args) || !payload[:args].is_a?(Array) || payload[:args].empty? || !payload[:args][0].is_a?(Array)
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
+
args = payload[:args].dup
|
7
|
+
args[0] =
|
8
|
+
if args[0].size > 3
|
9
|
+
"[#{args[0].take(3).join(', ')} ... #{args[0].size}]"
|
10
|
+
else
|
11
|
+
args[0].inspect
|
12
|
+
end
|
13
|
+
|
14
|
+
{args: args}.merge(payload.except(:args)).inspect
|
6
15
|
end
|
7
16
|
|
8
|
-
|
9
|
-
return unless logger.debug?
|
17
|
+
module_function
|
10
18
|
|
11
|
-
|
12
|
-
|
13
|
-
name = color(name, CYAN, true) # WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW
|
14
|
-
debug { "#{name} #{(payload.inspect)}" }
|
19
|
+
def logger
|
20
|
+
@@logger
|
15
21
|
end
|
16
22
|
|
17
|
-
|
23
|
+
def logger=(logger)
|
24
|
+
@@logger = logger
|
25
|
+
end
|
26
|
+
end
|
18
27
|
|
19
|
-
|
20
|
-
|
28
|
+
class ApiCallLogSubscriber < ActiveSupport::LogSubscriber
|
29
|
+
include Logging
|
30
|
+
|
31
|
+
def api_call(event)
|
32
|
+
payload = event.payload
|
33
|
+
name = "TW::#{payload.delete(:operation)} (#{event.duration.round(1)}ms)"
|
34
|
+
name = color(name, YELLOW, true) # WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW
|
35
|
+
info { "#{name}#{" #{truncated_payload(payload)}" unless payload.empty?}" }
|
21
36
|
end
|
22
37
|
end
|
23
38
|
|
24
|
-
class
|
39
|
+
class AllLogSubscriber < ApiCallLogSubscriber
|
40
|
+
include Logging
|
25
41
|
|
26
|
-
def
|
42
|
+
def api_call(*args)
|
27
43
|
super
|
28
44
|
end
|
29
45
|
|
46
|
+
def twitter_any(event)
|
47
|
+
payload = event.payload
|
48
|
+
payload.delete(:name)
|
49
|
+
name = "TW::#{payload.delete(:operation)} (#{event.duration.round(1)}ms)"
|
50
|
+
name = color(name, CYAN, true) # WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW
|
51
|
+
debug { "#{name}#{" #{truncated_payload(payload)}" unless payload.empty?}" }
|
52
|
+
end
|
53
|
+
|
54
|
+
%w(request encode decode to_mash).each do |operation|
|
55
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
56
|
+
def #{operation}(event)
|
57
|
+
event.payload[:name] = '#{operation}'
|
58
|
+
twitter_any(event)
|
59
|
+
end
|
60
|
+
METHOD
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class ASLogSubscriber < ActiveSupport::LogSubscriber
|
30
65
|
def cache_any(event)
|
31
66
|
return unless logger.debug?
|
32
67
|
|
33
68
|
payload = event.payload
|
34
|
-
name= "AS::#{payload
|
69
|
+
name = "AS::#{payload[:name]} (#{event.duration.round(1)}ms)"
|
35
70
|
name = color(name, MAGENTA, true)
|
36
|
-
debug { "#{name} #{(payload.inspect)}" }
|
71
|
+
debug { "#{name} #{(payload.except(:name, :expires_in, :race_condition_ttl).inspect)}" }
|
37
72
|
end
|
38
73
|
|
39
|
-
|
74
|
+
# Ignore generate and fetch_hit
|
75
|
+
%w(read write delete exist?).each do |operation|
|
40
76
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
77
|
+
def cache_#{operation}(event)
|
78
|
+
event.payload[:name] = '#{operation}'
|
79
|
+
cache_any(event)
|
80
|
+
end
|
45
81
|
METHOD
|
46
82
|
end
|
47
83
|
|
48
84
|
private
|
49
85
|
|
50
86
|
def logger
|
51
|
-
|
87
|
+
Logging.logger
|
52
88
|
end
|
53
89
|
end
|
54
|
-
end
|
55
|
-
|
56
|
-
TwitterWithAutoPagination::LogSubscriber.attach_to :twitter_with_auto_pagination
|
57
|
-
TwitterWithAutoPagination::ASLogSubscriber.attach_to :active_support
|
90
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module TwitterWithAutoPagination
|
2
|
+
class Logger < ::Logger
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
Dir.mkdir('log') unless File.exists?('log')
|
6
|
+
super('log/twitter.log')
|
7
|
+
self.level = options.has_key?(:log_level) ? options.delete(:log_level) : :debug
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'parallel'
|
2
|
+
|
3
|
+
module TwitterWithAutoPagination
|
4
|
+
module Parallel
|
5
|
+
|
6
|
+
def parallel(options = {}, &block)
|
7
|
+
batch = Arguments.new
|
8
|
+
yield(batch)
|
9
|
+
|
10
|
+
in_threads = options.fetch(:in_threads, batch.size)
|
11
|
+
|
12
|
+
::Parallel.map_with_index(batch, in_threads: in_threads) do |args, i|
|
13
|
+
{i: i, result: send(*args)}
|
14
|
+
end.sort_by { |q| q[:i] }.map { |q| q[:result] }
|
15
|
+
end
|
16
|
+
|
17
|
+
class Arguments < Array
|
18
|
+
%i(users friend_ids follower_ids friends followers).each do |name|
|
19
|
+
define_method(name) do |*args|
|
20
|
+
send(:<< , [name, *args])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module TwitterWithAutoPagination
|
2
|
+
module RateLimit
|
3
|
+
def rate_limit
|
4
|
+
RateLimit.new(perform_get('/1.1/application/rate_limit_status.json')) rescue nil
|
5
|
+
end
|
6
|
+
|
7
|
+
class RateLimit
|
8
|
+
def initialize(status)
|
9
|
+
@status = status
|
10
|
+
end
|
11
|
+
|
12
|
+
def resources
|
13
|
+
@status[:resources]
|
14
|
+
end
|
15
|
+
|
16
|
+
def verify_credentials
|
17
|
+
extract_remaining_and_reset_in(resources[:account][:'/account/verify_credentials'])
|
18
|
+
end
|
19
|
+
|
20
|
+
def friend_ids
|
21
|
+
extract_remaining_and_reset_in(resources[:friends][:'/friends/ids'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def follower_ids
|
25
|
+
extract_remaining_and_reset_in(resources[:followers][:'/followers/ids'])
|
26
|
+
end
|
27
|
+
|
28
|
+
def users
|
29
|
+
extract_remaining_and_reset_in(resources[:users][:'/users/lookup'])
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h
|
33
|
+
{
|
34
|
+
verify_credentials: verify_credentials,
|
35
|
+
friend_ids: friend_ids,
|
36
|
+
follower_ids: follower_ids,
|
37
|
+
users: users
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def inspect
|
42
|
+
'verify_credentials ' + verify_credentials.inspect +
|
43
|
+
' friend_ids ' + friend_ids.inspect +
|
44
|
+
' follower_ids ' + follower_ids.inspect +
|
45
|
+
' users ' + users.inspect
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def extract_remaining_and_reset_in(limit)
|
51
|
+
{remaining: limit[:remaining], reset_in: (Time.at(limit[:reset]) - Time.now).round}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -4,14 +4,15 @@ require 'twitter_with_auto_pagination/rest/lists'
|
|
4
4
|
require 'twitter_with_auto_pagination/rest/search'
|
5
5
|
require 'twitter_with_auto_pagination/rest/timelines'
|
6
6
|
require 'twitter_with_auto_pagination/rest/users'
|
7
|
-
require 'twitter_with_auto_pagination/rest/uncategorized'
|
8
7
|
|
9
|
-
require 'twitter_with_auto_pagination/rest/extension/clusters'
|
10
|
-
require 'twitter_with_auto_pagination/rest/extension/favoriting'
|
11
|
-
require 'twitter_with_auto_pagination/rest/extension/friends_and_followers'
|
12
|
-
require 'twitter_with_auto_pagination/rest/extension/replying'
|
13
|
-
require 'twitter_with_auto_pagination/rest/extension/unfollowing'
|
14
|
-
require 'twitter_with_auto_pagination/rest/extension/users'
|
8
|
+
# require 'twitter_with_auto_pagination/rest/extension/clusters'
|
9
|
+
# require 'twitter_with_auto_pagination/rest/extension/favoriting'
|
10
|
+
# require 'twitter_with_auto_pagination/rest/extension/friends_and_followers'
|
11
|
+
# require 'twitter_with_auto_pagination/rest/extension/replying'
|
12
|
+
# require 'twitter_with_auto_pagination/rest/extension/unfollowing'
|
13
|
+
# require 'twitter_with_auto_pagination/rest/extension/users'
|
14
|
+
|
15
|
+
require 'twitter_with_auto_pagination/caching_and_logging'
|
15
16
|
|
16
17
|
module TwitterWithAutoPagination
|
17
18
|
module REST
|
@@ -22,14 +23,15 @@ module TwitterWithAutoPagination
|
|
22
23
|
include TwitterWithAutoPagination::REST::Search
|
23
24
|
include TwitterWithAutoPagination::REST::Timelines
|
24
25
|
include TwitterWithAutoPagination::REST::Users
|
25
|
-
include TwitterWithAutoPagination::REST::Uncategorized
|
26
26
|
|
27
|
-
include TwitterWithAutoPagination::REST::Extension::Clusters
|
28
|
-
include TwitterWithAutoPagination::REST::Extension::Favoriting
|
29
|
-
include TwitterWithAutoPagination::REST::Extension::FriendsAndFollowers
|
30
|
-
include TwitterWithAutoPagination::REST::Extension::Replying
|
31
|
-
include TwitterWithAutoPagination::REST::Extension::Unfollowing
|
32
|
-
include TwitterWithAutoPagination::REST::Extension::Users
|
27
|
+
# include TwitterWithAutoPagination::REST::Extension::Clusters
|
28
|
+
# include TwitterWithAutoPagination::REST::Extension::Favoriting
|
29
|
+
# include TwitterWithAutoPagination::REST::Extension::FriendsAndFollowers
|
30
|
+
# include TwitterWithAutoPagination::REST::Extension::Replying
|
31
|
+
# include TwitterWithAutoPagination::REST::Extension::Unfollowing
|
32
|
+
# include TwitterWithAutoPagination::REST::Extension::Users
|
33
|
+
|
34
|
+
include TwitterWithAutoPagination::CachingAndLogging
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -17,13 +17,6 @@ module TwitterWithAutoPagination
|
|
17
17
|
result
|
18
18
|
end
|
19
19
|
|
20
|
-
def friends_and_followers(*args)
|
21
|
-
_fetch_parallelly(
|
22
|
-
[
|
23
|
-
{method: :friends, args: args},
|
24
|
-
{method: :followers, args: args}])
|
25
|
-
end
|
26
|
-
|
27
20
|
def friends_followers_and_statuses(*args)
|
28
21
|
_fetch_parallelly(
|
29
22
|
[
|
@@ -5,13 +5,19 @@ module TwitterWithAutoPagination
|
|
5
5
|
module Favorites
|
6
6
|
include TwitterWithAutoPagination::REST::Utils
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
MAX_TWEETS_PER_REQUEST = 100
|
9
|
+
|
10
|
+
%i(favorites).each do |name|
|
11
|
+
define_method(name) do |*args|
|
12
|
+
options = args.extract_options!
|
13
|
+
call_limit = calc_call_limit(options.delete(:count), MAX_TWEETS_PER_REQUEST)
|
14
|
+
options = {count: MAX_TWEETS_PER_REQUEST, result_type: :recent, call_count: 0, call_limit: call_limit}.merge(options)
|
15
|
+
|
16
|
+
collect_with_max_id do |max_id|
|
17
|
+
options[:max_id] = max_id unless max_id.nil?
|
18
|
+
options[:call_count] += 1
|
19
|
+
twitter.send(name, *args, options) if options[:call_count] <= options[:call_limit]
|
20
|
+
end.map(&:attrs)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|