redd 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -12
- data/lib/redd.rb +0 -12
- data/lib/redd/base.rb +10 -6
- data/lib/redd/client/authenticated.rb +2 -1
- data/lib/redd/client/authenticated/account.rb +2 -0
- data/lib/redd/client/authenticated/apps.rb +1 -0
- data/lib/redd/client/authenticated/flair.rb +33 -7
- data/lib/redd/client/authenticated/gold.rb +1 -0
- data/lib/redd/client/authenticated/links_comments.rb +86 -10
- data/lib/redd/client/authenticated/live.rb +1 -0
- data/lib/redd/client/authenticated/moderation.rb +65 -16
- data/lib/redd/client/authenticated/multis.rb +1 -1
- data/lib/redd/client/authenticated/private_messages.rb +50 -4
- data/lib/redd/client/authenticated/subreddits.rb +28 -0
- data/lib/redd/client/authenticated/users.rb +1 -1
- data/lib/redd/client/authenticated/wiki.rb +1 -1
- data/lib/redd/client/oauth2.rb +2 -2
- data/lib/redd/client/oauth2/authorization.rb +44 -11
- data/lib/redd/client/oauth2/identity.rb +4 -0
- data/lib/redd/client/unauthenticated/account.rb +13 -1
- data/lib/redd/client/unauthenticated/captcha.rb +7 -0
- data/lib/redd/client/unauthenticated/links_comments.rb +23 -4
- data/lib/redd/client/unauthenticated/listing.rb +43 -25
- data/lib/redd/client/unauthenticated/live.rb +1 -0
- data/lib/redd/client/unauthenticated/moderation.rb +9 -1
- data/lib/redd/client/unauthenticated/subreddits.rb +30 -0
- data/lib/redd/client/unauthenticated/utilities.rb +7 -4
- data/lib/redd/client/unauthenticated/wiki.rb +18 -4
- data/lib/redd/error.rb +5 -3
- data/lib/redd/oauth2_access.rb +21 -3
- data/lib/redd/object/more_comments.rb +1 -0
- data/lib/redd/object/private_message.rb +2 -1
- data/lib/redd/object/submission.rb +4 -0
- data/lib/redd/object/user.rb +1 -0
- data/lib/redd/response/raise_error.rb +2 -1
- data/lib/redd/thing/editable.rb +1 -0
- data/lib/redd/thing/hideable.rb +1 -0
- data/lib/redd/thing/inboxable.rb +1 -0
- data/lib/redd/thing/messageable.rb +2 -8
- data/lib/redd/thing/moderatable.rb +1 -0
- data/lib/redd/thing/reportable.rb +1 -0
- data/lib/redd/thing/saveable.rb +1 -0
- data/lib/redd/thing/voteable.rb +1 -1
- data/lib/redd/version.rb +1 -1
- data/spec/redd/client/unauthenticated_spec.rb +1 -1
- data/spec/redd/rate_limit_spec.rb +5 -5
- data/spec/redd_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +2 -3
- data/github/redd.png +0 -0
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/redd/client/oauth2.rb
CHANGED
@@ -44,14 +44,14 @@ module Redd
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
-
def connection
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
33
|
-
|
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
|
-
|
65
|
+
grant_type: "refresh_token",
|
66
|
+
refresh_token: refresh_token
|
36
67
|
|
37
|
-
case
|
38
|
-
when
|
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
|
-
|
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)
|
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",
|
34
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
|