redd 0.6.5 → 0.7.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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +34 -33
  3. data/.rspec +3 -4
  4. data/.rubocop.yml +5 -5
  5. data/.travis.yml +9 -7
  6. data/{LICENSE.md → LICENSE.txt} +22 -22
  7. data/README.md +126 -241
  8. data/Rakefile +5 -6
  9. data/{RedditKit.LICENSE.md → RedditKit.LICENSE.txt} +13 -13
  10. data/lib/redd.rb +50 -4
  11. data/lib/redd/access.rb +76 -0
  12. data/lib/redd/clients/base.rb +178 -0
  13. data/lib/redd/clients/base/account.rb +20 -0
  14. data/lib/redd/clients/base/identity.rb +22 -0
  15. data/lib/redd/clients/base/none.rb +27 -0
  16. data/lib/redd/clients/base/privatemessages.rb +28 -0
  17. data/lib/redd/clients/base/read.rb +66 -0
  18. data/lib/redd/clients/base/stream.rb +74 -0
  19. data/lib/redd/clients/base/submit.rb +54 -0
  20. data/lib/redd/clients/base/utilities.rb +80 -0
  21. data/lib/redd/clients/base/wikiread.rb +33 -0
  22. data/lib/redd/clients/installed.rb +55 -0
  23. data/lib/redd/clients/script.rb +37 -0
  24. data/lib/redd/clients/userless.rb +31 -0
  25. data/lib/redd/clients/web.rb +57 -0
  26. data/lib/redd/error.rb +138 -153
  27. data/lib/redd/objects/base.rb +36 -0
  28. data/lib/redd/objects/comment.rb +22 -0
  29. data/lib/redd/objects/listing.rb +29 -0
  30. data/lib/redd/objects/more_comments.rb +10 -0
  31. data/lib/redd/objects/private_message.rb +18 -0
  32. data/lib/redd/objects/submission.rb +72 -0
  33. data/lib/redd/objects/subreddit.rb +152 -0
  34. data/lib/redd/objects/thing.rb +33 -0
  35. data/lib/redd/objects/thing/editable.rb +22 -0
  36. data/lib/redd/objects/thing/hideable.rb +18 -0
  37. data/lib/redd/objects/thing/inboxable.rb +25 -0
  38. data/lib/redd/objects/thing/messageable.rb +34 -0
  39. data/lib/redd/objects/thing/moderatable.rb +43 -0
  40. data/lib/redd/objects/thing/refreshable.rb +14 -0
  41. data/lib/redd/objects/thing/saveable.rb +21 -0
  42. data/lib/redd/objects/thing/votable.rb +33 -0
  43. data/lib/redd/objects/user.rb +52 -0
  44. data/lib/redd/objects/wiki_page.rb +15 -0
  45. data/lib/redd/rate_limit.rb +50 -49
  46. data/lib/redd/response/parse_json.rb +17 -33
  47. data/lib/redd/response/raise_error.rb +16 -25
  48. data/lib/redd/version.rb +4 -5
  49. data/redd.gemspec +30 -31
  50. data/spec/redd/objects/base_spec.rb +1 -0
  51. data/spec/redd/rate_limit_spec.rb +29 -29
  52. data/spec/redd/response/parse_json_spec.rb +12 -0
  53. data/spec/redd/response/raise_error_spec.rb +11 -0
  54. data/spec/redd_spec.rb +7 -5
  55. data/spec/spec_helper.rb +69 -50
  56. metadata +73 -136
  57. data/.yardopts +0 -1
  58. data/lib/redd/base.rb +0 -56
  59. data/lib/redd/client/authenticated.rb +0 -83
  60. data/lib/redd/client/authenticated/account.rb +0 -13
  61. data/lib/redd/client/authenticated/apps.rb +0 -13
  62. data/lib/redd/client/authenticated/flair.rb +0 -71
  63. data/lib/redd/client/authenticated/gold.rb +0 -13
  64. data/lib/redd/client/authenticated/links_comments.rb +0 -189
  65. data/lib/redd/client/authenticated/live.rb +0 -13
  66. data/lib/redd/client/authenticated/moderation.rb +0 -126
  67. data/lib/redd/client/authenticated/multis.rb +0 -9
  68. data/lib/redd/client/authenticated/private_messages.rb +0 -73
  69. data/lib/redd/client/authenticated/subreddits.rb +0 -172
  70. data/lib/redd/client/authenticated/users.rb +0 -9
  71. data/lib/redd/client/authenticated/wiki.rb +0 -9
  72. data/lib/redd/client/oauth2.rb +0 -71
  73. data/lib/redd/client/oauth2/authorization.rb +0 -108
  74. data/lib/redd/client/oauth2/identity.rb +0 -16
  75. data/lib/redd/client/oauth2_script.rb +0 -24
  76. data/lib/redd/client/oauth2_script/authorization.rb +0 -21
  77. data/lib/redd/client/unauthenticated.rb +0 -118
  78. data/lib/redd/client/unauthenticated/account.rb +0 -30
  79. data/lib/redd/client/unauthenticated/captcha.rb +0 -27
  80. data/lib/redd/client/unauthenticated/links_comments.rb +0 -60
  81. data/lib/redd/client/unauthenticated/listing.rb +0 -65
  82. data/lib/redd/client/unauthenticated/live.rb +0 -9
  83. data/lib/redd/client/unauthenticated/moderation.rb +0 -26
  84. data/lib/redd/client/unauthenticated/subreddits.rb +0 -49
  85. data/lib/redd/client/unauthenticated/users.rb +0 -67
  86. data/lib/redd/client/unauthenticated/utilities.rb +0 -109
  87. data/lib/redd/client/unauthenticated/wiki.rb +0 -33
  88. data/lib/redd/oauth2_access.rb +0 -70
  89. data/lib/redd/object/comment.rb +0 -74
  90. data/lib/redd/object/listing.rb +0 -29
  91. data/lib/redd/object/more_comments.rb +0 -14
  92. data/lib/redd/object/private_message.rb +0 -35
  93. data/lib/redd/object/submission.rb +0 -94
  94. data/lib/redd/object/subreddit.rb +0 -74
  95. data/lib/redd/object/user.rb +0 -34
  96. data/lib/redd/object/wiki_page.rb +0 -27
  97. data/lib/redd/thing.rb +0 -27
  98. data/lib/redd/thing/commentable.rb +0 -27
  99. data/lib/redd/thing/editable.rb +0 -16
  100. data/lib/redd/thing/hideable.rb +0 -16
  101. data/lib/redd/thing/inboxable.rb +0 -20
  102. data/lib/redd/thing/messageable.rb +0 -12
  103. data/lib/redd/thing/moderatable.rb +0 -32
  104. data/lib/redd/thing/reportable.rb +0 -12
  105. data/lib/redd/thing/saveable.rb +0 -16
  106. data/lib/redd/thing/voteable.rb +0 -22
  107. data/spec/README.md +0 -18
  108. data/spec/redd/base_spec.rb +0 -36
  109. data/spec/redd/client/authenticated/account_spec.rb +0 -5
  110. data/spec/redd/client/authenticated/apps_spec.rb +0 -2
  111. data/spec/redd/client/authenticated/flair_spec.rb +0 -26
  112. data/spec/redd/client/authenticated/gold_spec.rb +0 -2
  113. data/spec/redd/client/authenticated/links_comments_spec.rb +0 -231
  114. data/spec/redd/client/authenticated/live_spec.rb +0 -2
  115. data/spec/redd/client/unauthenticated/account_spec.rb +0 -15
  116. data/spec/redd/client/unauthenticated/captcha_spec.rb +0 -23
  117. data/spec/redd/client/unauthenticated/links_comments_spec.rb +0 -28
  118. data/spec/redd/client/unauthenticated/listing_spec.rb +0 -23
  119. data/spec/redd/client/unauthenticated/live_spec.rb +0 -2
  120. data/spec/redd/client/unauthenticated/moderation_spec.rb +0 -14
  121. data/spec/redd/client/unauthenticated/subreddits_spec.rb +0 -35
  122. data/spec/redd/client/unauthenticated/users_spec.rb +0 -34
  123. data/spec/redd/client/unauthenticated/wiki_spec.rb +0 -18
  124. data/spec/redd/oauth2_access_spec.rb +0 -83
  125. data/spec/redd/thing_spec.rb +0 -22
