redd 0.4.3 → 0.5.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.
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,8 +1,8 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Authenticated
4
+ # Methods to interact with multis (groups of subreddits).
4
5
  module Multis
5
-
6
6
  end
7
7
  end
8
8
  end
@@ -1,32 +1,78 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Authenticated
4
+ # Methods for sending and reading private messages
4
5
  module PrivateMessages
6
+ # Block the sender of the message from sending any more.
7
+ #
8
+ # @param message [Redd::Object::PrivateMessage, String] The message
9
+ # whose sender to block.
5
10
  def block_message(message)
6
11
  fullname = extract_fullname(message)
7
12
  post "/api/block", id: fullname
8
13
  end
9
14
 
15
+ # Compose a message to a person or the moderators of a subreddit.
16
+ #
17
+ # @param to [Redd::Object::User, Redd::Object::Subreddit, String] The
18
+ # thing to send a message to.
19
+ # @param subject [String] The subject of the message.
20
+ # @param text [String] The message text.
21
+ # @param captcha [String] A possible captcha result to send if one
22
+ # is required.
23
+ # @param identifier [String] The identifier for the captcha if one
24
+ # is required.
10
25
  def compose_message(to, subject, text, captcha = nil, identifier = nil)
11
- params = {
12
- api_type: "json", to: to.to_s, subject: subject, text: text
13
- }
26
+ params[:to] =
27
+ case to
28
+ when Redd::Object::User
29
+ to.name
30
+ when Redd::Object::Subreddit
31
+ to.display_name
32
+ when String
33
+ to
34
+ end
35
+
36
+ params = {api_type: "json", subject: subject, text: text}
14
37
  params << {captcha: captcha, iden: identifier} if captcha
15
38
 
16
39
  post "/api/compose", params
17
40
  end
18
41
 
42
+ # Mark a message as read.
43
+ #
44
+ # @param message [Redd::Object::PrivateMessage, String] The message
45
+ # to mark as read.
19
46
  def mark_as_read(message)
20
47
  fullname = extract_fullname(message)
21
48
  post "/api/read_message", id: fullname
22
49
  end
23
50
 
51
+ # Mark a message as unread.
52
+ #
53
+ # @param message [Redd::Object::PrivateMessage, String] The message
54
+ # to mark as unread.
24
55
  def mark_as_unread(message)
25
56
  fullname = extract_fullname(message)
26
57
  post "/api/unread_message", id: fullname
27
58
  end
28
59
 
29
- def messages(category = "inbox", params = {})
60
+ # Return a list of a user's private messages.
61
+ #
62
+ # @param category [String] The category of messages to view.
63
+ # @param mark [Boolean] Whether to remove the orangered from the
64
+ # user's inbox.
65
+ # @param params [Hash] A list of params to send with the request.
66
+ # @option params [String] :after Return results after the given
67
+ # fullname.
68
+ # @option params [String] :before Return results before the given
69
+ # fullname.
70
+ # @option params [Integer] :count (0) The number of items already seen
71
+ # in the listing.
72
+ # @option params [1..100] :limit (25) The maximum number of things to
73
+ # return.
74
+ def messages(category = "inbox", mark = false, params = {})
75
+ params[:mark] = mark
30
76
  object_from_response :get, "/message/#{category}.json", params
31
77
  end
32
78
  end
@@ -1,15 +1,38 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Authenticated
4
+ # Methods to interact with subreddits
4
5
  module Subreddits
6
+ # Subscribe to a subreddit.
7
+ #
8
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
9
+ # subscribe to.
5
10
  def subscribe(subreddit)
6
11
  edit_subscription(:sub, subreddit)
7
12
  end
8
13
 
14
+ # Unsubscribe from a subreddit.
15
+ #
16
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
17
+ # unsubscribe from.
9
18
  def unsubscribe(subreddit)
10
19
  edit_subscription(:unsub, subreddit)
11
20
  end
12
21
 
22
+ # Get a listing of subreddits.
23
+ #
24
+ # @param where [:popular, :new, :subscriber, :contributor, :moderator]
25
+ # The order of subreddits to return.
26
+ # @param params [Hash] A list of params to send with the request.
27
+ # @option params [String] :after Return results after the given
28
+ # fullname.
29
+ # @option params [String] :before Return results before the given
30
+ # fullname.
31
+ # @option params [Integer] :count (0) The number of items already seen
32
+ # in the listing.
33
+ # @option params [1..100] :limit (25) The maximum number of things to
34
+ # return.
35
+ # @return [Redd::Object::Listing] A listing of subreddits.
13
36
  def get_subreddits(where = :subscriber, params = {})
