redd 0.8.1 → 0.8.2

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.
@@ -21,7 +21,7 @@ module Redd
21
21
  # Save a link or comment to the user's account.
22
22
  # @param category [String] a category to save to
23
23
  def save(category = nil)
24
- params = { id: fullname }
24
+ params = { id: get_attribute(:name) }
25
25
  params[:category] = category if category
26
26
  @client.post('/api/save', params)
27
27
  end
@@ -33,12 +33,12 @@ module Redd
33
33
 
34
34
  # Hide a link from the user.
35
35
  def hide
36
- @client.post('/api/hide', id: get_attribute(:fullname))
36
+ @client.post('/api/hide', id: get_attribute(:name))
37
37
  end
38
38
 
39
39
  # Unhide a previously hidden link.
40
40
  def unhide
41
- @client.post('/api/unhide', id: get_attribute(:fullname))
41
+ @client.post('/api/unhide', id: get_attribute(:name))
42
42
  end
43
43
 
44
44
  # Upvote the model.
@@ -11,19 +11,28 @@ module Redd
11
11
  include Inboxable
12
12
  include Replyable
13
13
 
14
- # Make a Message from its id.
15
- # @option hash [String] :id the post's id (e.g. abc123)
16
- # @return [Submission]
17
- def self.from_response(client, hash)
18
- # FIXME: This returns the entire conversation, not the specific message. Possible to search,
19
- # because depth of replies is just one.
20
- super
21
- end
22
-
23
14
  # Delete the message from the user's inbox.
24
15
  def delete
25
16
  @client.post('/api/del_msg', id: get_attribute(:name))
26
17
  end
18
+
19
+ # Mute the author of the message.
20
+ def mute_author
21
+ @client.post('/api/mute_message_author', id: get_attribute(:name))
22
+ end
23
+
24
+ # Unmute the author of the message.
25
+ def unmute_author
26
+ @client.post('/api/unmute_message_author', id: get_attribute(:name))
27
+ end
28
+
29
+ private
30
+
31
+ def default_loader
32
+ # FIXME: This returns the entire conversation, not the specific message. Possible to search,
33
+ # because depth of replies is just one.
34
+ {}
35
+ end
27
36
  end
28
37
  end
29
38
  end
@@ -20,7 +20,7 @@ module Redd
20
20
  # @option params [String] :restrict_to restrict by subreddit (prefer {Subreddit#search})
21
21
  # @return [Listing<Comment, Submission>] the search results
22
22
  def search(query, **params)
23
- params[:q] = query if query
23
+ params[:q] = query
24
24
  params[:t] = params.delete(:time) if params.key?(:time)
25
25
  if params[:restrict_to]
26
26
  subreddit = params.delete(:restrict_to)
@@ -94,20 +94,49 @@ module Redd
94
94
  @client.post('/api/read_all_messages')
95
95
  end
96
96
 
97
+ # @return [Hash] the user's preferences
98
+ def my_preferences
99
+ @client.get('/api/v1/me/prefs').body
100
+ end
101
+
102
+ # Edit the user's preferences.
103
+ # @param new_prefs [Hash] the changed preferences
104
+ # @return [Hash] the new preferences
105
+ # @see #my_preferences
106
+ def edit_preferences(new_prefs = {})
107
+ @client.request(
108
+ :patch, '/api/v1/me/prefs',
109
+ headers: { 'Content-Type' => 'application/json' },
110
+ body: JSON.generate(new_prefs)
111
+ ).body
112
+ end
113
+
97
114
  # @return [Array<User>] the logged-in user's friends
98
115
  def friends
99
116
  @client.get('/api/v1/me/friends').body[:data][:children].map do |h|
100
- User.from_response(@client, name: h[:name], id: h[:id].sub('t2_', ''), since: h[:date])
117
+ User.new(@client, name: h[:name], id: h[:id].sub('t2_', ''), since: h[:date])
101
118
  end
102
119
  end
103
120
 
104
121
  # @return [Array<User>] users blocked by the logged-in user
105
122
  def blocked
106
123
  @client.get('/prefs/blocked').body[:data][:children].map do |h|
107
- User.from_response(@client, name: h[:name], id: h[:id].sub('t2_', ''), since: h[:date])
124
+ User.new(@client, name: h[:name], id: h[:id].sub('t2_', ''), since: h[:date])
125
+ end
126
+ end
127
+
128
+ # @return [Array<User>] users blocked by the logged-in user
129
+ def trusted
130
+ @client.get('/prefs/trusted').body[:data][:children].map do |h|
131
+ User.new(@client, name: h[:name], id: h[:id].sub('t2_', ''), since: h[:date])
108
132
  end
