twitter_friendly 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef71f130f04b632a363dd5dbe4f7e2b91127d3e74da06b2250d63bf939c90a86
4
- data.tar.gz: 4b0796b5bb063275954bade7042cb0ebe165710d8bc519b7844d78934c6817a0
3
+ metadata.gz: cec5d0d0bab4de7c8cc59727c5c57ce632b76c6e40c3684a66cce539cbb509ef
4
+ data.tar.gz: d37e61958513f084b5eed73f68f9d073202dd58e774138072cb6a1b28b3e70bc
5
5
  SHA512:
6
- metadata.gz: 473bd0e95817c1d6ff726374466fce9eace07ee8b4f3333674f0a2dcfa648b62c47e5641e88a21d4430618c09af342f4f07836fe5190aefeaa5bb3b588c8611a
7
- data.tar.gz: e5af4919178d9602423a7c30944850d09080bd4e9fdc81f55de42466fe6705f23e0ce7a4d51a0abc52d7628db3bcc673791f06735e88cafd5675dac9d7995185
6
+ metadata.gz: 376dbce938d1e5baf735fee3ff09a869ce2b2b562c159046c1a92c37d9e5408d2f5ae4ce005f98eb62d5dbb6f10b31229b15bd402a905c949ad9adbe38aa0aae
7
+ data.tar.gz: 93f140337e9a317165f974e65a992e34a42d1f278add7add063379c882c51aeef54ccb179cef419e02ad21956f3d9aad2f370fad211d5bb680ab587fa8298eeb
data/.gitignore CHANGED
@@ -7,4 +7,8 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ *.log
11
+ /.pryrc
12
+ /.env
13
+ /.twitter_friendly
10
14
  /.idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ -fd
@@ -0,0 +1,41 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ # For ruby compatibility, we test the highest and lowest minor versions only.
5
+ # For example, if our gemspec says `required_ruby_version = ">= 2.3.0"`, and
6
+ # ruby 2.5.0 has just been released, then we test 2.3 and 2.5, but not 2.4.
7
+ rvm:
8
+ - 2.3.8
9
+ - 2.4.5
10
+ - 2.5.3
11
+
12
+ env:
13
+ global:
14
+ - TRAVIS=true
15
+
16
+ # We want to use `sudo: false` because the container infrastructure is supposed
17
+ # to be faster, but Travis is having issues with containers lately ..
18
+ #
19
+ # > No output has been received in the last 10m0s
20
+ #
21
+ # .. and they recommend we use the VM infrastructure (`sudo: required`) in
22
+ # the meantime.
23
+ sudo: required
24
+
25
+ before_install:
26
+ - gem update bundler
27
+
28
+ gemfile:
29
+ - gemfiles/ar_4.2.gemfile
30
+ - gemfiles/ar_5.1.gemfile
31
+ - gemfiles/ar_5.2.gemfile
32
+ matrix:
33
+ exclude:
34
+ # optimization: don't test intermediate rubies (see above)
35
+ - rvm: 2.4.5
36
+ gemfile: gemfiles/ar_4.2.gemfile
37
+ - rvm: 2.4.5
38
+ gemfile: gemfiles/ar_5.1.gemfile
39
+ - rvm: 2.4.5
40
+ gemfile: gemfiles/ar_5.2.gemfile
41
+ fast_finish: true
@@ -1,18 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twitter_friendly (0.1.0)
4
+ twitter_friendly (0.2.0)
5
+ activesupport (>= 4.2, < 6.0)
6
+ oj (~> 3.7.6)
5
7
  parallel (~> 1.12.1)
6
8
  twitter (~> 6.2.0)
7
9
 
8
10
  GEM
9
11
  remote: https://rubygems.org/
10
12
  specs:
13
+ activesupport (5.2.2)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
11
18
  addressable (2.5.2)
12
19
  public_suffix (>= 2.0.2, < 4.0)
13
20
  buftok (0.2.0)
21
+ coderay (1.1.2)
22
+ concurrent-ruby (1.1.4)
23
+ diff-lcs (1.3)
14
24
  domain_name (0.5.20180417)
15
25
  unf (>= 0.0.5, < 1.0.0)
26
+ dotenv (2.6.0)
16
27
  equalizer (0.0.11)
17
28
  http (3.3.0)
18
29
  addressable (~> 2.3)
@@ -23,13 +34,35 @@ GEM
23
34
  domain_name (~> 0.5)
