redd 0.8.0.pre.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69d6cf992f71356b1db86a000bdc3be4508e351c
4
- data.tar.gz: 01d0b098fb7c26a91e34ff001310417c93e3bd74
3
+ metadata.gz: ca106c8ea55f1c1278f643802a357163ebca48cc
4
+ data.tar.gz: 38302c79dbc6c94813c182b5b0ec2b0cae02c124
5
5
  SHA512:
6
- metadata.gz: 4019ce12ee1cfac8927642bfdd327e4221835842a230ad73bce35b0ce3e1f0445523bf5a796aeca182b63c7061861ba1a28a587fe8814594d6d89531ece2c3a6
7
- data.tar.gz: 292775ce9121b4de029ee49e451417508b64524940043569ebe53b807387fac0b1539a7cf5e37a13d494c83267421a1789a75e00ec96cadbaa2cf01128c0f9b7
6
+ metadata.gz: c379f17013fbd83957752e7e745b8f55bc37b96f7cb96ad4d08252f1857b57258cf2fe5fcb8a711f65217908ad703b2e4a506720833226fcc89d36fefe2e9f62
7
+ data.tar.gz: a95cee5b5b15124d6867f1a998c9abb21b7aace479d23ff32e85e86b06c6dac129ffa9dedfc169ce6612a1bfe07614b5a79d8b4d1e5fd506b938bc0bd8b4cdfb
data/README.md CHANGED
@@ -40,6 +40,10 @@ end
40
40
  **Yes**, that's all there is to it! You don't need to handle rate-limiting, refresh access tokens
41
41
  or protect against issues on reddit's end (like 5xx errors).
42
42
 
43
+ #### Where can I find the documentation?
44
+
45
+ [**Latest**](www.rubydoc.info/gems/redd) / [**GitHub**](http://www.rubydoc.info/github/avinashbot/redd/master/Redd/Models/Session)
46
+
43
47
  #### How can I contact you?
44
48
  [Reddit](https://www.reddit.com/message/compose/?to=Mustermind) /
45
49
  [GitHub](https://github.com/avinashbot/redd/issues/new) /
@@ -37,7 +37,7 @@ server.mount_proc '/authenticate' do |_, res|
37
37
  state: '0',
38
38
  redirect_uri: 'http://localhost:8000/redirect',
39
39
  'scope': %w(identity read subscribe privatemessages wikiread submit vote edit modposts history
40
- modflair modconfig)
40
+ modflair modconfig modmail livemanage)
41
41
  )
42
42
  )
43
43
  end
@@ -66,7 +66,7 @@ module Redd
66
66
 
67
67
  def model(verb, path, options = {})
68
68
  # XXX: make unmarshal explicit in methods?
69
- unmarshal(request(verb, path, options).body)
69
+ unmarshal(send(verb, path, options).body)
70
70
  end
71
71
 
72
72
  # Makes a request, ensuring not to break the rate limit by sleeping.
@@ -56,6 +56,11 @@ module Redd
56
56
  @attributes
57
57
  end
58
58
 
59
+ # @return [Array<self>] an array representation of self
60
+ def to_ary
61
+ [self]
62
+ end
63
+
59
64
  # Checks whether an attribute is supported by method_missing.
60
65
  # @param method_name [Symbol] the method name or attribute to check
