redd 0.8.8 → 0.9.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/CONTRIBUTING.md +63 -0
- data/Guardfile +7 -0
- data/README.md +6 -5
- data/Rakefile +1 -1
- data/TODO.md +423 -0
- data/bin/console +91 -77
- data/bin/guard +2 -0
- data/lib/redd.rb +7 -5
- data/lib/redd/api_client.rb +2 -3
- data/lib/redd/auth_strategies/auth_strategy.rb +7 -2
- data/lib/redd/auth_strategies/script.rb +7 -0
- data/lib/redd/auth_strategies/userless.rb +7 -0
- data/lib/redd/auth_strategies/web.rb +6 -1
- data/lib/redd/client.rb +0 -3
- data/lib/redd/errors.rb +56 -0
- data/lib/redd/middleware.rb +10 -8
- data/lib/redd/models/access.rb +30 -18
- data/lib/redd/models/comment.rb +185 -27
- data/lib/redd/models/front_page.rb +16 -36
- data/lib/redd/models/gildable.rb +1 -1
- data/lib/redd/models/inboxable.rb +13 -3
- data/lib/redd/models/listing.rb +27 -6
- data/lib/redd/models/live_thread.rb +76 -23
- data/lib/redd/models/live_update.rb +46 -0
- data/lib/redd/models/messageable.rb +1 -1
- data/lib/redd/models/mod_action.rb +59 -0
- data/lib/redd/models/model.rb +23 -0
- data/lib/redd/models/moderatable.rb +6 -6
- data/lib/redd/models/modmail.rb +61 -0
- data/lib/redd/models/modmail_conversation.rb +154 -0
- data/lib/redd/models/modmail_message.rb +35 -0
- data/lib/redd/models/more_comments.rb +29 -5
- data/lib/redd/models/multireddit.rb +63 -20
- data/lib/redd/models/paginated_listing.rb +113 -0
- data/lib/redd/models/postable.rb +11 -13
- data/lib/redd/models/private_message.rb +78 -11
- data/lib/redd/models/replyable.rb +2 -2
- data/lib/redd/models/reportable.rb +14 -0
- data/lib/redd/models/searchable.rb +2 -2
- data/lib/redd/models/self.rb +17 -0
- data/lib/redd/models/session.rb +75 -31
- data/lib/redd/models/submission.rb +309 -56
- data/lib/redd/models/subreddit.rb +330 -103
- data/lib/redd/models/trophy.rb +34 -0
- data/lib/redd/models/user.rb +185 -46
- data/lib/redd/models/wiki_page.rb +37 -16
- data/lib/redd/utilities/error_handler.rb +13 -13
- data/lib/redd/utilities/unmarshaller.rb +7 -5
- data/lib/redd/version.rb +1 -1
- data/redd.gemspec +18 -15
- metadata +82 -16
- data/lib/redd/error.rb +0 -53
- data/lib/redd/models/basic_model.rb +0 -80
- data/lib/redd/models/lazy_model.rb +0 -75
- data/lib/redd/models/mod_mail.rb +0 -142
- data/lib/redd/utilities/stream.rb +0 -61
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'model'
|
4
|
+
|
5
|
+
module Redd
|
6
|
+
module Models
|
7
|
+
# A user trophy.
|
8
|
+
class Trophy < Model
|
9
|
+
# @!attribute [r] icon_70px
|
10
|
+
# @return [String] the url for a 70x70 thumbnail icon
|
11
|
+
property :icon_70px, from: :icon_70
|
12
|
+
|
13
|
+
# @!attribute [r] icon_40px
|
14
|
+
# @return [String] the url for a 40x40 thumbnail icon
|
15
|
+
property :icon_40px, from: :icon_40
|
16
|
+
|
17
|
+
# @!attribute [r] name
|
18
|
+
# @return [String] the name of the trophy
|
19
|
+
property :name
|
20
|
+
|
21
|
+
# @!attribute [r] id
|
22
|
+
# @return [String] the trophy id
|
23
|
+
property :id
|
24
|
+
|
25
|
+
# @!attribute [r] award_id
|
26
|
+
# @return [String]
|
27
|
+
property :award_id
|
28
|
+
|
29
|
+
# @!attribute [r] description
|
30
|
+
# @return [String] the trophy description
|
31
|
+
property :description
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/redd/models/user.rb
CHANGED
@@ -1,53 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'model'
|
4
4
|
require_relative 'messageable'
|
5
5
|
|
6
6
|
module Redd
|
7
7
|
module Models
|
8
8
|
# A reddit user.
|
9
|
-
class User <
|
9
|
+
class User < Model
|
10
10
|
include Messageable
|
11
11
|
|
12
|
-
# Create a User from their name.
|
13
|
-
# @param client [APIClient] the api client to initialize the object with
|
14
|
-
# @param id [String] the username
|
15
|
-
# @return [User]
|
16
|
-
def self.from_id(client, 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
|
-
end
|
27
|
-
|
28
|
-
# Compose a message to the moderators of a subreddit.
|
29
|
-
#
|
30
|
-
# @param subject [String] the subject of the message
|
31
|
-
# @param text [String] the message text
|
32
|
-
# @param from [Subreddit, nil] the subreddit to send the message on behalf of
|
33
|
-
def send_message(subject:, text:, from: nil)
|
34
|
-
super(to: get_attribute(:name), subject: subject, text: text, from: from)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Add the user as a friend.
|
38
|
-
# @param note [String] a note for the friend
|
39
|
-
def friend(note = nil)
|
40
|
-
name = get_attribute(:name)
|
41
|
-
body = JSON.generate(note ? { name: name, note: note } : { name: name })
|
42
|
-
@client.request(:put, "/api/v1/me/friends/#{name}", body: body)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Unfriend the user.
|
46
|
-
def unfriend
|
47
|
-
name = get_attribute(:name)
|
48
|
-
@client.request(:delete, "/api/v1/me/friends/#{name}", raw: true, form: { id: name })
|
49
|
-
end
|
50
|
-
|
51
12
|
# Get the appropriate listing.
|
52
13
|
# @param type [:overview, :submitted, :comments, :liked, :disliked, :hidden, :saved, :gilded]
|
53
14
|
# the type of listing to request
|
@@ -65,7 +26,7 @@ module Redd
|
|
65
26
|
# @return [Listing<Submission>]
|
66
27
|
def listing(type, **params)
|
67
28
|
params[:t] = params.delete(:time) if params.key?(:time)
|
68
|
-
|
29
|
+
client.model(:get, "/user/#{read_attribute(:name)}/#{type}.json", params)
|
69
30
|
end
|
70
31
|
|
71
32
|
# @!method overview(**params)
|
@@ -78,20 +39,198 @@ module Redd
|
|
78
39
|
# @!method gilded(**params)
|
79
40
|
#
|
80
41
|
# @see #listing
|
81
|
-
%i
|
42
|
+
%i[overview submitted comments liked disliked hidden saved gilded].each do |type|
|
82
43
|
define_method(type) { |**params| listing(type, **params) }
|
83
44
|
end
|
84
45
|
|
46
|
+
# Compose a message to the moderators of a subreddit.
|
47
|
+
#
|
48
|
+
# @param subject [String] the subject of the message
|
49
|
+
# @param text [String] the message text
|
50
|
+
# @param from [Subreddit, nil] the subreddit to send the message on behalf of
|
51
|
+
def send_message(subject:, text:, from: nil)
|
52
|
+
super(to: read_attribute(:name), subject: subject, text: text, from: from)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Block this user.
|
56
|
+
def block
|
57
|
+
client.post('/api/block_user', account_id: read_attribute(:id))
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Array<Trophy>] this user's trophies
|
61
|
+
def trophies
|
62
|
+
client.get("/api/v1/user/#{read_attribute(:name)}/trophies")
|
63
|
+
.body[:data][:trophies]
|
64
|
+
.map { |t| client.unmarshal(t) }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Unblock a previously blocked user.
|
68
|
+
# @param me [User] (optional) the person doing the unblocking
|
69
|
+
def unblock(me: nil)
|
70
|
+
my_id = 't2_' + (me.is_a?(User) ? user.id : client.get('/api/v1/me').body[:id])
|
71
|
+
# Talk about an unintuitive endpoint
|
72
|
+
client.post('/api/unfriend', container: my_id, name: read_attribute(:name), type: 'enemy')
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add the user as a friend.
|
76
|
+
# @param note [String] a note for the friend
|
77
|
+
def friend(note = nil)
|
78
|
+
name = read_attribute(:name)
|
79
|
+
body = JSON.generate(note ? { name: name, note: note } : { name: name })
|
80
|
+
client.request(:put, "/api/v1/me/friends/#{name}", body: body)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Unfriend the user.
|
84
|
+
def unfriend
|
85
|
+
name = read_attribute(:name)
|
86
|
+
client.request(:delete, "/api/v1/me/friends/#{name}", raw: true, form: { id: name })
|
87
|
+
end
|
88
|
+
|
85
89
|
# Gift a redditor reddit gold.
|
86
90
|
# @param months [Integer] the number of months of gold to gift
|
87
91
|
def gift_gold(months: 1)
|
88
|
-
|
92
|
+
client.post("/api/v1/gold/give/#{read_attribute(:name)}", months: months)
|
89
93
|
end
|
90
94
|
|
95
|
+
# @!attribute [r] name
|
96
|
+
# @return [String] the user's username
|
97
|
+
property :name
|
98
|
+
|
99
|
+
# @!attribute [r] employee?
|
100
|
+
# @return [Boolean] whether the user is a reddit employee
|
101
|
+
property :employee?, from: :is_employee
|
102
|
+
|
103
|
+
# @!attribute [r] features
|
104
|
+
# @return [Hash] a hash of features
|
105
|
+
property :features
|
106
|
+
|
107
|
+
# @!attribute [r] friend?
|
108
|
+
# @return [Boolean] whether the user is your friend
|
109
|
+
property :friend?, from: :is_friend
|
110
|
+
|
111
|
+
# @!attribute [r] no_profanity?
|
112
|
+
# @return [Boolean] whether the user chooses to filter profanity
|
113
|
+
property :no_profanity?, from: :pref_no_profanity
|
114
|
+
|
115
|
+
# @!attribute [r] suspended?
|
116
|
+
# @return [Boolean] whether the user is suspended
|
117
|
+
property :suspended?, from: :is_suspended
|
118
|
+
|
119
|
+
# @!attribute [r] geopopular
|
120
|
+
# @return [String]
|
121
|
+
property :geopopular, from: :pref_geopopular
|
122
|
+
|
123
|
+
# @!attribute [r] subreddit
|
124
|
+
# @return [Subreddit] the user's personal "subreddit"
|
125
|
+
property :subreddit, with: ->(name) { Subreddit.new(client, display_name: name) if name }
|
126
|
+
|
127
|
+
# @!attribute [r] sponsor?
|
128
|
+
# @return [Boolean]
|
129
|
+
property :sponsor?, from: :is_sponsor
|
130
|
+
|
131
|
+
# @!attribute [r] gold_expiration
|
132
|
+
# @return [Time, nil] the time when the user's gold expires
|
133
|
+
property :gold_expiration, with: ->(epoch) { Time.at(epoch) if epoch }
|
134
|
+
|
135
|
+
# @!attribute [r] id
|
136
|
+
# @return [String] the user's base36 id
|
137
|
+
property :id
|
138
|
+
|
139
|
+
# @!attribute [r] profile_image
|
140
|
+
# @return [String] a link to the user's profile image
|
141
|
+
property :profile_image, from: :profile_img
|
142
|
+
|
143
|
+
# @!attribute [r] over_18?
|
144
|
+
# @return [Boolean] whether the user's profile is considered over 18.
|
145
|
+
property :over_18?, from: :profile_over_18
|
146
|
+
|
147
|
+
# @!attribute [r] suspension_expiration
|
148
|
+
# @return [Time, nil] the time when the user's suspension expires
|
149
|
+
property :suspension_expiration, from: :suspension_expiration_utc,
|
150
|
+
with: ->(epoch) { Time.at(epoch) if epoch }
|
151
|
+
|
152
|
+
# @!attribute [r] verified?
|
153
|
+
# @return [Boolean] whether the user is verified (?)
|
154
|
+
property :verified?, from: :verified
|
155
|
+
|
156
|
+
# @!attribute [r] new_modmail_exists?
|
157
|
+
# @return [Boolean] whether the user has mail in the new modmail
|
158
|
+
property :new_modmail_exists?, from: :new_modmail_exists
|
159
|
+
|
160
|
+
# @!attribute [r] over_18?
|
161
|
+
# @return [Boolean] whether the user has indicated they're over 18
|
162
|
+
property :over_18?, from: :over_18
|
163
|
+
|
164
|
+
# @!attribute [r] gold?
|
165
|
+
# @return [Boolean] whether the user currently has gold
|
166
|
+
property :gold?, from: :is_gold
|
167
|
+
|
168
|
+
# @!attribute [r] mod?
|
169
|
+
# @return [Boolean] whether the user is a moderator
|
170
|
+
property :mod?, from: :is_mod
|
171
|
+
|
172
|
+
# @!attribute [r] has_verified_email?
|
173
|
+
# @return [Boolean] whether the user's email has been verified
|
174
|
+
property :has_verified_email?, from: :has_verified_email
|
175
|
+
|
176
|
+
# @!attribute [r] has_mod_mail?
|
177
|
+
# @return [Boolean] whether the user has old-style mod mail
|
178
|
+
property :has_mod_mail?, from: :has_mod_mail
|
179
|
+
|
180
|
+
# @!attribute [r] hidden_from_robots?
|
181
|
+
# @return [Boolean] whether the user chose to hide from Google
|
182
|
+
property :hidden_from_robots?, from: :hide_from_robots
|
183
|
+
|
184
|
+
# @!attribute [r] link_karma
|
185
|
+
# @return [Integer] the user's link karma
|
186
|
+
property :link_karma
|
187
|
+
|
188
|
+
# @!attribute [r] inbox_count
|
189
|
+
# @return [Integer] the number of messages in the user's inbox
|
190
|
+
property :inbox_count
|
191
|
+
|
192
|
+
# @!attribute [r] show_top_karma_subreddits?
|
193
|
+
# @return [Boolean] whether top karma subreddits are shown on the user's page
|
194
|
+
property :show_top_karma_subreddits?, from: :pref_top_karma_subreddits
|
195
|
+
|
196
|
+
# @!attribute [r] has_mail?
|
197
|
+
# @return [Boolean] whether the user has new messages
|
198
|
+
property :has_mail?, from: :has_mail
|
199
|
+
|
200
|
+
# @!attribute [r] show_snoovatar?
|
201
|
+
# @return [Boolean] whether the user's snoovatar is shown
|
202
|
+
property :show_snoovatar?, from: :pref_show_snoovatar
|
203
|
+
|
204
|
+
# @!attribute [r] created_at
|
205
|
+
# @return [Time] the time the user signed up
|
206
|
+
property :created_at, from: :created_utc, with: ->(epoch) { Time.at(epoch) }
|
207
|
+
|
208
|
+
# @!attribute [r] gold_creddits
|
209
|
+
# @return [Integer] the number of gold creddits the user has
|
210
|
+
property :gold_creddits
|
211
|
+
|
212
|
+
# @!attribute [r] in_beta?
|
213
|
+
# @return [Boolean] whether the user is in beta
|
214
|
+
property :in_beta?, from: :in_beta
|
215
|
+
|
216
|
+
# @!attribute [r] comment_karma
|
217
|
+
# @return [Integer] the user's comment karma
|
218
|
+
property :comment_karma
|
219
|
+
|
220
|
+
# @!attribute [r] has_subscribed?
|
221
|
+
# @return [Boolean]
|
222
|
+
property :has_subscribed?, from: :has_subscribed
|
223
|
+
|
91
224
|
private
|
92
225
|
|
93
|
-
def
|
94
|
-
|
226
|
+
def lazer_reload
|
227
|
+
# return load_from_fullname if self[:id] && !self[:name]
|
228
|
+
fully_loaded!
|
229
|
+
client.get("/user/#{read_attribute(:name)}/about").body[:data]
|
230
|
+
end
|
231
|
+
|
232
|
+
def load_from_fullname
|
233
|
+
client.get('/api/user_data_by_account_ids', ids: read_attribute(:id)).body.values.first
|
95
234
|
end
|
96
235
|
end
|
97
236
|
end
|
@@ -1,34 +1,55 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'model'
|
4
4
|
|
5
5
|
module Redd
|
6
6
|
module Models
|
7
7
|
# A reddit user.
|
8
|
-
class WikiPage <
|
8
|
+
class WikiPage < Model
|
9
9
|
# Edit the wiki page.
|
10
10
|
# @param content [String] the new wiki page contents
|
11
11
|
# @param reason [String, nil] an optional reason for editing the page
|
12
12
|
def edit(content, reason: nil)
|
13
|
-
params = { page:
|
13
|
+
params = { page: read_attribute(:title), content: content }
|
14
14
|
params[:reason] = reason if reason
|
15
|
-
|
15
|
+
client.post("/r/#{read_attribute(:subreddit).display_name}/api/wiki/edit", params)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
# @!attribute [r] title
|
19
|
+
# @return [String] the page title
|
20
|
+
property :title, :required
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
# @!attribute [r] subreddit
|
23
|
+
# @return [Subreddit] the wiki page's (optional) subreddit
|
24
|
+
property :subreddit, :nil
|
25
|
+
|
26
|
+
# @!attribute [r] may_revise?
|
27
|
+
# @return [Boolean] not sure, whether you're allowed to edit the page?
|
28
|
+
property :may_revise?, from: :may_revise
|
29
|
+
|
30
|
+
# @!attribute [r] revision_date
|
31
|
+
# @return [Time] the time of the last revision
|
32
|
+
property :revision_date, with: ->(t) { Time.at(t) }
|
33
|
+
|
34
|
+
# @!attribute [r] content_md
|
35
|
+
# @return [String] the markdown version of the content
|
36
|
+
property :content_md
|
37
|
+
|
38
|
+
# @!attribute [r] content_html
|
39
|
+
# @return [String] the html version of the content
|
40
|
+
property :content_html
|
41
|
+
|
42
|
+
# @!attribute [r] revision_by
|
43
|
+
# @return [User] the user who made the last revision
|
44
|
+
property :revision_by, with: ->(res) { User.new(client, res[:data]) }
|
45
|
+
|
46
|
+
private
|
28
47
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
48
|
+
def lazer_reload
|
49
|
+
fully_loaded!
|
50
|
+
path = "/wiki/#{read_attribute(:title)}"
|
51
|
+
path = "/r/#{read_attribute(:subreddit).display_name}#{path}" if self[:subreddit]
|
52
|
+
client.get(path).body[:data]
|
32
53
|
end
|
33
54
|
end
|
34
55
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../
|
3
|
+
require_relative '../errors'
|
4
4
|
|
5
5
|
module Redd
|
6
6
|
module Utilities
|
@@ -11,15 +11,15 @@ module Redd
|
|
11
11
|
INSUFFICIENT_SCOPE = 'insufficient_scope'
|
12
12
|
|
13
13
|
HTTP_ERRORS = {
|
14
|
-
400 =>
|
15
|
-
403 =>
|
16
|
-
404 =>
|
17
|
-
429 =>
|
18
|
-
500 =>
|
19
|
-
502 =>
|
20
|
-
503 =>
|
21
|
-
504 =>
|
22
|
-
}
|
14
|
+
400 => Errors::BadRequest,
|
15
|
+
403 => Errors::Forbidden,
|
16
|
+
404 => Errors::NotFound,
|
17
|
+
429 => Errors::TooManyRequests,
|
18
|
+
500 => Errors::ServerError,
|
19
|
+
502 => Errors::ServerError,
|
20
|
+
503 => Errors::ServerError,
|
21
|
+
504 => Errors::ServerError
|
22
|
+
}
|
23
23
|
|
24
24
|
def check_error(res, raw:)
|
25
25
|
# Check for status code-based errors first and return it if we found one.
|
@@ -38,14 +38,14 @@ module Redd
|
|
38
38
|
def invalid_access_error(res)
|
39
39
|
return nil unless res.code == 401 && res.headers[AUTH_HEADER] &&
|
40
40
|
res.headers[AUTH_HEADER].include?(INVALID_TOKEN)
|
41
|
-
InvalidAccess.new(res)
|
41
|
+
Errors::InvalidAccess.new(res)
|
42
42
|
end
|
43
43
|
|
44
44
|
# Deal with an error caused by not having enough the correct scope
|
45
45
|
def insufficient_scope_error(res)
|
46
46
|
return nil unless res.code == 403 && res.headers[AUTH_HEADER] &&
|
47
47
|
res.headers[AUTH_HEADER].include?(INSUFFICIENT_SCOPE)
|
48
|
-
InsufficientScope.new(res)
|
48
|
+
Errors::InsufficientScope.new(res)
|
49
49
|
end
|
50
50
|
|
51
51
|
# Deal with an error signalled by the HTTP response code.
|
@@ -57,7 +57,7 @@ module Redd
|
|
57
57
|
def api_error(res)
|
58
58
|
return nil unless res.body.is_a?(Hash) && res.body[:json] && res.body[:json][:errors] &&
|
59
59
|
!res.body[:json][:errors].empty?
|
60
|
-
APIError.new(res)
|
60
|
+
Errors::APIError.new(res)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -7,17 +7,19 @@ module Redd
|
|
7
7
|
# Contains the mapping from 'kind' strings to classes.
|
8
8
|
# TODO: UserList type!
|
9
9
|
MAPPING = {
|
10
|
+
'Listing' => Models::Listing,
|
10
11
|
't1' => Models::Comment,
|
11
12
|
't2' => Models::User,
|
12
13
|
't3' => Models::Submission,
|
13
14
|
't4' => Models::PrivateMessage,
|
14
15
|
't5' => Models::Subreddit,
|
16
|
+
't6' => Models::Trophy,
|
15
17
|
'more' => Models::MoreComments,
|
16
18
|
'wikipage' => Models::WikiPage,
|
17
|
-
'modaction' => Models::
|
19
|
+
'modaction' => Models::ModAction,
|
18
20
|
'LabeledMulti' => Models::Multireddit,
|
19
|
-
'LiveUpdate' => Models::
|
20
|
-
}
|
21
|
+
'LiveUpdate' => Models::LiveUpdate
|
22
|
+
}
|
21
23
|
|
22
24
|
def initialize(client)
|
23
25
|
@client = client
|
@@ -25,7 +27,7 @@ module Redd
|
|
25
27
|
|
26
28
|
def unmarshal(res)
|
27
29
|
# I'm loving the hell out of this pattern.
|
28
|
-
model = js_listing(res) || js_model(res) ||
|
30
|
+
model = js_listing(res) || js_model(res) || api_model(res)
|
29
31
|
raise "cannot unmarshal: #{res.inspect}" if model.nil?
|
30
32
|
model
|
31
33
|
end
|
@@ -43,7 +45,7 @@ module Redd
|
|
43
45
|
def js_model(res)
|
44
46
|
# FIXME: deprecate this? this shouldn't be happening in the API, so this is better handled
|
45
47
|
# in the respective classes.
|
46
|
-
Models::
|
48
|
+
Models::Model.new(@client, res[:json][:data]) if res[:json] && res[:json][:data]
|
47
49
|
end
|
48
50
|
|
49
51
|
# Unmarshal API-provided listings.
|