redd 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c90f67d9e2534cad626e22954ec8d4b901219fde
4
- data.tar.gz: 3a100caa0269c8fdbd4b14dfc1a6c8a1664b707a
3
+ metadata.gz: a9bef7701b48a6df684f8014d9514b6968406860
4
+ data.tar.gz: 65b56eae484015cea298b41ff8f8f254db735e4a
5
5
  SHA512:
6
- metadata.gz: 03f52c6f88fefb1f14e6ae690d98bf53240dc9f7bf76039ff2b236e6e98c41f774f327c8a9fab85780ace0cf3c623188d13b971a5878369f0ed9f870463cf5d9
7
- data.tar.gz: 33fb6ee0ce7d72dca59af56a93b43284f0417f624945329466970c91a2dee84dbd51d9845dbaf63d40dd8c9d2ad26a86793ff514e5aa67fce403f3c69591a069
6
+ metadata.gz: 5e35f19510578de13aedbfb4ba552e9de82d3360cc041e4d5a2d5c6fc7aa0e46c6e3c5c9ffc09e4177e3a40adc4db95b08370b518dc8450f5adcf14ff1ca53c8
7
+ data.tar.gz: 4fb1df95bd17fd235d75a440f5dc6f508a6696f2f29479b5a64ee8cb498bd9f7489dd72cef3a489b23790487d0cbd72c65baac76c78e7068ac3291fb9d2b3450
data/lib/redd.rb CHANGED
@@ -45,6 +45,6 @@ module Redd
45
45
  web: Clients::Web
46
46
  }
47
47
 
48
- @client = types[type].new(*args, **kwargs)
48
+ types[type].new(*args, **kwargs)
49
49
  end
50
50
  end
@@ -45,7 +45,7 @@ module Redd
45
45
  # @param [Hash] body A JSON hash.
46
46
  # @return [Objects::Thing, Objects::Listing]
47
47
  def object_from_body(body)
48
- return nil unless body.is_a?(Hash) && body.key?(:kind)
48
+ return nil unless body.is_a?(Hash)
49
49
  object = object_from_kind(body[:kind])
50
50
  flat = flatten_body(body)
51
51
  object.new(self, flat)
@@ -73,8 +73,6 @@ module Redd
73
73
  flattened
74
74
  end
75
75
 
76
- private
77
-
78
76
  # Get a given property of a given object.
79
77
  # @param [Objects::Base, String] object The object with the property.
80
78
  # @param [Symbol] property The property to get.
@@ -82,12 +80,14 @@ module Redd
82
80
  object.respond_to?(property) ? object.send(property) : object.to_s
83
81
  end
84
82
 
83
+ private
84
+
85
85
  # Take a multilevel body ({kind: "tx", data: {...}}) and flatten it
86
86
  # into something like {kind: "tx", ...}
87
87
  # @param [Hash] body The response body.
88
88
  # @return [Hash] The flattened hash.
89
89
  def flatten_body(body)
90
- data = body[:data]
90
+ data = body[:data] || body
91
91
  data[:kind] = body[:kind]
92
92
  data
93
93
  end
data/lib/redd/error.rb CHANGED
@@ -27,6 +27,7 @@ module Redd
27
27
  when /wrong_password/i then InvalidCredentials
28
28
  when /bad_captcha/i then InvalidCaptcha
29
29
  when /ratelimit/i then RateLimited
30
+ when /quota_filled/i then RateLimited
30
31
  when /bad_css_name/i then InvalidClassName
31
32
  when /too_old/i then Archived
32
33
  when /too_much_flair_css/i then TooManyClassNames
@@ -120,7 +121,7 @@ module Redd
120
121
  attr_reader :time
121
122
 
122
123
  def initialize(env)
123
- @time = env[:body][:json][:ratelimit]
124
+ @time = env[:body][:json][:ratelimit] || 60*60
124
125
  super
125
126
  end
126
127
  end
@@ -15,7 +15,7 @@ module Redd
15
15
 
16
16
  # @return [Listing] The comment's replies.
17
17
  def replies
18
- @replies ||= client.object_from_body(self[:replies])
18
+ @replies ||= (client.object_from_body(self[:replies]) || [])
19
19
  end
20
20
  end
21
21
  end
@@ -21,7 +21,7 @@ module Redd
21
21
  @before = attributes[:before]
22
22
  @after = attributes[:after]
23
23
  attributes[:children].each do |child|
24
- self << client.object_from_body(child) || child
24
+ self << (client.object_from_body(child) || child)
25
25
  end
26
26
  end
27
27
  end
@@ -41,7 +41,7 @@ module Redd
41
41
  resubmit: resubmit, sendreplies: sendreplies
42
42
  }
43
43
 
44
- params << {captcha: captcha, iden: identifier} if captcha
44
+ params.merge!(captcha: captcha, iden: identifier) if captcha
45
45
  params[:kind], params[:text] = :self, text if text
46
46
  params[:kind], params[:url] = :link, url if url
