redd 0.7.5 → 0.7.6

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
  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