14
37
  path =
15
38
  if [:popular, :new].include?(where)
@@ -22,6 +45,11 @@ module Redd
22
45
 
23
46
  private
24
47
 
48
+ # Subscribe or unsubscribe to a subreddit.
49
+ #
50
+ # @param action [:sub, :unsub] The type of action to perform.
51
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
52
+ # perform the action on.
25
53
  def edit_subscription(action, subreddit)
26
54
  fullname = extract_fullname(subreddit)
27
55
  post "/api/subscribe", action: action, sr: fullname
@@ -1,8 +1,8 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Authenticated
4
+ # Methods to interact with other users
4
5
  module Users
5
-
6
6
  end
7
7
  end
8
8
  end
@@ -1,8 +1,8 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Authenticated
4
+ # Methods to interact with wiki pages
4
5
  module Wiki
5
-
6
6
  end
7
7
  end
8
8
  end
@@ -44,14 +44,14 @@ module Redd
44
44
 
45
45
  private
46
46
 
47
- def connection(access_token = @access.access_token)
47
+ def connection
48
48
  @connection ||= Faraday.new(url: api_endpoint) do |faraday|
49
49
  faraday.use Faraday::Request::UrlEncoded
50
50
  faraday.use Redd::Response::RaiseError
51
51
  faraday.use Redd::Response::ParseJson
52
52
  faraday.adapter Faraday.default_adapter
53
53
 
54
- faraday.headers["Authorization"] = "bearer #{access_token}"
54
+ faraday.headers["Authorization"] = "bearer #{@access.access_token}"
55
55
  faraday.headers["User-Agent"] = "Redd/Ruby, v#{Redd::VERSION}"
56
56
  end
57
57
  end
@@ -3,40 +3,73 @@ require "redd/oauth2_access"
3
3
  module Redd
4
4
  module Client
5
5
  class OAuth2
6
+ # Methods for obtaining an access token
6
7
  module Authorization
7
- def auth_url(scope = ["identity"], duration = "temporary", state = "x")
8
+ # Build an authorization url to redirect the user to.
9
+ #
10
+ # @param scopes [Array<String>] The access scopes to request from the
11
+ # user.
12
+ # @param duration [:temporary, :permanent] The duration of your access
13
+ # to the user's account.
14
+ # @param state [String] A random string to check later.
15
+ # @return [String] The url.
16
+ #
17
+ # @note The access tokens from both duration last only an hour, but you
18
+ # also get a refresh token when the duration is permanent.
19
+ # @note You may be tempted to let the state remain "x", but seriously,
20
+ # use this; it helps prevent against CSRF attacks.
21
+ def auth_url(scopes = ["identity"], duration = :temporary, state = "x")
8
22
  path = "https://ssl.reddit.com/api/v1/authorize"
23
+ scope = scopes.is_a?(Array) ? scopes.join(",") : scopes
9
24
  query = {
10
25
  client_id: @client_id,
11
26
  redirect_uri: @redirect_uri,
12
27
  response_type: "code",
13
28
  state: state,
14
- scope: scope.join(","),
29
+ scope: scope,
15
30
  duration: duration
16
31
  }
17
32
  string_query = query.map { |key, value| "#{key}=#{value}" }.join("&")
18
-
19
33
  "#{path}?#{string_query}"
20
34
  end
21
35
 
22
- def request_access_token(code, set_access = true)
36
+ # Request an access token from the code that is sent with the redirect.
37
+ #
38
+ # @param code [String] The code that was sent in the GET request.
39
+ # @param set_access [Boolean] Whether to automatically use this token
40
+ # for all future requests with this client.
41
+ # @return [Redd::OAuth2Access] A package of the necessary information
42
+ # to access the user's information.
43
+ def request_access(code, set_access = true)
23
44
  response = auth_connection.post "/api/v1/access_token",
24
- grant_type: "authorization_code", code: code,
25
- redirect_uri: @redirect_uri
45
+ grant_type: "authorization_code",
46
+ code: code,
47
+ redirect_uri: @redirect_uri
26
48
 
