redd 0.7.10 → 0.8.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -30
- data/.rspec +1 -1
- data/.rubocop.yml +16 -3
- data/.travis.yml +13 -7
- data/Gemfile +3 -1
- data/LICENSE.txt +21 -0
- data/README.md +40 -126
- data/Rakefile +10 -3
- data/TODO.md +11 -0
- data/bin/console +84 -0
- data/bin/setup +8 -0
- data/lib/redd.rb +84 -46
- data/lib/redd/api_client.rb +109 -0
- data/lib/redd/auth_strategies/auth_strategy.rb +60 -0
- data/lib/redd/auth_strategies/installed.rb +22 -0
- data/lib/redd/auth_strategies/script.rb +23 -0
- data/lib/redd/auth_strategies/userless.rb +17 -0
- data/lib/redd/auth_strategies/web.rb +29 -0
- data/lib/redd/client.rb +88 -0
- data/lib/redd/error.rb +19 -142
- data/lib/redd/models/access.rb +20 -0
- data/lib/redd/models/basic_model.rb +124 -0
- data/lib/redd/models/comment.rb +51 -0
- data/lib/redd/models/front_page.rb +71 -0
- data/lib/redd/models/inboxable.rb +23 -0
- data/lib/redd/models/lazy_model.rb +63 -0
- data/lib/redd/models/listing.rb +26 -0
- data/lib/redd/models/messageable.rb +20 -0
- data/lib/redd/models/moderatable.rb +41 -0
- data/lib/redd/models/more_comments.rb +10 -0
- data/lib/redd/models/multireddit.rb +32 -0
- data/lib/redd/models/postable.rb +70 -0
- data/lib/redd/models/private_message.rb +29 -0
- data/lib/redd/models/replyable.rb +16 -0
- data/lib/redd/models/session.rb +86 -0
- data/lib/redd/models/submission.rb +40 -0
- data/lib/redd/models/subreddit.rb +201 -0
- data/lib/redd/models/user.rb +72 -0
- data/lib/redd/models/wiki_page.rb +24 -0
- data/lib/redd/utilities/error_handler.rb +35 -0
- data/lib/redd/utilities/rate_limiter.rb +21 -0
- data/lib/redd/utilities/stream.rb +63 -0
- data/lib/redd/utilities/unmarshaller.rb +39 -0
- data/lib/redd/version.rb +4 -3
- data/logo.png +0 -0
- data/redd.gemspec +26 -22
- metadata +73 -99
- data/LICENSE.md +0 -22
- data/RedditKit.LICENSE.md +0 -9
- data/lib/redd/access.rb +0 -76
- data/lib/redd/clients/base.rb +0 -188
- data/lib/redd/clients/base/account.rb +0 -20
- data/lib/redd/clients/base/identity.rb +0 -22
- data/lib/redd/clients/base/none.rb +0 -27
- data/lib/redd/clients/base/privatemessages.rb +0 -33
- data/lib/redd/clients/base/read.rb +0 -113
- data/lib/redd/clients/base/stream.rb +0 -81
- data/lib/redd/clients/base/submit.rb +0 -19
- data/lib/redd/clients/base/utilities.rb +0 -104
- data/lib/redd/clients/base/wikiread.rb +0 -33
- data/lib/redd/clients/installed.rb +0 -57
- data/lib/redd/clients/script.rb +0 -41
- data/lib/redd/clients/userless.rb +0 -32
- data/lib/redd/clients/web.rb +0 -58
- data/lib/redd/objects/base.rb +0 -39
- data/lib/redd/objects/comment.rb +0 -22
- data/lib/redd/objects/labeled_multi.rb +0 -13
- data/lib/redd/objects/listing.rb +0 -29
- data/lib/redd/objects/more_comments.rb +0 -11
- data/lib/redd/objects/private_message.rb +0 -28
- data/lib/redd/objects/submission.rb +0 -139
- data/lib/redd/objects/subreddit.rb +0 -330
- data/lib/redd/objects/thing.rb +0 -26
- data/lib/redd/objects/thing/editable.rb +0 -22
- data/lib/redd/objects/thing/hideable.rb +0 -18
- data/lib/redd/objects/thing/inboxable.rb +0 -25
- data/lib/redd/objects/thing/messageable.rb +0 -34
- data/lib/redd/objects/thing/moderatable.rb +0 -43
- data/lib/redd/objects/thing/refreshable.rb +0 -14
- data/lib/redd/objects/thing/saveable.rb +0 -21
- data/lib/redd/objects/thing/votable.rb +0 -33
- data/lib/redd/objects/user.rb +0 -52
- data/lib/redd/objects/wiki_page.rb +0 -15
- data/lib/redd/rate_limit.rb +0 -88
- data/lib/redd/response/parse_json.rb +0 -18
- data/lib/redd/response/raise_error.rb +0 -16
- data/spec/redd/objects/base_spec.rb +0 -1
- data/spec/redd/response/raise_error_spec.rb +0 -11
- data/spec/redd_spec.rb +0 -5
- data/spec/spec_helper.rb +0 -71
data/lib/redd/objects/thing.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative "base"
|
2
|
-
|
3
|
-
module Redd
|
4
|
-
module Objects
|
5
|
-
# A reddit thing.
|
6
|
-
# @see http://www.reddit.com/dev/api#fullnames
|
7
|
-
class Thing < Base
|
8
|
-
# Load up all the possible mixins for the thing.
|
9
|
-
Dir[File.join(File.dirname(__FILE__), "thing", "*.rb")].each do |file|
|
10
|
-
require(file)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Check for equality.
|
14
|
-
# @param other The other object.
|
15
|
-
# @return [Boolean]
|
16
|
-
def ==(other)
|
17
|
-
other.is_a?(Thing) && fullname == other.fullname
|
18
|
-
end
|
19
|
-
|
20
|
-
# @return [String] The fullname of the thing.
|
21
|
-
def fullname
|
22
|
-
self[:name] || "#{kind}_#{id}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be edited and deleted.
|
5
|
-
module Editable
|
6
|
-
# Edit a thing.
|
7
|
-
# @param text [String] The new text.
|
8
|
-
# @return [Thing] The edited thing.
|
9
|
-
def edit(text)
|
10
|
-
post("/api/editusertext", thing_id: fullname, text: text)
|
11
|
-
self[(self.is_a?(Submission) ? :selftext : :body)] = text
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
|
-
# Delete the thing
|
16
|
-
def delete!
|
17
|
-
post("/api/del", id: fullname)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be hidden from the user.
|
5
|
-
module Hideable
|
6
|
-
# Hide a link from the user.
|
7
|
-
def hide
|
8
|
-
post("/api/hide", id: fullname)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Unhide a previously hidden link.
|
12
|
-
def unhide
|
13
|
-
post("/api/unhide", id: fullname)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be sent to a user's inbox.
|
5
|
-
module Inboxable
|
6
|
-
# Mark this thing as read.
|
7
|
-
def mark_as_read
|
8
|
-
post("/api/read_message", id: fullname)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Mark one or more messages as unread.
|
12
|
-
def mark_as_unread
|
13
|
-
post("/api/unread_message", id: fullname)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Reply to the thing.
|
17
|
-
# @param text [String] The text to comment.
|
18
|
-
# @return [Objects::Comment, Objects::PrivateMessage] The reply.
|
19
|
-
def reply(text)
|
20
|
-
client.add_comment(self, text)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be sent a message.
|
5
|
-
module Messageable
|
6
|
-
# Compose a message to a person or the moderators of a subreddit.
|
7
|
-
#
|
8
|
-
# @param [String] subject The subject of the message.
|
9
|
-
# @param [String] text The message text.
|
10
|
-
# @param [String] from_sr The subreddit to send the message on behalf
|
11
|
-
# of or nil if from the user.
|
12
|
-
# @param [String] captcha A possible captcha result to send if one
|
13
|
-
# is required.
|
14
|
-
# @param [String] identifier The identifier for the captcha if one
|
15
|
-
# is required.
|
16
|
-
def send_message(
|
17
|
-
subject, text, from_sr = nil, captcha = nil, identifier = nil
|
18
|
-
)
|
19
|
-
params = {subject: subject, text: text}
|
20
|
-
params.merge!(captcha: captcha, iden: identifier) if captcha
|
21
|
-
params[:from_sr] = client.property(from_sr, :display_name) if from_sr
|
22
|
-
params[:to] =
|
23
|
-
if respond_to?(:display_name)
|
24
|
-
"/r/#{self[:display_name]}"
|
25
|
-
else
|
26
|
-
self[:name]
|
27
|
-
end
|
28
|
-
|
29
|
-
post("/api/compose", params)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that a moderator can manage.
|
5
|
-
module Moderatable
|
6
|
-
# Approve a submission.
|
7
|
-
def approve!
|
8
|
-
post("/api/approve", id: fullname)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Remove a submission.
|
12
|
-
# @param [Boolean] spam Whether or not this item is removed due to it
|
13
|
-
# being spam.
|
14
|
-
def remove!(spam = false)
|
15
|
-
post("/api/remove", id: fullname, spam: spam)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Distinguish a link or comment with a sigil to show that it has
|
19
|
-
# been created by a moderator.
|
20
|
-
# @param [:yes, :no, :admin, :special] how How to distinguish the
|
21
|
-
# thing.
|
22
|
-
def distinguish(how = :yes)
|
23
|
-
post("/api/distinguish", id: fullname, how: how)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Remove the sigil that shows a thing was created by a moderator.
|
27
|
-
def undistinguish
|
28
|
-
distinguish(:no)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Stop getting any moderator-related reports on the thing.
|
32
|
-
def ignore_reports
|
33
|
-
post("/api/ignore_reports", id: fullname)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Start getting moderator-related reports on the thing again.
|
37
|
-
def unignore_reports
|
38
|
-
post("/api/unignore_reports", id: fullname)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be refreshed with the current data.
|
5
|
-
module Refreshable
|
6
|
-
# Refresh the thing.
|
7
|
-
def refresh!
|
8
|
-
body = get("/api/info", id: fullname).body[:data][:children][0]
|
9
|
-
deep_merge!(body[:data])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be saved to a user's account.
|
5
|
-
module Saveable
|
6
|
-
# Save a link or comment (if gilded) to the user's account.
|
7
|
-
# @param [String] category A category to save to (if gilded).
|
8
|
-
def save(category = nil)
|
9
|
-
params = {id: fullname}
|
10
|
-
params.merge!(category: category) if category
|
11
|
-
post("/api/save", params)
|
12
|
-
end
|
13
|
-
|
14
|
-
# Remove the link or comment from the user's saved links.
|
15
|
-
def unsave
|
16
|
-
post("/api/unsave", id: fullname)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Redd
|
2
|
-
module Objects
|
3
|
-
class Thing
|
4
|
-
# Things that can be voted upon.
|
5
|
-
module Votable
|
6
|
-
# Upvote the thing.
|
7
|
-
def upvote
|
8
|
-
vote(1)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Downvote the thing.
|
12
|
-
def downvote
|
13
|
-
vote(-1)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Remove your vote on the thing.
|
17
|
-
def clear_vote
|
18
|
-
vote(0)
|
19
|
-
end
|
20
|
-
alias_method :unvote, :clear_vote
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
# Send a vote.
|
25
|
-
# @param [-1, 0, 1] direction The direction to vote in.
|
26
|
-
def vote(direction)
|
27
|
-
post("/api/vote", id: fullname, dir: direction)
|
28
|
-
self[:ups] += direction
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/lib/redd/objects/user.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
require_relative "thing"
|
2
|
-
|
3
|
-
module Redd
|
4
|
-
module Objects
|
5
|
-
# The model for a reddit user
|
6
|
-
class User < Thing
|
7
|
-
include Thing::Messageable
|
8
|
-
|
9
|
-
# @!method get_overview(**params)
|
10
|
-
# @!method get_submitted(**params)
|
11
|
-
# @!method get_comments(**params)
|
12
|
-
# @!method get_liked(**params)
|
13
|
-
# @!method get_disliked(**params)
|
14
|
-
# @!method get_hidden(**params)
|
15
|
-
# @!method get_saved(**params)
|
16
|
-
# @!method get_gilded(**params)
|
17
|
-
#
|
18
|
-
# Get the appropriate listing.
|
19
|
-
# @option params [String] :after Return results after the given
|
20
|
-
# fullname.
|
21
|
-
# @option params [String] :before Return results before the given
|
22
|
-
# fullname.
|
23
|
-
# @option params [Integer] :count The number of items already seen
|
24
|
-
# in the listing.
|
25
|
-
# @option params [1..100] :limit The maximum number of things to
|
26
|
-
# return.
|
27
|
-
# @option params [:hot, :new, :top, :controversial] :sort The type of
|
28
|
-
# sort to use.
|
29
|
-
# @option params [:hour, :day, :week, :month, :year, :all] :t The
|
30
|
-
# time period to consider when sorting.
|
31
|
-
# @option params [:given] :show For {#get_gilded}, whether to show the
|
32
|
-
# gildings given.
|
33
|
-
# @note The option :t only applies to the top and controversial sorts.
|
34
|
-
# @return [Listing<Submission>]
|
35
|
-
%w(
|
36
|
-
overview submitted comments liked disliked hidden saved gilded
|
37
|
-
).each do |type|
|
38
|
-
define_method :"get_#{type}" do |**params|
|
39
|
-
client.request_object(
|
40
|
-
:get, "/user/#{name}/#{type}.json", **params
|
41
|
-
)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Get posts that the user has gilded.
|
46
|
-
# @see #get_gilded
|
47
|
-
def get_gildings_given(**params)
|
48
|
-
get_gilded(**params.merge(show: "given"))
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require_relative "thing"
|
2
|
-
|
3
|
-
module Redd
|
4
|
-
module Objects
|
5
|
-
# A submission made in a subreddit.
|
6
|
-
class WikiPage < Thing
|
7
|
-
alias_property :content, :content_md
|
8
|
-
alias_property :body, :content_md
|
9
|
-
|
10
|
-
def revision_user
|
11
|
-
@revision_by ||= client.object_from_body(revision_by)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/lib/redd/rate_limit.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
# The main Redd module.
|
2
|
-
module Redd
|
3
|
-
# The class that handles rate limiting for reddit.
|
4
|
-
#
|
5
|
-
# If you'd rather have an asynchronous or queue-based limiting, it's easy to
|
6
|
-
# write one yourself. A rate limiting class is any class that has an
|
7
|
-
# {#after_limit} method. The block returns a Faraday::Response object, so you
|
8
|
-
# can also extract the headers from the response and use those instead. To
|
9
|
-
# remove rate limiting entirely, follow the example below.
|
10
|
-
#
|
11
|
-
# @example To remove rate limiting entirely, just burst forever.
|
12
|
-
# rt = Redd::RateLimit.new
|
13
|
-
# rt.burst!(Float::INFINITY)
|
14
|
-
class RateLimit
|
15
|
-
# @!attribute [rw] gap
|
16
|
-
# @return [Integer, Float] The minimum time between requests.
|
17
|
-
attr_accessor :gap
|
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
|
-
|
33
|
-
# @param [Float, Integer] gap The minimum time between each request.
|
34
|
-
def initialize(gap)
|
35
|
-
# Some time ages ago, because we never made a request.
|
36
|
-
@last_request = Time.at(0)
|
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
|
46
|
-
end
|
47
|
-
|
48
|
-
# Sleep until 1 second has passed since the last request and perform the
|
49
|
-
# given request unless bursting.
|
50
|
-
#
|
51
|
-
# @yield [Faraday::Response] A response.
|
52
|
-
# @return [Faraday::Response] The response.
|
53
|
-
def after_limit
|
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 = 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
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require "faraday/response"
|
2
|
-
require_relative "../error"
|
3
|
-
|
4
|
-
module Redd
|
5
|
-
# The module that contains middleware that alters the Faraday response.
|
6
|
-
module Response
|
7
|
-
# Faraday Middleware that parses JSON using OJ, via MultiJson.
|
8
|
-
class ParseJson < Faraday::Response::Middleware
|
9
|
-
dependency "multi_json"
|
10
|
-
|
11
|
-
def on_complete(env)
|
12
|
-
env[:body] = MultiJson.load(env[:body], symbolize_keys: true)
|
13
|
-
rescue MultiJson::ParseError
|
14
|
-
raise ::Redd::Error::JSONError.new(env), env[:body]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require "faraday/response"
|
2
|
-
require_relative "../error"
|
3
|
-
|
4
|
-
module Redd
|
5
|
-
# The module that contains middleware that alters the Faraday response.
|
6
|
-
module Response
|
7
|
-
# Faraday Middleware that raises an error if there's one.
|
8
|
-
# @see Error
|
9
|
-
class RaiseError < Faraday::Response::Middleware
|
10
|
-
def on_complete(env)
|
11
|
-
error = Redd::Error.from_response(env)
|
12
|
-
fail error.new(env), env[:body] if error
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
# There's no point in testing Base, since we'd basically be testing Hashie.
|