@@ -0,0 +1,152 @@
1
+ require_relative "thing"
2
+
3
+ module Redd
4
+ module Objects
5
+ # A comment made on links.
6
+ # @todo #subscribe! and #unsubscribe!
7
+ class Subreddit < Thing
8
+ include Thing::Messageable
9
+ include Thing::Refreshable
10
+
11
+ alias_property :header_image, :header_img
12
+ alias_property :nsfw?, :over18
13
+ alias_property :users_online, :accounts_active
14
+ alias_property :type, :subreddit_type
15
+ alias_property :times_gilded, :gilded
16
+
17
+ # @return [String] The url for the subreddit's stylesheet.
18
+ def stylesheet_url
19
+ get("/r/#{display_name}/stylesheet").headers["location"]
20
+ end
21
+
22
+ # @return [String] The css for the subreddit.
23
+ def stylesheet
24
+ Faraday.get(stylesheet_url).body
25
+ end
26
+
27
+ # Accept a moderator invite from a subreddit.
28
+ def accept_moderator_invite!
29
+ post("/r/#{display_name}/api/accept_moderator_invite")
30
+ end
31
+
32
+ # Stop being a contributor of the subreddit.
33
+ def leave_contributor_status!
34
+ post("/api/leavecontributor", id: fullname)
35
+ end
36
+
37
+ # Stop being a moderator of the subreddit.
38
+ def leave_moderator_status!
39
+ post("/api/leavemoderator", id: fullname)
40
+ end
41
+
42
+ # Get a list of everbody on the subreddit with a user flair.
43
+ #
44
+ # @param [Hash] params A list of params to send with the request.
45
+ # @option params [String] :after Return results after the given
46
+ # fullname.
47
+ # @option params [String] :before Return results before the given
48
+ # fullname.
49
+ # @option params [Integer] :count The number of items already seen in the
50
+ # listing.
51
+ # @option params [1..1000] :limit The maximum number of things to
52
+ # return.
53
+ # @option params [String] :name The username when getting the flair of
54
+ # just one user.
55
+ # @return [Objects::Listing<Hash>] A listing of flair hashes.
56
+ def get_flairlist(**params)
57
+ body = get("/r/#{display_name}/api/flairlist.json", params).body
58
+ client.object_from_body(
59
+ kind: "Listing",
60
+ data: {
61
+ children: body[:users],
62
+ before: body[:prev],
63
+ after: body[:next]
64
+ }
65
+ )
66
+ end
67
+
68
+ # Get the flair of a user.
69
+ #
70
+ # @param [Objects::User, String] user The user to find.
71
+ # @return [Hash, nil] Flair info about the user or nil if nobody was
72
+ # found.
73
+ def get_flair(user)
74
+ username = client.property(user, :name)
75
+ flair = get_flairlist(user: username).first
76
+ flair if flair[:user].casecmp(username) == 0
77
+ end
78
+
79
+ # Set the flair of a user or link.
80
+ # @param [Objects::Subreddit, Objects::User] thing The user or link to
81
+ # set the flair to.
82
+ # @param [:user, :link] type The type of thing.
83
+ # @param [String] text The text to set the flair to.
84
+ # @param [String] css_class The css_class of the flair.
85
+ def set_flair(thing, type = nil, text = nil, css_class = nil)
86
+ if thing.is_a?(Objects::User) || type == :user
87
+ params[:name] = client.property(thing, :name)
88
+ elsif thing.is_a?(Objects::Submission) || type == :user
89
+ params[:link] = client.property(thing, :fullname)
90
+ else
91
+ fail "You should provide a proper type."
92
+ end
93
+
94
+ post("/r/#{display_name}/api/flair", text: text, css_class: css_class)
95
+ end
96
+
97
+ # @!method get_hot(**params)
98
+ # @!method get_new(**params)
99
+ # @!method get_top(**params)
100
+ # @!method get_controversial(**params)
101
+ # @!method get_comments(**params)
102
+ #
103
+ # Get the appropriate listing.
104
+ # @param params [Hash] A list of params to send with the request.
105
+ # @option params [String] :after Return results after the given
106
+ # fullname.
107
+ # @option params [String :before Return results before the given
108
+ # fullname.
109
+ # @option params [Integer] :count (0) The number of items already seen
110
+ # in the listing.
111
+ # @option params [1..100] :limit (25) The maximum number of things to
112
+ # return.
113
+ # @option params [:hour, :day, :week, :month, :year, :all] :t The
114
+ # time period to consider when sorting.
115
+ #
116
+ # @note The option :t only applies to the top and controversial sorts.
117
+ # @return [Objects::Listing<Objects::Thing>]
118
+ %w(hot new top controversial comments).each do |sort|
119
+ define_method :"get_#{sort}" do |**params|
120
+ client.send(:"get_#{sort}", self, **params)
121
+ end
122
+ end
123
+
124
+ # @!method get_reports(**params)
125
+ # @!method get_spam(**params)
126
+ # @!method get_modqueue(**params)
127
+ # @!method get_unmoderated(**params)
128
+ # @!method get_edited(**params)
129
+ #
130
+ # Get the appropriate moderator listing.
131
+ # @param [Hash] params A list of params to send with the request.
132
+ # @option params [String] :after Return results after the given
133
+ # fullname.
134
+ # @option params [String] :before Return results before the given
135
+ # fullname.
136
+ # @option params [Integer] :count The number of items already seen
137
+ # in the listing.
138
+ # @option params [1..100] :limit The maximum number of things to
139
+ # return.
140
+ # @option params :location No idea what this does.
141
+ # @option params [:links, :comments] :only The type of things to show.
142
+ #
143
+ # @return [Objects::Listing<Objects::Thing>]
144
+ # @see https://www.reddit.com/dev/api#GET_about_{location}
145
+ %w(reports spam modqueue unmoderated edited).each do |sort|
146
+ define_method :"get_#{sort}" do |**params|
147
+ request_object(:get, "/r/#{display_name}/about/#{sort}", params)
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,33 @@
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
+
25
+ private
26
+
27
+ def response_merge!(meth, path, params = {})
28
+ body = client.send(meth, path, params).body
29
+ deep_merge!(body[:data])
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
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
@@ -0,0 +1,18 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,34 @@
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 << {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
@@ -0,0 +1,43 @@
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
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,21 @@
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 << {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
@@ -0,0 +1,33 @@
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
@@ -0,0 +1,52 @@
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",
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