61
66
  # @param include_private [Boolean] whether to also include private methods
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lazy_model'
4
+
5
+ module Redd
6
+ module Models
7
+ # Represents a conversation in the new modmail.
8
+ # TODO: add message and modmail-specific user type
9
+ class Conversation < LazyModel
10
+ # Get a Conversation from its id.
11
+ # @option hash [String] :id the base36 id (e.g. abc123)
12
+ # @return [Conversation]
13
+ def self.from_response(client, hash)
14
+ id = hash.fetch(:id)
15
+ new(client) do |c|
16
+ response = c.get("/api/mod/conversations/#{id}").body
17
+ response[:conversation].merge(
18
+ messages: response[:messages],
19
+ user: response[:user],
20
+ mod_actions: response[:modActions]
21
+ )
22
+ end
23
+ end
24
+
25
+ # Get a Conversation from its id.
26
+ # @param id [String] the base36 id (e.g. abc123)
27
+ # @return [Conversation]
28
+ def self.from_id(client, id)
29
+ from_response(client, id: id)
30
+ end
31
+
32
+ # Mark this conversation as read.
33
+ def mark_as_read
34
+ @client.post('/api/mod/conversations/read', conversationIds: [get_attribute(:id)])
35
+ end
36
+
37
+ # Mark this conversation as unread.
38
+ def mark_as_unread
39
+ @client.post('/api/mod/conversations/unread', conversationIds: [get_attribute(:id)])
40
+ end
41
+
42
+ # Mark this conversation as archived.
43
+ def archive
44
+ perform_action(:post, 'archive')
45
+ end
46
+
47
+ # Removed this conversation from archived.
48
+ def unarchive
49
+ perform_action(:post, 'unarchive')
50
+ end
51
+
52
+ # Highlight this conversation.
53
+ def highlight
54
+ perform_action(:post, 'highlight')
55
+ end
56
+
57
+ # Remove the highlight on this conversation.
58
+ def unhighlight
59
+ perform_action(:delete, 'highlight')
60
+ end
61
+
62
+ # Mute this conversation.
63
+ def mute
64
+ perform_action(:post, 'mute')
65
+ end
66
+
67
+ # Unmute this conversation.
68
+ def unmute
69
+ perform_action(:post, 'unmute')
70
+ end
71
+
72
+ private
73
+
74
+ # Perform an action on a conversation.
75
+ # @param method [:post, :delete] the method to use
76
+ # @param action [String] the name of the action
77
+ def perform_action(method, action)
78
+ @client.send(method, "/api/mod/conversations/#{id}/#{action}")
79
+ end
80
+ end
81
+ end
82
+ end
@@ -16,6 +16,11 @@ module Redd
16
16
  new(client, hash)
17
17
  end
18
18
 
19
+ # @return [Array<Comment, Submission, PrivateMessage>] an array representation of self
20
+ def to_ary
21
+ get_attribute(:children)
22
+ end
23
+
19
24
  %i([] each empty? first last).each do |method_name|
20
25
  define_method(method_name) do |*args, &block|