27
49
  access = Redd::OAuth2Access.new(response.body)
28
50
  @access = access if set_access
29
51
  access
30
52
  end
31
53
 
32
- def refresh_access_token(access = nil, set_access = true)
33
- refresh_token = extract_attribute(access, :refresh_token)
54
+ # Obtain a new access token using a refresh token.
55
+ #
56
+ # @param token [Redd::OAuth2Access, String, nil] The refresh token or
57
+ # OAuth2Access. If none is provided, it'll refresh the one the client
58
+ # is currently using.
59
+ # @param set_access [Boolean] Whether to automatically use this token
60
+ # for all future requests with this client.
61
+ # @return [Redd::OAuth2Access] The refreshed information.
62
+ def refresh_access(token = nil, set_access = true)
63
+ refresh_token = extract_attribute(token, :refresh_token)
34
64
  response = auth_connection.post "/api/v1/access_token",
35
- grant_type: "refresh_token", refresh_token: refresh_token
65
+ grant_type: "refresh_token",
66
+ refresh_token: refresh_token
36
67
 
37
- case access
38
- when Redd::OAuth2Access
68
+ case token
69
+ when nil
39
70
  access.refresh(response.body)
71
+ when Redd::OAuth2Access
72
+ token.refresh(response.body)
40
73
  when ::String
41
74
  new_access = Redd::OAuth2Access.new(response.body)
42
75
  @access = new_access if set_access
@@ -1,7 +1,11 @@
1
1
  module Redd
2
2
  module Client
3
3
  class OAuth2
4
+ # Methods to interact with the user logged-in via OAuth2
4
5
  module Identity
6
+ # @return [Redd::Object::User] The logged-in user.
7
+ # @note This overrides the Authenticated class's method, since that
8
+ # method doesn't apply here but does the same thing.
5
9
  def me
6
10
  response = get "/api/v1/me.json"
7
11
  object_from_body kind: "t2", data: response
@@ -1,10 +1,22 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods for managing accounts.
4
5
  module Account
6
+ # Login to the reddit account.
7
+ #
8
+ # @param username [String] The username.
9
+ # @param password [String] The password.
10
+ # @param remember [Boolean] Indicates whether you intend to use the
11
+ # returned cookie for a long time.
12
+ # @param options [Hash] The options to create an instance of
13
+ # {Redd::Client::Authenticated}.
5
14
  def login(username, password, remember = false, options = {})
6
15
  response = post "/api/login",
7
- api_type: "json", user: username, passwd: password, rem: remember
16
+ api_type: "json",
17
+ user: username,
18
+ passwd: password,
19
+ rem: remember
8
20
  data = response[:json][:data]
9
21
 
10
22
  require "redd/client/authenticated"
@@ -1,16 +1,23 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods to get captchas.
5
+ # Many things like sending messages and posting links require captchas.
4
6
  module Captcha
7
+ # @return [Boolean] Whether a captcha is required for some API methods.
5
8
  def needs_captcha?
6
9
  get "/api/needs_captcha.json"
7
10
  end
8
11
 
12
+ # Create a new captcha identifier.
13
+ # @return [String] The identifier.
9
14
  def new_captcha
10
15
  response = get "/api/new_captcha", api_type: "json"
11
16
  response[:json][:data][:iden]
12
17
  end
13
18
 
19
+ # @param identifier [String] The captcha identifier.
20
+ # @return The url for the captcha image.
14
21
  def captcha_url(identifier)
15
22
  "http://www.reddit.com/captcha/#{identifier}.png"
16
23
  end
@@ -2,20 +2,37 @@ module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
4
  module LinksComments
5
+ # @param params [Hash] A hash of parameters to send to reddit.
6
+ # @option params [String] :id The fullname of a thing.
7
+ # @option params [String] :url The url of a thing. If an id is also
8
+ # provided, the id will take precedence.
9
+ # @return [Redd::Object::Submission, Redd::Object::Comment] The object.
10
+ #
5
11
  # @note Reddit does accept a subreddit, but with fullnames and urls, I
6
12
  # assumed that was unnecessary.
7
13
  def get_info(params = {})
8
- object_from_response :get, "/api/info.json", params
14
+ object = object_from_response :get, "/api/info.json", params
15
+ object.first
9
16
  end
10
17
 
