redd 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -12
  3. data/lib/redd.rb +0 -12
  4. data/lib/redd/base.rb +10 -6
  5. data/lib/redd/client/authenticated.rb +2 -1
  6. data/lib/redd/client/authenticated/account.rb +2 -0
  7. data/lib/redd/client/authenticated/apps.rb +1 -0
  8. data/lib/redd/client/authenticated/flair.rb +33 -7
  9. data/lib/redd/client/authenticated/gold.rb +1 -0
  10. data/lib/redd/client/authenticated/links_comments.rb +86 -10
  11. data/lib/redd/client/authenticated/live.rb +1 -0
  12. data/lib/redd/client/authenticated/moderation.rb +65 -16
  13. data/lib/redd/client/authenticated/multis.rb +1 -1
  14. data/lib/redd/client/authenticated/private_messages.rb +50 -4
  15. data/lib/redd/client/authenticated/subreddits.rb +28 -0
  16. data/lib/redd/client/authenticated/users.rb +1 -1
  17. data/lib/redd/client/authenticated/wiki.rb +1 -1
  18. data/lib/redd/client/oauth2.rb +2 -2
  19. data/lib/redd/client/oauth2/authorization.rb +44 -11
  20. data/lib/redd/client/oauth2/identity.rb +4 -0
  21. data/lib/redd/client/unauthenticated/account.rb +13 -1
  22. data/lib/redd/client/unauthenticated/captcha.rb +7 -0
  23. data/lib/redd/client/unauthenticated/links_comments.rb +23 -4
  24. data/lib/redd/client/unauthenticated/listing.rb +43 -25
  25. data/lib/redd/client/unauthenticated/live.rb +1 -0
  26. data/lib/redd/client/unauthenticated/moderation.rb +9 -1
  27. data/lib/redd/client/unauthenticated/subreddits.rb +30 -0
  28. data/lib/redd/client/unauthenticated/utilities.rb +7 -4
  29. data/lib/redd/client/unauthenticated/wiki.rb +18 -4
  30. data/lib/redd/error.rb +5 -3
  31. data/lib/redd/oauth2_access.rb +21 -3
  32. data/lib/redd/object/more_comments.rb +1 -0
  33. data/lib/redd/object/private_message.rb +2 -1
  34. data/lib/redd/object/submission.rb +4 -0
  35. data/lib/redd/object/user.rb +1 -0
  36. data/lib/redd/response/raise_error.rb +2 -1
  37. data/lib/redd/thing/editable.rb +1 -0
  38. data/lib/redd/thing/hideable.rb +1 -0
  39. data/lib/redd/thing/inboxable.rb +1 -0
  40. data/lib/redd/thing/messageable.rb +2 -8
  41. data/lib/redd/thing/moderatable.rb +1 -0
  42. data/lib/redd/thing/reportable.rb +1 -0
  43. data/lib/redd/thing/saveable.rb +1 -0
  44. data/lib/redd/thing/voteable.rb +1 -1
  45. data/lib/redd/version.rb +1 -1
  46. data/spec/redd/client/unauthenticated_spec.rb +1 -1
  47. data/spec/redd/rate_limit_spec.rb +5 -5
  48. data/spec/redd_spec.rb +1 -1
  49. data/spec/spec_helper.rb +1 -1
  50. metadata +2 -3
  51. data/github/redd.png +0 -0
@@ -1,6 +1,7 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods to interact with /r/live threads
4
5
  module Live
5
6
  end
6
7
  end
@@ -1,14 +1,22 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods that deal with subreddit styles
4
5
  module Moderation
6
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
7
+ # query.
8
+ # @return [String] The url for the subreddit's css stylesheet.
5
9
  def stylesheet_url(subreddit = nil)
10
+ name = extract_attribute(subreddit, :display_name)
6
11
  path = "/stylesheet"
7
- path = path.prepend("/r/#{subreddit}") if subreddit
12
+ path = path.prepend("/r/#{name}") if subreddit
8
13
 
9
14
  get(path).headers[:location]
10
15
  end
11
16
 
17
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
18
+ # query.
19
+ # @return [String] The css stylesheet for the subreddit.
12
20
  def stylesheet(subreddit = nil)
13
21
  get stylesheet_url(subreddit)
14
22
  end
@@ -1,15 +1,45 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods that deal with subreddits
4
5
  module Subreddits
6
+ # Return a Subreddit object from the title of a subreddit.
7
+ # @param title [String] The name of the subreddit.
8
+ # @return [Redd::Object::Subreddit]
5
9
  def subreddit(title)
6
10
  object_from_response :get, "/r/#{title}/about.json"
7
11
  end
8
12
 