24
35
  http-form_data (2.1.1)
25
36
  http_parser.rb (0.6.0)
37
+ i18n (1.5.1)
38
+ concurrent-ruby (~> 1.0)
26
39
  memoizable (0.4.2)
27
40
  thread_safe (~> 0.3, >= 0.3.1)
41
+ method_source (0.9.2)
42
+ minitest (5.11.3)
28
43
  multipart-post (2.0.0)
29
44
  naught (1.1.0)
45
+ oj (3.7.6)
30
46
  parallel (1.12.1)
47
+ pry (0.12.2)
48
+ coderay (~> 1.1.0)
49
+ method_source (~> 0.9.0)
31
50
  public_suffix (3.0.3)
32
- rake (10.5.0)
51
+ rake (12.3.2)
52
+ rb-readline (0.5.5)
53
+ rspec (3.8.0)
54
+ rspec-core (~> 3.8.0)
55
+ rspec-expectations (~> 3.8.0)
56
+ rspec-mocks (~> 3.8.0)
57
+ rspec-core (3.8.0)
58
+ rspec-support (~> 3.8.0)
59
+ rspec-expectations (3.8.2)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.8.0)
62
+ rspec-mocks (3.8.0)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.8.0)
65
+ rspec-support (3.8.0)
33
66
  simple_oauth (0.3.1)
34
67
  thread_safe (0.3.6)
35
68
  twitter (6.2.0)
@@ -43,6 +76,8 @@ GEM
43
76
  multipart-post (~> 2.0)
44
77
  naught (~> 1.0)
45
78
  simple_oauth (~> 0.3.0)
79
+ tzinfo (1.2.5)
80
+ thread_safe (~> 0.1)
46
81
  unf (0.1.4)
47
82
  unf_ext
48
83
  unf_ext (0.0.7.5)
@@ -51,9 +86,13 @@ PLATFORMS
51
86
  ruby
52
87
 
53
88
  DEPENDENCIES
54
- bundler (~> 1.17)
55
- rake (~> 10.0)
89
+ bundler
90
+ dotenv
91
+ pry
92
+ rake
93
+ rb-readline
94
+ rspec (~> 3.8)
56
95
  twitter_friendly!
57
96
 
58
97
  BUNDLED WITH
