redd 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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