18
+ # Get the comments for a submission.
19
+ #
20
+ # @param submission [String, Redd::Object::Submission] The submission
21
+ # to get the comments for.
22
+ # @return [Redd::Object::Listing] A listing of comments.
11
23
  def submission_comments(submission)
12
24
  id = extract_id(submission)
13
25
  comments_from_response :get, "/comments/#{id}.json"
14
26
  end
15
27
 
28
+ # Get the replies for a comment.
29
+ #
30
+ # @param comment [String, Redd::Object::Submission] The comment to get
31
+ # the replies for.
32
+ # @return [Redd::Object::Listing] A listing of comments.
16
33
  def get_replies(comment)
17
34
  replies = comment.attributes[:replies]
18
- return [] unless replies.is_a?(Hash) and replies.has_key?(:kind)
35
+ return [] unless replies.is_a?(Hash) && replies.key?(:kind)
19
36
  object_from_body(replies)
20
37
  end
21
38
 
@@ -30,8 +47,10 @@ module Redd
30
47
  get_info(id: parent_id).first.link_id
31
48
  end
32
49
 
33
- response = post "/api/morechildren", api_type: "json",
34
- link_id: link_id, children: morecomments.children.join(",")
50
+ response = post "/api/morechildren",
51
+ api_type: "json",
52
+ link_id: link_id,
53
+ children: morecomments.children.join(",")
35
54
  comments = response[:json][:data][:things]
36
55
 
37
56
  # No idea how to increase the depth of the comments.
@@ -1,38 +1,56 @@
1
1
  module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
+ # Methods that return a listing
4
5
  module Listing
5
- def by_id(*fullnames)
6
- names = fullnames.join(",")
7
- object_from_response :get, "/by_id/#{names}.json"
6
+ # Get an object based on its id.
7
+ #
8
+ # @param fullname [String] The fullname of a thing.
9
+ # @return [Redd::Object] The object with the id.
10
+ def by_id(fullname)
11
+ object_from_response :get, "/by_id/#{fullname}.json"
8
12
  end
9
13
 
10
- def get_hot(*args)
11
- get_listing(:hot, *args)
12
- end
13
-
14
- def get_new(*args)
15
- get_listing(:new, *args)
16
- end
17
-
18
- def get_random(*args)
19
- get_listing(:random, *args)
20
- end
21
-
22
- def get_top(*args)
23
- get_listing(:top, *args)
24
- end
25
-
26
- def get_controversial(*args)
27
- get_listing(:controversial, *args)
28
- end
29
-
30
- def get_comments(*args)
31
- get_listing(:comments, *args)
14
+ # @!method get_hot
15
+ # @!method get_new
16
+ # @!method get_random
17
+ # @!method get_top
18
+ # @!method get_controversial
19
+ # @!method get_comments
20
+ #
21
+ # Get the appropriate listing.
22
+ # @param subreddit [Redd::Object::Subreddit] The subreddit to query.
23
+ # @param params [Hash] A list of params to send with the request.
24
+ #
25
+ # @see #get_listing
26
+ %w(hot new random top controversial comments).each do |sort|
27
+ define_method :"get_#{sort}" do |subreddit = nil, params = {}|
28
+ get_listing(sort, subreddit, params)
29
+ end
32
30
  end
33
31
 
34
32
  private
35
33
 
34
+ # Get the front page of reddit or a subreddit sorted by type.
35
+ #
36
+ # @param type [:hot, :new, :random, :top, :controversial, :comments]
37
+ # The type of listing to return
38
+ # @param subreddit [Redd::Object::Subreddit, String] The subreddit to
39
+ # query.
40
+ # @param params [Hash] A list of params to send with the request.
41
+ # @option params [String] :after Return results after the given
42
+ # fullname.
43
+ # @option params [String] :before Return results before the given
44
+ # fullname.
45
+ # @option params [Integer] :count (0) The number of items already seen
46
+ # in the listing.
47
+ # @option params [1..100] :limit (25) The maximum number of things to
48
+ # return.
49
+ # @option params [:hour, :day, :week, :month, :year, :all] :t The
50
+ # time period to consider when sorting.
51
+ # @return [Redd::Object::Listing] A listing of submissions or comments.
52
+ #
53
+ # @note The option :t only applies to the top and controversial sorts.
36
54
  def get_listing(type, subreddit = nil, params = {})
37
55
  name = extract_attribute(subreddit, :display_name) if subreddit
38
56