13
+ # Get a list of subreddits sorted by the given parameter.
14
+ # @param where [:subscriber, :contributor, :moderator, :popular, :new]
15
+ # The type of subreddits to look for.
16
+ # @param params [Hash] A hash of parameters to send with the request.
17
+ # @option params [String] :after Return results after the given
18
+ # fullname.
19
+ # @option params [String] :before Return results before the given
20
+ # fullname.
21
+ # @option params [Integer] :count (0) The number of items already seen
22
+ # in the listing.
23
+ # @option params [1..100] :limit (25) The maximum number of things to
24
+ # return.
25
+ # @return [Redd::Object::Listing] A listing of subreddits.
9
26
  def get_subreddits(where = :popular, params = {})
10
27
  object_from_response :get, "/subreddits/#{where}.json", params
11
28
  end
12
29
 
30
+ # Look for subreddits matching the given query.
31
+ #
32
+ # @param query [String] The search query.
33
+ # @param params [Hash] A hash of parameters to send with the request.
34
+ # @option params [String] :after Return results after the given
35
+ # fullname.
36
+ # @option params [String] :before Return results before the given
37
+ # fullname.
38
+ # @option params [Integer] :count (0) The number of items already seen
39
+ # in the listing.
40
+ # @option params [1..100] :limit (25) The maximum number of things to
41
+ # return.
42
+ # @return [Redd::Object::Listing] A listing of subreddits.
13
43
  def search_subreddits(query, params = {})
14
44
  params << {q: query}
15
45
  object_from_response :get, "/subreddits/search.json", params
@@ -11,6 +11,7 @@ require "redd/object/wiki_page"
11
11
  module Redd
12
12
  module Client
13
13
  class Unauthenticated
14
+ # Non-API methods that make life easier
14
15
  module Utilities
15
16
  def comment_stream(*args, &block)
16
17
  submission_stream(:comments, *args, &block)
@@ -23,7 +24,7 @@ module Redd
23
24
  objects = get_listing(listing, subreddit, params)
24
25
  unless objects.empty?
25
26
  # Run the loop for each of the new comments accessed.
26
- # I should probably add it to some sort of Set to avoid duplicates.
27
+ # I should probably add it to a Set to avoid duplicates.
27
28
  objects.reverse_each { |object| block.call(object) }
28
29
  # Set the latest comment.
29
30
  params[:before] = objects.first.fullname
@@ -38,7 +39,7 @@ module Redd
38
39
  when ::String
39
40
  object
40
41
  else
41
- object.send(attribute)
42
+ object.send(attribute)
42
43
  end
43
44
  end
44
45
 
@@ -50,7 +51,8 @@ module Redd
50
51
  extract_attribute(object, :id)
51
52
  end
52
53
 
53
- def object_from_kind(kind) # rubocop:disable Style/MethodLength
54
+ # rubocop:disable Style/MethodLength, Style/CyclomaticComplexity
55
+ def object_from_kind(kind)
54
56
  case kind
55
57
  when "Listing"
56
58
  Redd::Object::Listing
@@ -72,6 +74,7 @@ module Redd
72
74
  Redd::Thing
73
75
  end
74
76
  end
77
+ # rubocop:enable Style/MethodLength, Style/CyclomaticComplexity
75
78
 
76
79
  def objects_from_listing(thing)
77
80
  thing[:data][:children].map do |child|
@@ -80,7 +83,7 @@ module Redd
80
83
  end
81
84
 
82
85
  def object_from_body(body)
83
- return nil unless body.is_a?(Hash) && body.has_key?(:kind)
86
+ return nil unless body.is_a?(Hash) && body.key?(:kind)
84
87
  object = object_from_kind(body[:kind])
85
88
 
86
89
  if object == Redd::Object::Listing
@@ -1,17 +1,31 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods to interact with subreddit wikis
4
5
  module Wiki
6
+ # Get a list of pages in the subreddit wiki.
7
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
8
+ # look in.
9
+ # @return [Array] An array of wikipage titles.
5
10
  def get_wikipages(subreddit = nil)
11
+ name = extract_attribute(subreddit, :display_name)
12
+
6
13
  path = "/wiki/pages.json"
7
- path.prepend("/r/#{subreddit}") if subreddit
14
+ path.prepend("/r/#{name}") if subreddit
8
15
  get(path)[:data]
9
16
  end
10
17
 
11
- def wikipage(page, subreddit = nil, params = {})
18
+ # Get a wiki page.
19
+ # @param page [String] The title of the wiki page.
20
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
21
+ # look in.
22
+ # @return [Redd::Object::WikiPage] A wiki page.
23
+ def wikipage(page, subreddit = nil)
24
+ name = extract_attribute(subreddit, :display_name)
25
+
12
26
  path = "/wiki/#{page}.json"