59
- 1.17.2
98
+ 2.0.1
data/README.md CHANGED
@@ -1,8 +1,13 @@
1
- # TwitterFriendly
1
+ # twitter_friendly
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/twitter_friendly`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Gem Version](https://badge.fury.io/rb/twitter_friendly.png)](https://badge.fury.io/rb/twitter_friendly)
4
+ [![Build Status](https://travis-ci.org/ts-3156/twitter_friendly.svg?branch=master)](https://travis-ci.org/ts-3156/twitter_friendly)
4
5
 
5
- TODO: Delete this and the text above, and describe your gem
6
+ A twitter-friendly Ruby interface to the Twitter API. This twitter_friendly gem provides multiple features.
7
+
8
+ - Auto pagination
9
+ - Auto caching
10
+ - Parallelly fetching
6
11
 
7
12
  ## Installation
8
13
 
@@ -14,25 +19,172 @@ gem 'twitter_friendly'
14
19
 
15
20
  And then execute:
16
21
 
17
- $ bundle
22
+ ```sh
23
+ $ bundle
24
+ ```
18
25
 
19
26
  Or install it yourself as:
20
27
 
21
- $ gem install twitter_friendly
28
+ ```sh
29
+ $ gem install twitter_friendly
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ You can pass configuration options as a block to `TwitterFriendly::Client.new` just like the below.
35
+
36
+ ```
37
+ client = TwitterFriendly::Client.new do |config|
38
+ config.consumer_key = "YOUR_CONSUMER_KEY"
39
+ config.consumer_secret = "YOUR_CONSUMER_SECRET"
40
+ config.access_token = "YOUR_ACCESS_TOKEN"
41
+ config.access_token_secret = "YOUR_ACCESS_SECRET"
42
+ end
43
+ ```
44
+
45
+ ## Useful features
46
+
47
+ After configuring a `client`, you can do the following things.
48
+
49
+ Fetch all friends's user IDs (by screen name or user ID, or by implicit authenticated user)
50
+
51
+ ```ruby
52
+ ids = client.follower_ids('gem')
53
+ ids.size
54
+ # => 1741
55
+ ```
56
+
57
+ As using a cache, it's super fast from the second time.
58
+
59
+ ```ruby
60
+ Benchmark.bm 20 do |r|
61
+ r.report "Fetch follower_ids" do
62
+ client.follower_ids('gem')
63
+ end
64
+ r.report "(Cached)" do
65
+ client.follower_ids('gem')
66
+ end
67
+ end
68
+
69
+ # user system total real
70
+ # Fetch follower_ids 0.010330 0.003607 0.013937 ( 0.981068)
71
+ # (Cached) 0.000865 0.000153 0.001018 ( 0.001019) <- Roughly 900 times faster!
72
+ ```
73
+
74
+ You don't need to write a boilerplate code as having auto pagination feature.
75
+
76
+ ```ruby
77
+ users = client.follower_ids('a_user_has_many_friends')
78
+ users.size
79
+ # => 50000
80
+ ```
81
+
82
+ If you don't use twitter_friendly gem, you must write the code like the below to fetch all follower's ids.
83
+
84
+ ```ruby
85
+ def collect_with_max_id(collection=[], max_id=nil, &block)
86
+ response = yield(max_id)
87
+ collection += response
88
+ response.empty? ? collection.flatten : collect_with_max_id(collection, response.last.id - 1, &block)
89
+ end
90
+
91
+ ids =
92
+ collect_with_max_id do |max_id|
93
+ options = {count: 200, include_rts: true}
94
+ options[:max_id] = max_id unless max_id.nil?
95
+ client.follower_ids('user_name', options)
96
+ end
97
+ ```
98
+
99
+ Additionally, twitter_friendly gem has a parallel execution feature.
100
+
101
+ ```ruby
102
+ ids = [id1, id2, id3, ... , id1000]
103
+
104
+ Benchmark.bm 25 do |r|
105
+ r.report "Fetch users in parallel" do
106
+ client.users(ids)
107
+ end
108
+
109
+ client.cache.clear
22
110
 
23
- ## Usage
111
+ r.report "Fetch users in serial" do
112
+ client.users(ids, parallel: false)
113
+ end
114
+ end
24
115
 
25
- TODO: Write usage instructions here
116
+ # user system total real
117
+ # Fetch users in parallel 0.271966 0.057981 0.329947 ( 2.675270) <- Super fast!
118
+ # Fetch users in serial 0.201375 0.044399 0.245774 ( 8.068372)
119
+ ```
120
+
121
+ ## Usage examples
122
+
123
+ Fetch all friends's user IDs (by screen name or user ID, or by implicit authenticated user)
124
+
125
+ ```ruby
126
+ client.friend_ids('gem')
127
+ client.friend_ids(213747670)
128
+ client.friend_ids
129
+ ```
130
+
131
+ Fetch all followers's user IDs (by screen name or user ID, or by implicit authenticated user)
132
+
133
+ ```ruby
134
+ client.follower_ids('gem')
135
+ client.follower_ids(213747670)
136
+ client.follower_ids
137
+ ```
138
+
139
+ Fetch all friends with profile details (by screen name or user ID, or by implicit authenticated user)
140
+
141
+ ```ruby
142
+ client.friends('gem')
143
+ client.friends(213747670)
144
+ client.friends
145
+ ```
26
146
 
27
- ## Development
147
+ Fetch all followers with profile details (by screen name or user ID, or by implicit authenticated user)
28
148
 
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
149
+ ```ruby
150
+ client.followers('gem')
151
+ client.followers(213747670)
152
+ client.followers
153
+ ```
30
154
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
155
+
156
+ Fetch the timeline of Tweets (by screen name or user ID, or by implicit authenticated user)
157
+
158
+ ```ruby
159
+ client.user_timeline('gem')
160
+ client.user_timeline(213747670)
161
+ client.user_timeline
162
+
163
+ result.size
164
+ # => 588
165
+
166
+ result.first.text
167
+ # => "Your tweet text..."
168
+
169
+ result.first.user.screen_name
170
+ # => "your_screen_name"
171
+ ```
172
+
173
+ Fetch the timeline of Tweets from the authenticated user's home page
174
+
175
+ ```ruby
176
+ client.home_timeline
177
+ ```
178
+
179
+ Fetch the timeline of Tweets mentioning the authenticated user
180
+
181
+ ```ruby
182
+ client.mentions_timeline
183
+ ```
32
184
 
33
185
  ## Contributing
34
186
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/twitter_friendly.
187
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ts-3156/twitter_friendly.
36
188
 