47
47
 
@@ -150,15 +150,16 @@ module Redd
150
150
  # @param [String] text The text to set the flair to.
151
151
  # @param [String] css_class The css_class of the flair.
152
152
  def set_flair(thing, type = nil, text = nil, css_class = nil)
153
+ params = {text: text, css_class: css_class}
153
154
  if thing.is_a?(Objects::User) || type == :user
154
155
  params[:name] = client.property(thing, :name)
155
- elsif thing.is_a?(Objects::Submission) || type == :user
156
+ elsif thing.is_a?(Objects::Submission) || type == :link
156
157
  params[:link] = client.property(thing, :fullname)
157
158
  else
158
159
  fail "You should provide a proper type."
159
160
  end
160
161
 
161
- post("/r/#{display_name}/api/flair", text: text, css_class: css_class)
162
+ post("/r/#{display_name}/api/flair", params)
162
163
  end
163
164
 
164
165
  # @!endgroup
@@ -282,16 +283,16 @@ module Redd
282
283
  else
283
284
  about = admin_about
284
285
  final = about
285
- .select { |k, _| required.include?(k) }
286
- .merge(
287
- name: display_name,
288
- type: about[:subreddit_type],
289
- lang: about[:language],
290
- link_type: about[:content_options],
291
- allow_top: true,
292
- css_on_cname: true
293
- )
294
- .merge(attributes)
286
+ .select { |k, _| required.include?(k) }
287
+ .merge(
288
+ name: display_name,
289
+ type: about[:subreddit_type],
290
+ lang: about[:language],
291
+ link_type: about[:content_options],
292
+ allow_top: true,
293
+ css_on_cname: true
294
+ )
295
+ .merge(attributes)
295
296
  params.merge!(final)
296
297
  end
297
298
 
@@ -1,50 +1,88 @@
1
1
  # The main Redd module.
2
2
  module Redd
3
- # The class that handles rate limiting for reddit. reddit does supply
4
- # X-Ratelimit headers but using those headers instead would just lead to
5
- # short bursts, so it's better to go at a constant speed and space out
6
- # requests every second.
3
+ # The class that handles rate limiting for reddit.
7
4
  #
8
- # If you'd rather have short bursts or no rate limiting at all, it's easy to
5
+ # If you'd rather have an asynchronous or queue-based limiting, it's easy to
9
6
  # write one yourself. A rate limiting class is any class that has an
10
7
  # {#after_limit} method. The block returns a Faraday::Response object, so you
11
8
  # can also extract the headers from the response and use those instead. To
12
9
  # remove rate limiting entirely, follow the example below.
13
10
  #
14
- # @example No Rate Limiting
15
- # class IWantToGetIPBanned
16
- # def after_limit
17
- # yield
18
- # end
19
- # end
20
- #
21
- # client = Redd.it(..., rate_limit: IWantToGetIPBanned.new)
11
+ # @example To remove rate limiting entirely, just burst forever.
12
+ # rt = Redd::RateLimit.new
13
+ # rt.burst!(Float::INFINITY)
22
14
  class RateLimit
23
- # @!attribute [r] last_request_time
24
- # @return [Time] The time when the last request took place.
25
- attr_reader :last_request_time
26
-
27
15
  # @!attribute [rw] gap
28
16
  # @return [Integer, Float] The minimum time between requests.
29
17
  attr_accessor :gap
30
18
 
19
+ # @!attribute [rw] burst_length
20
+ # @return [Integer] The number of requests left to burst.
21
+ attr_accessor :burst_length
22
+
23
+ # @!attribute [r] last_request
24
+ # @return [Time] The time the last request was made.
25
+ attr_reader :last_request
26
+
27
+ # @!attribute [r] used
28
+ # @!attribute [r] remaining
29
+ # @!attribute [r] reset
30
+ # @return [Integer] The data from reddit's response headers.
31
+ attr_reader :used, :remaining, :reset
32
+
31
33
  # @param [Float, Integer] gap The minimum time between each request.
32
34
  def initialize(gap)
33
35
  # Some time ages ago, because we never made a request.
34
- @last_request_time = Time.at(0)
36
+ @last_request = Time.at(0)
35
37
  @gap = gap
38
+ @burst_length = 0
39
+ end
40
+
41
+ # Don't sleep for the next few requests.
42
+ # @param [Integer] times The number of times to ignore limiting.
43
+ # @return [Integer] The total times rate limiting will be ignored.
44
+ def burst!(times)
45
+ @burst_length += times
36
46
  end
37
47
 
38
- # Sleep until 2 seconds have passed since the last request and perform the
39
- # given request.
48
+ # Sleep until 1 second has passed since the last request and perform the
49
+ # given request unless bursting.
40
50
  #
41
- # @yield A block.
42
- # @return The return value of the block.
51
+ # @yield [Faraday::Response] A response.
52
+ # @return [Faraday::Response] The response.
43
53
  def after_limit