13
- path.prepend("/r/#{subreddit}") if subreddit
14
- object_from_response :get, path, params
27
+ path.prepend("/r/#{name}") if subreddit
28
+ object_from_response :get, path
15
29
  end
16
30
  end
17
31
  end
@@ -1,6 +1,6 @@
1
1
  module Redd
2
+ # An error from reddit
2
3
  class Error < StandardError
3
-
4
4
  attr_reader :code
5
5
  attr_reader :headers
6
6
  attr_reader :body
@@ -12,8 +12,8 @@ module Redd
12
12
  end
13
13
 
14
14
  class << self
15
- # @note I ripped off RedditKit.rb :|
16
- def from_response(response) # rubocop:disable Style/CyclomaticComplexity Style/MethodLength
15
+ # rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
16
+ def from_response(response)
17
17
  status = response[:status]
18
18
  body = parse_error(response[:body]).to_s
19
19
  case status
@@ -57,6 +57,7 @@ module Redd
57
57
  Redd::Error::TimedOut
58
58
  end
59
59
  end
60
+ # rubocop:enable Style/CyclomaticComplexity, Style/MethodLength
60
61
 
61
62
  def parse_error(body)
62
63
  return nil unless body.is_a?(Hash)
@@ -89,6 +90,7 @@ module Redd
89
90
 
90
91
  class PermissionDenied < Error; end
91
92
 
93
+ # Raised when the client needs to wait before making another request
92
94
  class RateLimited < Error
93
95
  attr_reader :time
94
96
 
@@ -1,17 +1,29 @@
1
1
  require "multi_json"
2
2
 
3
3
  module Redd
4
+ # A container for the client's access to their account via OAuth2
4
5
  class OAuth2Access
6
+ # @!attribute [r] access_token
7
+ # @return [String] The access token used to access the users account.
5
8
  attr_reader :access_token
6
9
 
10
+ # @!attribute [r] refresh_token
11
+ # @return [String, nil] The refresh token, if the access was permanent.
7
12
  attr_reader :refresh_token
8
13
 
14
+ # @!attribute [r] scope
15
+ # @return [Array] The scope that the client is allowed to access.
9
16
  attr_reader :scope
10
17
 
18
+ # @!attribute [r] duration
19
+ # @return [Symbol] Time the client is given access (temporary/permanent)
11
20
  attr_reader :duration
12
21
 
22
+ # @!attribute [r] expires_at
23
+ # @return [Time] The time when the access token expires.
13
24
  attr_reader :expires_at
14
25
 
26
+ # @param response [String] The response body containing the required info.
15
27
  def initialize(response)
16
28
  @access_token = response[:access_token]
17
29
  @refresh_token = response[:refresh_token]
@@ -20,21 +32,25 @@ module Redd
20
32
  @expires_at =
21
33
  if response[:expires_at]
22
34
  Time.at(response[:expires_at])
23
- else
35
+ else
24
36
  Time.now + response[:expires_in]
25
37
  end
26
38
  end
27
39
 
40
+ # Refresh the object with the new response.
41
+ # This happens when a new access token is requested using a request token.
42
+ # @param response [Hash] The new response body.
28
43
  def refresh(response)
29
44
  @access_token = response[:access_token]
30
45
  @expires_at = Time.now + response[:expires_in]
31
- self
32
46
  end
33
47
 
48
+ # @return [Boolean] Whether the access has expired.
34
49
  def expired?
35
50
  Time.now > @expires_at
36
51
  end
37
52
 
53
+ # @return [String] A JSON representation of the data that can be loaded later.
38
54
  def to_json
39
55
  MultiJson.dump(
40
56
  access_token: @access_token,
@@ -44,9 +60,11 @@ module Redd
44
60
  )
45
61
  end
46
62
 
63
+ # Create a new instance of the class from the JSON returned from #to_json
64
+ # @return [OAuth2Access]
47
65
  def self.from_json(json)
48
66
  hash = MultiJson.load(json, symbolize_keys: true)
49
67
  new(hash)
50
68
  end
51
69
  end
52
- end
70
+ end
@@ -1,5 +1,6 @@
1
1
  module Redd
2
2
  module Object
3
+ # The model for a morecomments object
3
4
  class MoreComments < Redd::Base
4
5
  attr_reader :count
5
6
  attr_reader :parent_id
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  module Object
5
+ # The model for private messages
5
6
  class PrivateMessage < Redd::Thing
6
7
  require "redd/thing/inboxable"
7
8
 
@@ -20,7 +21,7 @@ module Redd
20
21
  attr_reader :author
21
22
 