109
133
  end
110
134
 
135
+ # @return [Array<String>] a list of categories the user's items are saved in
136
+ def saved_categories
137
+ @client.get('/api/saved_categories').body
138
+ end
139
+
111
140
  # Return a listing of the user's subreddits.
112
141
  #
113
142
  # @param type ['subscriber', 'contributor', 'moderator'] the type of subreddits
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'lazy_model'
4
+ require_relative 'gildable'
4
5
  require_relative 'moderatable'
5
6
  require_relative 'postable'
6
7
  require_relative 'replyable'
@@ -12,25 +13,17 @@ module Redd
12
13
  module Models
13
14
  # A text or link post.
14
15
  class Submission < LazyModel
16
+ include Gildable
15
17
  include Moderatable
16
18
  include Postable
17
19
  include Replyable
18
20
 
19
- coerce_attribute :author, User
20
- coerce_attribute :subreddit, Subreddit
21
-
22
- # Make a Submission from its id.
23
- # @option hash [String] :id the post's id (e.g. abc123)
21
+ # Create a Subreddit from its fullname.
22
+ # @param client [APIClient] the api client to initialize the object with
23
+ # @param id [String] the fullname
24
24
  # @return [Submission]
25
- def self.from_response(client, hash)
26
- link_id = hash.fetch(:id)
27
- new(client, hash) do |c|
28
- # `data` is a pair (2-element array):
29
- # - data[0] is a one-item listing containing the submission
30
- # - data[1] is listing of comments
31
- data = c.get("/comments/#{link_id}").body
32
- data[0][:data][:children][0][:data].merge(comments: c.unmarshal(data[1]))
33
- end
25
+ def self.from_id(client, id)
26
+ new(client, name: id)
34
27
  end
35
28
 
36
29
  # Get all submissions for the same url.
@@ -98,6 +91,25 @@ module Redd
98
91
  def unlock
99
92
  @client.post('/api/unlock', id: get_attribute(:name))
100
93
  end
94
+
95
+ private
96
+
97
+ def default_loader
98
+ # Ensure we have the link's id.
99
+ id = @attributes[:id] ? @attributes[:id] : @attributes.fetch(:name).sub('t3_', '')
100
+ response = @client.get("/comments/#{id}").body
101
+ # `response` is a pair (2-element array):
102
+ # - response[0] is a one-item listing containing the submission
103
+ # - response[1] is listing of comments
104
+ response[0][:data][:children][0][:data].merge(comments: @client.unmarshal(response[1]))
105
+ end
106
+
107
+ def after_initialize
108
+ if @attributes[:subreddit]
109
+ @attributes[:subreddit] = Subreddit.from_id(@client, @attributes[:subreddit])
110
+ end
111
+ @attributes[:author] = User.from_id(@client, @attributes[:author]) if @attributes[:author]
112
+ end
101
113
  end
102
114
  end
103
115
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'basic_model'
3
4
  require_relative 'lazy_model'
4
5
  require_relative 'messageable'
5
6
  require_relative 'searchable'
@@ -12,14 +13,6 @@ module Redd
12
13
  include Messageable
13
14
  include Searchable
14
15
 
15
- # A list of keys that are required by #modify_settings.
16
- SETTINGS_KEYS = %i(allow_images allow_top collapse_deleted_comments comment_score_hide_mins
17
- description exclude_banned_modqueue header-title hide_ads lang link_type
18
- over_18 public_description public_traffic show_media show_media_preview
19
- spam_comments spam_links spam_selfposts spoilers_enabled submit_link_label
20
- submit_text submit_text_label suggested_comment_sort theme_sr
21
- theme_sr_update title type wiki_edit_age wiki_edit_karma wikimode).freeze
22
-
23
16
  # A mapping from keys returned by #settings to keys required by #modify_settings
24
17
  SETTINGS_MAP = {
25
18
  subreddit_type: :type,
@@ -29,20 +22,16 @@ module Redd
29
22
  header_hover_text: :'header-title'
30
23
  }.freeze
31
24
 
32
- # Make a Subreddit from its name.
33
- # @option hash [String] :display_name the subreddit's name
34
- # @return [Subreddit]
35
- def self.from_response(client, hash)
36
- name = hash.fetch(:display_name)
37
- new(client, hash) { |c| c.get("/r/#{name}/about").body[:data] }
38
- end
25
+ # Represents a moderator action, part of a moderation log.
26
+ # @see Subreddit#log
27
+ class ModAction < BasicModel; end
39
28
 
40
29
  # Create a Subreddit from its name.
41
30
  # @param client [APIClient] the api client to initialize the object with