44
- wait_time = @last_request_time + @gap - Time.now
45
- sleep(wait_time) if wait_time > 0
46
- @last_request_time = Time.now
47
- yield
54
+ response = yield
55
+ update!(response)
56
+ sleep(wait_time)
57
+ response
58
+ end
59
+
60
+ private
61
+
62
+ # Update necessary info with each request.
63
+ # @param [Faraday::Response] response The response to the request made.
64
+ def update!(response)
65
+ @last_request = Time.now
66
+ %w(used remaining reset).each do |type|
67
+ value = response.headers["x-ratelimit-#{type}"]
68
+ instance_variable_set("@#{type}", value.to_i) unless value.nil?
69
+ end
70
+ end
71
+
72
+ # @return [Float, Integer] The number of seconds to sleep.
73
+ def wait_time
74
+ if @burst_length > 0 && @remaining > 0
75
+ # Don't sleep if we are in burst mode.
76
+ @burst_length -= 1
77
+ 0
78
+ elsif @reset.nil? || @remaining.nil?
79
+ # Just guess if no headers were given (max 1 sec after last request).
80
+ time = @last_request_time - Time.now + @gap
81
+ time > 0 ? time : 0
82
+ else
83
+ # Most cases, spread out requests over available time.
84
+ @reset.to_f / (@gap * @remaining + 1)
85
+ end
48
86
  end
49
87
  end
50
88
  end
data/lib/redd/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Redd # rubocop:disable Style/Documentation
2
2
  # The semantic version number.
3
- VERSION = "0.7.5"
3
+ VERSION = "0.7.6"
4
4
  end
data/redd.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.8.1"
21
+ spec.add_development_dependency "bundler", "~> 1.9.4"
22
22
  spec.add_development_dependency "rake", "~> 10.4.2"
23
23
  spec.add_development_dependency "rspec", "~> 3.2.0"
24
24
  spec.add_development_dependency "vcr", "~> 2.9.3"
data/spec/redd_spec.rb CHANGED
@@ -1,5 +1,3 @@
1
- require "redd/version"
2
-
3
1
  RSpec.describe Redd do
4
2
  it "has a version number" do
5
3
  expect(Redd::VERSION).to be_a(String)
data/spec/spec_helper.rb CHANGED
@@ -40,6 +40,8 @@ RSpec.configure do |config|
40
40
  config.filter_run_including :focus
41
41
  config.run_all_when_everything_filtered = true
42
42
 
43
+ # If we don't have the details to perform authentication, we can't do those
44
+ # tests.
43
45
  if ENV["TRAVIS_SECURE_ENV_VARS"] == "false"
44
46
  config.filter_run_excluding :secure
45
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avinash Dwarapu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-19 00:00:00.000000000 Z
11
+ date: 2015-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.8.1
19
+ version: 1.9.4
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.8.1
26
+ version: 1.9.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,6 @@ files:
194
194
  - lib/redd/version.rb
195
195
  - redd.gemspec
196
196
  - spec/redd/objects/base_spec.rb
197
- - spec/redd/rate_limit_spec.rb
198
197
  - spec/redd/response/parse_json_spec.rb
199
198
  - spec/redd/response/raise_error_spec.rb
200
199
  - spec/redd_spec.rb
@@ -219,15 +218,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
218
  version: '0'
220
219
  requirements: []
221
220
  rubyforge_project:
222
- rubygems_version: 2.2.2
221
+ rubygems_version: 2.4.5
223
222
  signing_key:
224
223
  specification_version: 4
225
224
  summary: A Reddit API Wrapper for Ruby.
226
225
  test_files:
227
226
  - spec/redd/objects/base_spec.rb
228
- - spec/redd/rate_limit_spec.rb
229
227
  - spec/redd/response/parse_json_spec.rb
230
228
  - spec/redd/response/raise_error_spec.rb
231
229
  - spec/redd_spec.rb
232
230
  - spec/spec_helper.rb
233
- has_rdoc:
@@ -1,29 +0,0 @@
1
- RSpec.describe Redd::RateLimit do
2
- let(:rate_limit) { Redd::RateLimit.new(2) }
3
-
4
- it "waits two seconds between consecutive requests" do
5
- rate_limit.after_limit {}
6
- start_time = Time.now
7
- rate_limit.after_limit {}
8
- end_time = Time.now
9
-
10
- expect(end_time - start_time).to be_within(0.1).of(2)
11
- end
12
-
13
- it "doesn't wait if two seconds have passed since last request" do
14
- rate_limit.after_limit {}
15
- sleep(2)
16
- start_time = Time.now
17
- rate_limit.after_limit {}
18
- end_time = Time.now
19
-
20
- expect(end_time - start_time).to be_within(0.1).of(0)
21
- end
22
-
23
- it "stores the time the last request was made" do
24
- time = Time.now
25
- rate_limit.after_limit {}
26
-
27
- expect(rate_limit.last_request_time).to be_within(0.1).of(time)
28
- end
29
- end