22
23
  alias_method :from, :author
23
- alias_method :to, :author
24
+ alias_method :to, :dest
24
25
 
25
26
  def created
26
27
  @created ||= Time.at(@attributes[:created_utc])
@@ -60,6 +60,10 @@ module Redd
60
60
  alias_method :self?, :is_self
61
61
  alias_method :comments_count, :num_comments
62
62
 
63
+ def subreddit_name
64
+ @subreddit_name ||= @attributes[:subreddit]
65
+ end
66
+
63
67
  def subreddit
64
68
  @subreddit ||= client.subreddit(@attributes[:subreddit])
65
69
  end
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  module Object
5
+ # The model for a reddit user
5
6
  class User < Redd::Thing
6
7
  require "redd/thing/messageable"
7
8
 
@@ -8,7 +8,8 @@ module Redd
8
8
  # @param faraday
9
9
  def call(faraday)
10
10
  @app.call(faraday).on_complete do |env|
11
- if error = Redd::Error.from_response(env)
11
+ error = Redd::Error.from_response(env)
12
+ if error
12
13
  if error == Redd::Error::RateLimited
13
14
  time = env.body[:json][:ratelimit]
14
15
  fail error.new(env, time)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be edited
5
6
  module Editable
6
7
  def delete
7
8
  client.delete(self)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be hidden
5
6
  module Hideable
6
7
  def hide
7
8
  client.hide(self)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be added to one's inbox
5
6
  module Inboxable
6
7
  def mark_as_read
7
8
  client.mark_as_read(self)
@@ -2,16 +2,10 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be sent a message
5
6
  module Messageable
6
7
  def send_message(subject, text, captcha = nil, identifier = nil)
7
- to = case self
8
- when Redd::Object::Subreddit
9
- "/r/" + display_name
10
- when Redd::Object::User
11
- name
12
- end
13
-
14
- client.send_message(to, subject, text, captcha, identifier)
8
+ client.send_message(self, subject, text, captcha, identifier)
15
9
  end
16
10
  end
17
11
  end
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be moderated
5
6
  module Moderatable
6
7
  def approve
7
8
  client.approve(self)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be reported to the mods
5
6
  module Reportable
6
7
  def report
7
8
  client.report(self)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be saved
5
6
  module Saveable
6
7
  def save(category = nil)
7
8
  client.save(self, category)
@@ -2,6 +2,7 @@ require "redd/thing"
2
2
 
3
3
  module Redd
4
4
  class Thing
5
+ # A Redd::Object that can be voted on
5
6
  module Voteable
6
7
  def upvote
7
8
  client.upvote(self)
@@ -16,7 +17,6 @@ module Redd
16
17
  end
17
18
 
18
19
  alias_method :clear_vote, :unvote
19
-
20
20
  end
21
21
  end
22
22
  end
@@ -1,5 +1,5 @@
1
1
  # The main Redd module.
2
2
  module Redd
3
3
  # The semantic version number for Redd.
4
- VERSION = "0.4.3"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -12,4 +12,4 @@ describe Redd::Client::Unauthenticated, :vcr do
12
12
  expect(newclient.user_agent).to eq("SPEC_USERAGENT")
13
13
  expect(newclient.api_endpoint).to eq("SPEC_ENDPOINT.COM")
14
14
  end
15
- end
15
+ end
@@ -2,19 +2,19 @@ describe Redd::RateLimit do
2
2
  let(:rate_limit) { Redd::RateLimit.new }
3
3
 
4
4
  it "waits two seconds between consecutive requests" do
5
- rate_limit.after_limit { }
5
+ rate_limit.after_limit {}
6
6
  start_time = Time.now
7
- rate_limit.after_limit { }
7
+ rate_limit.after_limit {}
8
8
  end_time = Time.now
9
9
 
10
10
  expect(end_time - start_time).to be_within(0.1).of(2)
11
11
  end
12
12
 
13
13
  it "doesn't wait if two seconds have passed since last request" do
14
- rate_limit.after_limit { }
14
+ rate_limit.after_limit {}
15
15
  sleep(2)
16
16
  start_time = Time.now
17
- rate_limit.after_limit { }
17
+ rate_limit.after_limit {}
18
18
  end_time = Time.now
19
19
 
20
20
  expect(end_time - start_time).to be_within(0.1).of(0)
@@ -22,7 +22,7 @@ describe Redd::RateLimit do
22
22
 
23
23
  it "stores the time the last request was made" do
24
24
  time = Time.now
25
- rate_limit.after_limit { }
25
+ rate_limit.after_limit {}
26
26
 
27
27
  expect(rate_limit.last_request_time).to be_within(0.1).of(time)
28
28
  end