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 +4 -4
- data/README.md +4 -0
- data/bin/console +1 -1
- data/lib/redd/api_client.rb +1 -1
- data/lib/redd/models/basic_model.rb +5 -0
- data/lib/redd/models/conversation.rb +82 -0
- data/lib/redd/models/listing.rb +5 -0
- data/lib/redd/models/live_thread.rb +67 -0
- data/lib/redd/models/mod_mail.rb +45 -0
- data/lib/redd/models/more_comments.rb +5 -0
- data/lib/redd/models/postable.rb +10 -0
- data/lib/redd/models/session.rb +32 -14
- data/lib/redd/models/submission.rb +11 -0
- data/lib/redd/models/subreddit.rb +1 -0
- data/lib/redd/utilities/error_handler.rb +5 -4
- data/lib/redd/utilities/unmarshaller.rb +11 -9
- data/lib/redd/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca106c8ea55f1c1278f643802a357163ebca48cc
|
4
|
+
data.tar.gz: 38302c79dbc6c94813c182b5b0ec2b0cae02c124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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) /
|
data/bin/console
CHANGED
@@ -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
|
data/lib/redd/api_client.rb
CHANGED
@@ -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(
|
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
|
data/lib/redd/models/listing.rb
CHANGED
@@ -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
|
data/lib/redd/models/postable.rb
CHANGED
@@ -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.
|
data/lib/redd/models/session.rb
CHANGED
@@ -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']
|
66
|
-
#
|
67
|
-
# @param
|
68
|
-
#
|
69
|
-
# @
|
70
|
-
# @option params [
|
71
|
-
#
|
72
|
-
# @
|
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
|
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'
|
10
|
-
't2'
|
11
|
-
't3'
|
12
|
-
't4'
|
13
|
-
't5'
|
14
|
-
'more'
|
15
|
-
'wikipage'
|
16
|
-
'Listing'
|
17
|
-
'LabeledMulti'
|
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)
|
data/lib/redd/version.rb
CHANGED
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
|
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:
|
199
|
+
version: '0'
|
197
200
|
requirements: []
|
198
201
|
rubyforge_project:
|
199
202
|
rubygems_version: 2.6.8
|