21
26
  get_attribute(:children).public_send(method_name, *args, &block)
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lazy_model'
4
+
5
+ module Redd
6
+ module Models
7
+ # Represents a live thread.
8
+ class LiveThread < LazyModel
9
+ # Get a Conversation from its id.
10
+ # @option hash [String] :id the base36 id (e.g. abc123)
11
+ # @return [Conversation]
12
+ def self.from_response(client, hash)
13
+ id = hash.fetch(:id)
14
+ new(client, hash) { |c| c.get("/live/#{id}/about").body[:data] }
15
+ end
16
+
17
+ # Get a LiveThread from its id.
18
+ # @param id [String] the id
19
+ # @return [LiveThread]
20
+ def self.from_id(client, id)
21
+ from_response(client, id: id)
22
+ end
23
+
24
+ # Configure the settings of this live thread
25
+ # @param params [Hash] a list of params to send with the request
26
+ # @option params [String] :description the new description
27
+ # @option params [Boolean] :nsfw whether the thread is for users 18 and above
28
+ # @option params [String] :resources the new resources
29
+ # @option params [String] :title the thread title
30
+ def configure(**params)
31
+ @client.post("/api/live/#{get_attribute(:id)}/edit", params)
32
+ end
33
+
34
+ # Add an update to this live event.
35
+ # @param body [String] the update text
36
+ def update(body)
37
+ @client.post("/api/live/#{get_attribute(:id)}/update", body: body)
38
+ end
39
+
40
+ # @return [Array<User>] the contributors to this thread
41
+ def contributors
42
+ @client.get("/live/#{get_attribute(:id)}/contributors").body[0][:data].map do |user|
43
+ User.from_response(@client, user)
44
+ end
45
+ end
46
+
47
+ # @return [Array<User>] users invited to contribute to this thread
48
+ def invited_contributors
49
+ @client.get("/live/#{get_attribute(:id)}/contributors").body[1][:data].map do |user|
50
+ User.from_response(@client, user)
51
+ end
52
+ end
53
+
54
+ # Returns all discussions that link to this live thread.
55
+ # @param params [Hash] a list of params to send with the request
56
+ # @option params [String] :after return results after the given fullname
57
+ # @option params [String] :before return results before the given fullname
58
+ # @option params [Integer] :count the number of items already seen in the listing
59
+ # @option params [1..100] :limit the maximum number of things to return
60
+ #
61
+ # @return [Listing<Submission>]
62
+ def discussions(**params)
63
+ @client.model(:get, "/live/#{get_attribute(:id)}/discussions", params)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'basic_model'
4
+ require_relative 'subreddit'
5
+ require_relative 'conversation'
6
+
7
+ module Redd
8
+ module Models
9
+ # A container for the new modmail.
10
+ # XXX: Instead of making ModMail a dumb container, could it be a lazy wrapper for #unread_count?
11
+ class ModMail < BasicModel
12
+ # @return [#highlighted, #notifications, #archived, #new, #inprogress, #mod] the number of
13
+ # unread messages in each category
14
+ def unread_count
15
+ BasicModel.new(nil, @client.get('/api/mod/conversations/unread/count').body)
16
+ end
17
+
18
+ # @return [Array<Subreddit>] moderated subreddits that are enrolled in the new modmail
19
+ def enrolled
20
+ @client.get('/api/mod/conversations/subreddits').body[:subreddits].map do |_, s|
21
+ Subreddit.from_response(@client, s.merge(last_updated: s.delete(:lastUpdated)))
22
+ end
23
+ end
24
+
25
+ # Get the conversations
26
+ # @param after [String] base36 modmail conversation id
27
+ # @param subreddits [Subreddit, Array<Subreddit>] the subreddits to limit to
28
+ # @param limit [Integer] an integer (default: 25)
29
+ # @param sort [:recent, :mod, :user, :unread] the sort order
30
+ # @param state [:new, :inprogress, :mod, :notifications, :archived, :highlighted, :all] the
31
+ # state to limit the conversations by
32
+ def conversations(subreddits: nil, **params)
33
+ params[:entity] = Array(subreddits).map(&:display_name).join(',') if subreddits
34
+ @client.get('/api/mod/conversations', **params).body
35
+ end
36
+
37
+ # Get a conversation from its base36 id.
38
+ # @param id [String] the conversation's id
39
+ # @return [Conversation]
40
+ def get(id)
41
+ Conversation.from_id(@client, id)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -19,6 +19,11 @@ module Redd
19
19
  )
20
20
  end
21
21
 
22
+ # @return [Array<String>] an array representation of self
23
+ def to_ary
24
+ get_attribute(:children)
25
+ end
26
+
22
27
  # Keep expanding until all top-level MoreComments are converted to comments
23
28
  def recursive_expand(link:, sort: 'best')
24
29
  # FIXME: this returns a flattened listing of comments and doesn't preserve the structure
@@ -56,6 +56,16 @@ module Redd
56
56
  vote(0)
57
57
  end
58
58
 
59
+ # Send replies to this thing to the user's inbox.
60
+ def enable_inbox_replies
61
+ @client.post('/api/sendreplies', id: get_attribute(:name), state: true)
62
+ end
63
+
64
+ # Stop sending replies to this thing to the user's inbox.
65
+ def disable_inbox_replies
66
+ @client.post('/api/sendreplies', id: get_attribute(:name), state: false)
67
+ end
68
+
59
69
  private
60
70
 
61
71
  # Send a vote.
@@ -9,6 +9,16 @@ module Redd
9
9
  class Session < BasicModel
10
10
  include Searchable
11
11
 