37
189
  ## License
38
190
 
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dotenv/load'
4
+ require 'twitter_friendly'
5
+
6
+ TwitterFriendly.cache.clear
7
+
8
+ client =
9
+ TwitterFriendly::Client.new(
10
+ consumer_key: ENV['CK'],
11
+ consumer_secret: ENV['CS'],
12
+ access_token: ENV['AT'],
13
+ access_token_secret: ENV['ATS']
14
+ )
15
+
16
+ def diff(ary1, ary2)
17
+ [ary1 - ary2, ary2 - ary1]
18
+ end
19
+
20
+ def diff?(ary1, ary2)
21
+ diff(ary1, ary2).flatten.any?
22
+ end
23
+
24
+ def users_diff(ary1, ary2)
25
+ diff(ary1.map {|a| a[:id]}, ary2.map {|a| a[:id]})
26
+ end
27
+
28
+ def users_diff?(ary1, ary2)
29
+ users_diff(ary1, ary2).flatten.any?
30
+ end
31
+
32
+ friend_ids = follower_ids = []
33
+
34
+ %i(friend_ids follower_ids).each do |method|
35
+ ids = client.send(method)
36
+ cached_ids = client.send(method)
37
+ raw_ids = client.internal_client.send(method).attrs[:ids]
38
+
39
+ puts method
40
+ puts " fetch #{ids.size}, cache #{cached_ids.size}, raw #{raw_ids.size}"
41
+ puts " ids is different from cached_ids diff=#{diff(ids, cached_ids).inspect}" if diff?(ids, cached_ids)
42
+ puts " cached_ids is different from raw_ids diff=#{diff(cached_ids, raw_ids).inspect}" if diff?(cached_ids, raw_ids)
43
+ puts " ids is different from raw_ids diff=#{diff(ids, raw_ids).inspect}" if diff?(ids, raw_ids)
44
+ puts " #{client.rate_limit.send(method)}"
45
+
46
+ eval("#{method}=ids")
47
+ end
48
+
49
+ client.cache.clear
50
+
51
+ ids1, ids2 = client.friend_ids_and_follower_ids
52
+ cached_ids1, cached_ids2 = client.friend_ids_and_follower_ids
53
+
54
+ puts 'friend_ids_and_follower_ids'
55
+ puts " fetch #{ids1.size}, cache #{cached_ids1.size}"
56
+ puts " fetch #{ids2.size}, cache #{cached_ids2.size}"
57
+ puts " ids1 is different from cached_ids1 diff=#{diff(ids1, cached_ids1)}" if diff?(ids1, cached_ids1)
58
+ puts " ids2 is different from cached_ids2 diff=#{diff(ids2, cached_ids2)}" if diff?(ids2, cached_ids2)
59
+
60
+ client.cache.clear
61
+
62
+ friends = followers = []
63
+
64
+ %i(friends followers).each do |method|
65
+ users = client.send(method)
66
+ cached_users = client.send(method)
67
+ # raw_users = client.internal_client.send(method).attrs[:users]
68
+
69
+ puts method
70
+ puts " users #{users.size}, cached_users #{cached_users.size}"
71
+ puts " users is different from cached_users diff=#{users_diff(users, cached_users)}" if users_diff?(users, cached_users)
72
+ # puts " cached_users is different from raw_users" if cached_users != raw_users
73
+ # puts " users is different from raw_users" if users != raw_users
74
+ puts " #{client.rate_limit.send(method)}"
75
+
76
+ eval("#{method}=users")
77
+ end
78
+
79
+ client.cache.clear
80
+
81
+ users1, users2 = client.friends_and_followers
82
+ cached_users1, cached_users2 = client.friends_and_followers
83
+
84
+ puts 'friends_and_followers'
85
+ puts " fetch #{users1.size}, cache #{cached_users1.size}"
86
+ puts " fetch #{users2.size}, cache #{cached_users2.size}"
87
+ puts " users1 is different from cached_users1 diff=#{users_diff(users1, cached_users1)}" if users_diff?(users1, cached_users1)
88
+ puts " users2 is different from cached_users2 diff=#{users_diff(users2, cached_users2)}" if users_diff?(users2, cached_users2)
89
+
90
+ client.cache.clear
91
+
92
+ puts friend_ids.zip(friends).all? {|id, user| id == user[:id] }
93
+ puts follower_ids.zip(followers).all? {|id, user| id == user[:id] }
94
+
95
+ puts 'ok'