42
31
  # @param id [String] the subreddit name
43
32
  # @return [Subreddit]
44
33
  def self.from_id(client, id)
45
- from_response(client, display_name: id)
34
+ new(client, display_name: id)
46
35
  end
47
36
 
48
37
  # @return [Array<String>] the subreddit's wiki pages
@@ -54,7 +43,7 @@ module Redd
54
43
  # @param title [String] the page's title
55
44
  # @return [WikiPage]
56
45
  def wiki_page(title)
57
- WikiPage.from_response(@client, title: title, subreddit: self)
46
+ WikiPage.new(@client, title: title, subreddit: self)
58
47
  end
59
48
 
60
49
  # Search a subreddit.
@@ -198,7 +187,7 @@ module Redd
198
187
  params[:kind] = url ? 'link' : 'self'
199
188
  params[:url] = url if url
200
189
  params[:text] = text if text
201
- Submission.from_response(@client, @client.post('/api/submit', params).body[:json][:data])
190
+ Submission.new(@client, @client.post('/api/submit', params).body[:json][:data])
202
191
  end
203
192
 
204
193
  # Compose a message to the moderators of a subreddit.
@@ -293,10 +282,117 @@ module Redd
293
282
  @client.post('/api/site_admin', full_params)
294
283
  end
295
284
 
285
+ # Get the moderation log.
286
+ # @param params [Hash] a list of params to send with the request
287
+ # @option params [String] :after return results after the given fullname
288
+ # @option params [String] :before return results before the given fullname
289
+ # @option params [Integer] :count the number of items already seen in the listing
290
+ # @option params [1..100] :limit the maximum number of things to return
291
+ # @option params [String] :type filter events to a specific type
292
+ #
293
+ # @return [Listing<ModAction>]
294
+ def mod_log(**params)
295
+ @client.model(:get, "/r/#{get_attribute(:display_name)}/about/log", params)
296
+ end
297
+
298
+ # Invite a user to moderate this subreddit.
299
+ # @param user [User] the user to invite
300
+ # @param permissions [String] the permission string to invite the user with
301
+ def invite_moderator(user, permissions: '+all')
302
+ add_relationship(type: 'moderator_invite', name: user.name, permissions: permissions)
303
+ end
304
+
305
+ # Take back a moderator request.
306
+ # @param user [User] the requested user
307
+ def uninvite_moderator(user)
308
+ remove_relationship(type: 'moderator_invite', name: user.name)
309
+ end
310
+
311
+ # Accept an invite to become a moderator of this subreddit.
312
+ def accept_moderator_invite
313
+ @client.post("/r/#{get_attribute(:display_name)}/api/accept_moderator_invite")
314
+ end
315
+
316
+ # Dethrone a moderator.
317
+ # @param user [User] the user to remove
318
+ def remove_moderator(user)
319
+ remove_relationship(type: 'moderator', name: user.name)
320
+ end
321
+
322
+ # Leave from being a moderator on a subreddit.
323
+ def leave_moderator
324
+ @client.post('/api/leavemoderator', id: get_attribute(:name))
325
+ end
326
+
327
+ # Add a contributor to the subreddit.
328
+ # @param user [User] the user to add
329
+ def add_contributor(user)
330
+ add_relationship(type: 'contributor', name: user.name)
331
+ end
332
+
333
+ # Remove a contributor from the subreddit.
334
+ # @param user [User] the user to remove
335
+ def remove_contributor(user)
336
+ remove_relationship(type: 'contributor', name: user.name)
337
+ end
338
+
339
+ # Leave from being a contributor on a subreddit.
340
+ def leave_contributor
341
+ @client.post('/api/leavecontributor', id: get_attribute(:name))
342
+ end
343
+
344
+ # Ban a user from a subreddit.
345
+ # @param user [User] the user to ban
346
+ # @param params [Hash] additional options to supply with the request
347
+ # @option params [String] :ban_reason the reason for the ban
348
+ # @option params [String] :ban_message a message sent to the banned user
349
+ # @option params [String] :note a note that only moderators can see
350
+ # @option params [Integer] :duration the number of days to ban the user (if temporary)
351
+ def ban(user, **params)
352
+ add_relationship(type: 'banned', name: user.name, **params)
353
+ end
354
+
355
+ # Remove a ban on a user.
356
+ # @param user [User] the user to unban
357
+ def unban(user)
358
+ remove_relationship(type: 'banned', name: user.name)
359
+ end
360
+
361
+ # Allow a user to contribute to the wiki.
362
+ # @param user [User] the user to add
363
+ def add_wiki_contributor(user)
364
+ add_relationship(type: 'wikicontributor', name: user.name)
365
+ end
366
+
367
+ # No longer allow a user to contribute to the wiki.
368
+ # @param user [User] the user to remove
369
+ def remove_wiki_contributor(user)
370
+ remove_relationship(type: 'wikicontributor', name: user.name)
371
+ end
372
+
373
+ # Ban a user from contributing to the wiki.
374
+ # @param user [User] the user to ban
375
+ # @param params [Hash] additional options to supply with the request
376
+ # @option params [String] :ban_reason the reason for the ban (not sure this matters)
377
+ # @option params [String] :note a note that only moderators can see
378
+ # @option params [Integer] :duration the number of days to ban the user (if temporary)
379
+ def ban_wiki_contributor(user, **params)
380
+ add_relationship(type: 'wikibanned', name: user.name, **params)
381
+ end
382
+
383
+ # No longer ban a user from contributing to the wiki.
384
+ # @param user [User] the user to unban
385
+ def unban_wiki_contributor(user)
386
+ remove_relationship(type: 'wikibanned', name: user.name)
387
+ end
388
+
296
389
  private
