twitter_with_auto_pagination 0.8.12 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|