12
+ # @return [ModMail] the new modmail
13
+ def modmail
14
+ ModMail.new(@client)
15
+ end
16
+
17
+ # @return [LiveThread] the live thread
18
+ def live_thread(id)
19
+ LiveThread.from_id(client, id)
20
+ end
21
+
12
22
  # @return [FrontPage] the user's front page
13
23
  def front_page
14
24
  FrontPage.new(@client)
@@ -62,20 +72,14 @@ module Redd
62
72
 
63
73
  # Return a listing of the user's inbox (including comment replies and private messages).
64
74
  #
65
- # @param category ['inbox', 'unread', 'sent'] The category of messages
66
- # to view.
67
- # @param mark [Boolean] Whether to remove the orangered from the
68
- # user's inbox.
69
- # @param params [Hash] A list of optional params to send with the request.
70
- # @option params [String] :after Return results after the given
71
- # fullname.
72
- # @option params [String] :before Return results before the given
73
- # fullname.
74
- # @option params [Integer] :count (0) The number of items already seen
75
- # in the listing.
76
- # @option params [1..100] :limit (25) The maximum number of things to
77
- # return.
78
- # @return [Listing]
75
+ # @param category ['inbox', 'unread', 'sent', 'moderator'] the category of messages to view
76
+ # @param mark [Boolean] whether to remove the orangered from the user's inbox
77
+ # @param params [Hash] a list of optional params to send with the request
78
+ # @option params [String] :after return results after the given fullname
79
+ # @option params [String] :before return results before the given fullname
80
+ # @option params [Integer] :count (0) the number of items already seen in the listing
81
+ # @option params [1..100] :limit (25) the maximum number of things to return
82
+ # @return [Listing<Comment, PrivateMessage>]
79
83
  def my_messages(category: 'inbox', mark: false, **params)
80
84
  @client.model(:get, "/message/#{category}.json", params.merge(mark: mark))
81
85
  end
@@ -84,6 +88,20 @@ module Redd
84
88
  def read_all_messages
85
89
  @client.post('/api/read_all_messages')
86
90
  end
91
+
92
+ # @return [Array<User>] the logged-in user's friends
93
+ def friends
94
+ @client.get('/api/v1/me/friends').body[:data][:children].map do |h|
95
+ User.from_response(@client, name: h[:name], id: h[:id].tr('t2_', ''), since: h[:date])
96
+ end
97
+ end
98
+
99
+ # @return [Array<User>] users blocked by the logged-in user
100
+ def blocked
101
+ @client.get('/prefs/blocked').body[:data][:children].map do |h|
102
+ User.from_response(@client, name: h[:name], id: h[:id].tr('t2_', ''), since: h[:date])
103
+ end
104
+ end
87
105
  end
88
106
  end
89
107
  end
@@ -33,6 +33,17 @@ module Redd
33
33
  end
34
34
  end
35
35
 
36
+ # Get all submissions for the same url.
37
+ # @param params [Hash] A list of optional params to send with the request.
38
+ # @option params [String] :after return results after the given fullname
39
+ # @option params [String] :before return results before the given fullname
40
+ # @option params [Integer] :count (0) the number of items already seen in the listing
41
+ # @option params [1..100] :limit (25) the maximum number of things to return
42
+ # @return [Listing<Submission>]
43
+ def duplicates(**params)
44
+ @client.unmarshal(@client.get("/duplicates/#{get_attribute(:id)}", params).body[1])
45
+ end
46
+
36
47
  # Mark the link as "Not Suitable For Work".
37
48
  def mark_as_nsfw
38
49
  @client.get('/api/marknsfw', id: get_attribute(:name))
@@ -141,6 +141,7 @@ module Redd
141
141
  # @return [Array<Hash>]
142
142
  def relationship_listing(type, **params)
143
143
  # TODO: add methods to determine if a certain user was banned/muted/etc
144
+ # TODO: return User types?
144
145
  user_list = @client.get("/r/#{get_attribute(:display_name)}/about/#{type}", params).body
145
146
  user_list[:data][:children]
146
147
  end
@@ -8,7 +8,7 @@ module Redd
8
8
  class ErrorHandler
