redd 0.8.1 → 0.8.2

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