297
390
 
391
+ def default_loader
392
+ @client.get("/r/#{@attributes.fetch(:display_name)}/about").body[:data]
393
+ end
394
+
298
395
  def add_relationship(**params)
299
- # FIXME: add public methods
300
396
  @client.post("/r/#{get_attribute(:display_name)}/api/friend", params)
301
397
  end
302
398
 
@@ -9,20 +9,20 @@ module Redd
9
9
  class User < LazyModel
10
10
  include Messageable
11
11
 
12
- # Make a User from their name.
13
- # @option hash [String] :name the user's name
14
- # @return [User]
15
- def self.from_response(client, hash)
16
- name = hash.fetch(:name)
17
- new(client, hash) { |c| c.get("/user/#{name}/about").body[:data] }
18
- end
19
-
20
12
  # Create a User from their name.
21
13
  # @param client [APIClient] the api client to initialize the object with
22
14
  # @param id [String] the username
23
15
  # @return [User]
24
16
  def self.from_id(client, id)
25
- from_response(client, name: id)
17
+ new(client, name: id)
18
+ end
19
+
20
+ # Unblock a previously blocked user.
21
+ # @param me [User] (optional) the person doing the unblocking
22
+ def unblock(me: nil)
23
+ my_id = 't2_' + (me.is_a?(User) ? user.id : @client.get('/api/v1/me').body[:id])
24
+ # Talk about an unintuitive endpoint
25
+ @client.post('/api/unfriend', container: my_id, name: get_attribute(:name), type: 'enemy')
26
26
  end
27
27
 
28
28
  # Compose a message to the moderators of a subreddit.
@@ -81,6 +81,18 @@ module Redd
81
81
  %i(overview submitted comments liked disliked hidden saved gilded).each do |type|
82
82
  define_method(type) { |**params| listing(type, **params) }
83
83
  end
84
+
85
+ # Gift a redditor reddit gold.
86
+ # @param months [Integer] the number of months of gold to gift
87
+ def gift_gold(months: 1)
88
+ @client.post("/api/v1/gold/give/#{get_attribute(:name)}", months: months)
89
+ end
90
+
91
+ private
92
+
93
+ def default_loader
94
+ @client.get("/user/#{@attributes.fetch(:name)}/about").body[:data]
95
+ end
84
96
  end
85
97
  end
86
98
  end
@@ -6,18 +6,15 @@ module Redd
6
6
  module Models
7
7
  # A reddit user.
8
8
  class WikiPage < LazyModel
9
- # Make a Wikipage from its title and subreddit.
10
- # @option hash [String] :title the page's title
11
- # @option hash [Subreddit] :subreddit the page's subreddit
12
- # @return [WikiPage]
13
- def self.from_response(client, hash)
14
- title = hash.fetch(:title)
15
- if hash.key?(:subreddit)
16
- sr_name = hash[:subreddit].display_name
17
- new(client, hash) { |c| c.get("/r/#{sr_name}/wiki/#{title}").body[:data] }
18
- else
19
- new(client, hash) { |c| c.get("/wiki/#{title}").body[:data] }
9
+ private
10
+
11
+ def default_loader
12
+ title = @attributes.fetch(:title)
13
+ if @attributes.key?(:subreddit)
14
+ sr_name = attributes[:subreddit].display_name
15
+ return @client.get("/r/#{sr_name}/wiki/#{title}").body[:data]
20
16
  end
17
+ @client.get("/wiki/#{title}").body[:data]
21
18
  end
22
19
  end
23
20
  end