9
9
  HTTP_ERRORS = {
10
10
  400 => Redd::BadRequest,
11
- 403 => Redd::Forbidden,
11
+ # 403 => Redd::Forbidden,
12
12
  404 => Redd::NotFound,
13
13
  500 => Redd::ServerError,
14
14
  502 => Redd::ServerError,
@@ -23,12 +23,13 @@ module Redd
23
23
 
24
24
  def check_error(response, raw:)
25
25
  # TODO: deal with errors of type { fields:, explanation:, message:, reason: }
26
- if !raw && response.body[:json] && response.body[:json][:errors] &&
27
- !response.body[:json][:errors].empty?
26
+ if !raw && response.body.is_a?(Hash) && response.body[:json] &&
27
+ response.body[:json][:errors] && !response.body[:json][:errors].empty?
28
28
  Redd::APIError.new(response)
29
29
  elsif HTTP_ERRORS.key?(response.code)
30
30
  HTTP_ERRORS[response.code].new(response)
31
- elsif response.code == 401
31
+ elsif response.code == 401 || response.code == 403
32
+ # FIXME: i think insufficient_scope comes with 403 and invalid_token with 401
32
33
  AUTHORIZATION_ERRORS.each do |key, klass|
33
34
  auth_header = response.headers['www-authenticate']
34
35
  return klass.new(response) if auth_header && auth_header.include?(key)
@@ -5,16 +5,18 @@ module Redd
5
5
  # Unmarshals hashes into objects.
6
6
  class Unmarshaller
7
7
  # Contains the mapping from 'kind' strings to classes.
8
+ # TODO: UserList type!
8
9
  MAPPING = {
9
- 't1' => Models::Comment,
10
- 't2' => Models::User,
11
- 't3' => Models::Submission,
12
- 't4' => Models::PrivateMessage,
13
- 't5' => Models::Subreddit,
14
- 'more' => Models::MoreComments,
15
- 'wikipage' => Models::WikiPage,
16
- 'Listing' => Models::Listing,
17
- 'LabeledMulti' => Models::Multireddit
10
+ 't1' => Models::Comment,
11
+ 't2' => Models::User,
12
+ 't3' => Models::Submission,
13
+ 't4' => Models::PrivateMessage,
14
+ 't5' => Models::Subreddit,
15
+ 'more' => Models::MoreComments,
16
+ 'wikipage' => Models::WikiPage,
17
+ 'Listing' => Models::Listing,
18
+ 'LabeledMulti' => Models::Multireddit,
19
+ 'LiveUpdateEvent' => Models::LiveThread
18
20
  }.freeze
19
21
 
20
22
  def initialize(client)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Redd
4
- VERSION = '0.8.0.pre.2'
4
+ VERSION = '0.8.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0.pre.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avinash Dwarapu
@@ -152,11 +152,14 @@ files:
152
152
  - lib/redd/models/access.rb
153
153
  - lib/redd/models/basic_model.rb
154
154
  - lib/redd/models/comment.rb
155
+ - lib/redd/models/conversation.rb
155
156
  - lib/redd/models/front_page.rb
156
157
  - lib/redd/models/inboxable.rb
157
158
  - lib/redd/models/lazy_model.rb
158
159
  - lib/redd/models/listing.rb
160
+ - lib/redd/models/live_thread.rb
159
161
  - lib/redd/models/messageable.rb
162
+ - lib/redd/models/mod_mail.rb
160
163
  - lib/redd/models/moderatable.rb
161
164
  - lib/redd/models/more_comments.rb
162
165
  - lib/redd/models/multireddit.rb
@@ -191,9 +194,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
194
  version: '0'
192
195
  required_rubygems_version: !ruby/object:Gem::Requirement
193
196
  requirements:
194
- - - ">"
197
+ - - ">="
195
198
  - !ruby/object:Gem::Version
196
- version: 1.3.1
199
+ version: '0'
197
200
  requirements: []
198
201
  rubyforge_project:
199
202
  rubygems_version: 2.6.8