redd 0.8.8 → 0.9.0.pre.1

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/CONTRIBUTING.md +63 -0
  4. data/Guardfile +7 -0
  5. data/README.md +6 -5
  6. data/Rakefile +1 -1
  7. data/TODO.md +423 -0
  8. data/bin/console +91 -77
  9. data/bin/guard +2 -0
  10. data/lib/redd.rb +7 -5
  11. data/lib/redd/api_client.rb +2 -3
  12. data/lib/redd/auth_strategies/auth_strategy.rb +7 -2
  13. data/lib/redd/auth_strategies/script.rb +7 -0
  14. data/lib/redd/auth_strategies/userless.rb +7 -0
  15. data/lib/redd/auth_strategies/web.rb +6 -1
  16. data/lib/redd/client.rb +0 -3
  17. data/lib/redd/errors.rb +56 -0
  18. data/lib/redd/middleware.rb +10 -8
  19. data/lib/redd/models/access.rb +30 -18
  20. data/lib/redd/models/comment.rb +185 -27
  21. data/lib/redd/models/front_page.rb +16 -36
  22. data/lib/redd/models/gildable.rb +1 -1
  23. data/lib/redd/models/inboxable.rb +13 -3
  24. data/lib/redd/models/listing.rb +27 -6
  25. data/lib/redd/models/live_thread.rb +76 -23
  26. data/lib/redd/models/live_update.rb +46 -0
  27. data/lib/redd/models/messageable.rb +1 -1
  28. data/lib/redd/models/mod_action.rb +59 -0
  29. data/lib/redd/models/model.rb +23 -0
  30. data/lib/redd/models/moderatable.rb +6 -6
  31. data/lib/redd/models/modmail.rb +61 -0
  32. data/lib/redd/models/modmail_conversation.rb +154 -0
  33. data/lib/redd/models/modmail_message.rb +35 -0
  34. data/lib/redd/models/more_comments.rb +29 -5
  35. data/lib/redd/models/multireddit.rb +63 -20
  36. data/lib/redd/models/paginated_listing.rb +113 -0
  37. data/lib/redd/models/postable.rb +11 -13
  38. data/lib/redd/models/private_message.rb +78 -11
  39. data/lib/redd/models/replyable.rb +2 -2
  40. data/lib/redd/models/reportable.rb +14 -0
  41. data/lib/redd/models/searchable.rb +2 -2
  42. data/lib/redd/models/self.rb +17 -0
  43. data/lib/redd/models/session.rb +75 -31
  44. data/lib/redd/models/submission.rb +309 -56
  45. data/lib/redd/models/subreddit.rb +330 -103
  46. data/lib/redd/models/trophy.rb +34 -0
  47. data/lib/redd/models/user.rb +185 -46
  48. data/lib/redd/models/wiki_page.rb +37 -16
  49. data/lib/redd/utilities/error_handler.rb +13 -13
  50. data/lib/redd/utilities/unmarshaller.rb +7 -5
  51. data/lib/redd/version.rb +1 -1
  52. data/redd.gemspec +18 -15
  53. metadata +82 -16
  54. data/lib/redd/error.rb +0 -53
  55. data/lib/redd/models/basic_model.rb +0 -80
  56. data/lib/redd/models/lazy_model.rb +0 -75
  57. data/lib/redd/models/mod_mail.rb +0 -142
  58. data/lib/redd/utilities/stream.rb +0 -61
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Redd
4
- VERSION = '0.8.8'
4
+ VERSION = '0.9.0.pre.1'
5
5
  end
@@ -1,35 +1,38 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  lib = File.expand_path('../lib', __FILE__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require 'redd/version'
7
6
 
8
- Gem::Specification.new do |spec|
9
- spec.name = 'redd'
10
- spec.version = Redd::VERSION
11
- spec.authors = ['Avinash Dwarapu']
12
- spec.email = ['avinash@dwarapu.me']
7
+ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
8
+ spec.name = 'redd'
9
+ spec.version = Redd::VERSION
10
+ spec.authors = ['Avinash Dwarapu']
11
+ spec.email = ['avinash@dwarapu.me']
12
+ spec.summary = 'A batteries-included API wrapper for reddit.'
13
+ spec.homepage = 'https://github.com/avinashbot/redd'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 2.1.0'
13
16
 
14
- spec.summary = 'A batteries-included API wrapper for reddit.'
15
- spec.homepage = 'https://github.com/avinashbot/redd'
16
- spec.license = 'MIT'
17
-
18
- spec.files = `git ls-files -z`
19
- .split("\x0")
20
- .reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
21
20
  spec.bindir = 'exe'
22
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
22
  spec.require_paths = ['lib']
24
23
 
25
24
  spec.add_dependency 'http', '~> 2.2'
25
+ spec.add_dependency 'lazy_lazer', '~> 0.6'
26
26
 
27
+ spec.add_development_dependency 'pry', '~> 0.10'
27
28
  spec.add_development_dependency 'bundler', '~> 1.14'
28
29
  spec.add_development_dependency 'rake', '~> 12.0'
29
- spec.add_development_dependency 'rubocop', '~> 0.47'
30
- spec.add_development_dependency 'pry', '~> 0.10'
30
+ spec.add_development_dependency 'yard', '~> 0.9.9'
31
+ spec.add_development_dependency 'rubocop', '~> 0.50'
31
32
 
32
33
  spec.add_development_dependency 'rspec', '~> 3.5'
34
+ spec.add_development_dependency 'guard', '~> 2.14'
35
+ spec.add_development_dependency 'guard-rspec', '~> 4.7'
33
36
  spec.add_development_dependency 'simplecov', '~> 0.13'
34
37
  spec.add_development_dependency 'webmock', '~> 2.3'
35
38
  spec.add_development_dependency 'vcr', '~> 3.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.8
4
+ version: 0.9.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avinash Dwarapu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-02 00:00:00.000000000 Z
11
+ date: 2017-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lazy_lazer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -53,33 +81,33 @@ dependencies:
53
81
  - !ruby/object:Gem::Version
54
82
  version: '12.0'
55
83
  - !ruby/object:Gem::Dependency
56
- name: rubocop
84
+ name: yard
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - "~>"
60
88
  - !ruby/object:Gem::Version
61
- version: '0.47'
89
+ version: 0.9.9
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
- version: '0.47'
96
+ version: 0.9.9
69
97
  - !ruby/object:Gem::Dependency
70
- name: pry
98
+ name: rubocop
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
101
  - - "~>"
74
102
  - !ruby/object:Gem::Version
75
- version: '0.10'
103
+ version: '0.50'
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
108
  - - "~>"
81
109
  - !ruby/object:Gem::Version
82
- version: '0.10'
110
+ version: '0.50'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: rspec
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +122,34 @@ dependencies:
94
122
  - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '3.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.14'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2.14'
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard-rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '4.7'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '4.7'
97
153
  - !ruby/object:Gem::Dependency
98
154
  name: simplecov
99
155
  requirement: !ruby/object:Gem::Requirement
@@ -148,11 +204,15 @@ files:
148
204
  - ".rspec"
149
205
  - ".rubocop.yml"
150
206
  - ".travis.yml"
207
+ - CONTRIBUTING.md
151
208
  - Gemfile
209
+ - Guardfile
152
210
  - LICENSE.txt
153
211
  - README.md
154
212
  - Rakefile
213
+ - TODO.md
155
214
  - bin/console
215
+ - bin/guard
156
216
  - bin/setup
157
217
  - lib/redd.rb
158
218
  - lib/redd/api_client.rb
@@ -161,34 +221,40 @@ files:
161
221
  - lib/redd/auth_strategies/userless.rb
162
222
  - lib/redd/auth_strategies/web.rb
163
223
  - lib/redd/client.rb
164
- - lib/redd/error.rb
224
+ - lib/redd/errors.rb
165
225
  - lib/redd/middleware.rb
166
226
  - lib/redd/models/access.rb
167
- - lib/redd/models/basic_model.rb
168
227
  - lib/redd/models/comment.rb
169
228
  - lib/redd/models/front_page.rb
170
229
  - lib/redd/models/gildable.rb
171
230
  - lib/redd/models/inboxable.rb
172
- - lib/redd/models/lazy_model.rb
173
231
  - lib/redd/models/listing.rb
174
232
  - lib/redd/models/live_thread.rb
233
+ - lib/redd/models/live_update.rb
175
234
  - lib/redd/models/messageable.rb
176
- - lib/redd/models/mod_mail.rb
235
+ - lib/redd/models/mod_action.rb
236
+ - lib/redd/models/model.rb
177
237
  - lib/redd/models/moderatable.rb
238
+ - lib/redd/models/modmail.rb
239
+ - lib/redd/models/modmail_conversation.rb
240
+ - lib/redd/models/modmail_message.rb
178
241
  - lib/redd/models/more_comments.rb
179
242
  - lib/redd/models/multireddit.rb
243
+ - lib/redd/models/paginated_listing.rb
180
244
  - lib/redd/models/postable.rb
181
245
  - lib/redd/models/private_message.rb
182
246
  - lib/redd/models/replyable.rb
247
+ - lib/redd/models/reportable.rb
183
248
  - lib/redd/models/searchable.rb
249
+ - lib/redd/models/self.rb
184
250
  - lib/redd/models/session.rb
185
251
  - lib/redd/models/submission.rb
186
252
  - lib/redd/models/subreddit.rb
253
+ - lib/redd/models/trophy.rb
187
254
  - lib/redd/models/user.rb
188
255
  - lib/redd/models/wiki_page.rb
189
256
  - lib/redd/utilities/error_handler.rb
190
257
  - lib/redd/utilities/rate_limiter.rb
191
- - lib/redd/utilities/stream.rb
192
258
  - lib/redd/utilities/unmarshaller.rb
193
259
  - lib/redd/version.rb
194
260
  - logo.png
@@ -205,12 +271,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
271
  requirements:
206
272
  - - ">="
207
273
  - !ruby/object:Gem::Version
208
- version: '0'
274
+ version: 2.1.0
209
275
  required_rubygems_version: !ruby/object:Gem::Requirement
210
276
  requirements:
211
- - - ">="
277
+ - - ">"
212
278
  - !ruby/object:Gem::Version
213
- version: '0'
279
+ version: 1.3.1
214
280
  requirements: []
215
281
  rubyforge_project:
216
282
  rubygems_version: 2.6.8
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Redd
4
- # An error raised by {Redd::Middleware} when there was an error returned by reddit.
5
- class TokenRetrievalError < StandardError; end
6
-
7
- # An error with the API.
8
- class APIError < StandardError
9
- attr_reader :response, :name
10
-
11
- def initialize(response)
12
- @response = response
13
- @name, message = response.body[:json][:errors][0]
14
- super(message)
15
- end
16
- end
17
-
18
- # Represents an error from reddit returned in a response.
19
- class ResponseError < StandardError
20
- attr_accessor :response
21
-
22
- def initialize(response)
23
- super(response.raw_body.length <= 80 ? response.raw_body : "#{response.raw_body[0..80]}...")
24
- @response = response
25
- end
26
- end
27
-
28
- # An error returned by AuthStrategy.
29
- # @note A common cause of this error is not having a bot account registered as a developer on
30
- # the app.
31
- class AuthenticationError < ResponseError; end
32
-
33
- # An error with Redd, probably (let me know!)
34
- class BadRequest < ResponseError; end
35
-
36
- # Whatever it is, you're not allowed to do it.
37
- class Forbidden < ResponseError; end
38
-
39
- # You don't have the correct scope to do this.
40
- class InsufficientScope < ResponseError; end
41
-
42
- # The access object supplied was invalid.
43
- class InvalidAccess < ResponseError; end
44
-
45
- # Returned when reddit raises a 404 error.
46
- class NotFound < ResponseError; end
47
-
48
- # Too many requests and not enough rate limiting.
49
- class TooManyRequests < ResponseError; end
50
-
51
- # An unknown error on reddit's end. Usually fixed with a retry.
52
- class ServerError < ResponseError; end
53
- end
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Redd
4
- module Models
5
- # The base class for all models.
6
- class BasicModel
7
- # @abstract Create an instance from a value.
8
- # @param _client [APIClient] the api client to initialize the object with
9
- # @param _value [Object] the object to coerce
10
- # @return [BasicModel]
11
- def self.from_id(_client, _value)
12
- # TODO: abstract this out?
13
- raise "coercion not implemented for #{name}"
14
- end
15
-
16
- # @return [APIClient] the client the model was initialized with
17
- attr_reader :client
18
-
19
- # Create a non-lazily initialized class.
20
- # @param client [APIClient] the client that the model uses to make requests
21
- # @param attributes [Hash] the class's attributes
22
- def initialize(client, attributes = {})
23
- @client = client
24
- @attributes = attributes
25
- after_initialize
26
- end
27
-
28
- # @return [Hash] a Hash representation of the object
29
- def to_h
30
- @attributes
31
- end
32
-
33
- # @return [Array<self>] an array representation of self
34
- def to_ary
35
- [self]
36
- end
37
-
38
- # @return [String] an easily readable representation of the object
39
- def inspect
40
- "#{super}\n" + @attributes.map { |a, v| " #{a}: #{v}" }.join("\n")
41
- end
42
-
43
- # Checks whether an attribute is supported by method_missing.
44
- # @param method_name [Symbol] the method name or attribute to check
45
- # @param include_private [Boolean] whether to also include private methods
46
- # @return [Boolean] whether the method is handled by method_missing
47
- def respond_to_missing?(method_name, include_private = false)
48
- @attributes.key?(method_name) || @attributes.key?(depredicate(method_name)) || super
49
- end
50
-
51
- # Return an attribute or raise a NoMethodError if it doesn't exist.
52
- # @param method_name [Symbol] the name of the attribute
53
- # @return [Object] the result of the attribute check
54
- def method_missing(method_name, *args, &block)
55
- return get_attribute(method_name) if @attributes.key?(method_name)
56
- return get_attribute(depredicate(method_name)) if @attributes.key?(depredicate(method_name))
57
- super
58
- end
59
-
60
- private
61
-
62
- # @abstract Lets us plug in custom code without making a mess
63
- def after_initialize; end
64
-
65
- # Remove a trailing '?' from a symbol name.
66
- # @param method_name [Symbol] the symbol to "depredicate"
67
- # @return [Symbol] the symbol but with the '?' removed
68
- def depredicate(method_name)
69
- method_name.to_s.chomp('?').to_sym
70
- end
71
-
72
- # Get an attribute, raising KeyError if not present.
73
- # @param name [Symbol] the attribute to check and get
74
- # @return [Object] the value of the attribute
75
- def get_attribute(name)
76
- @attributes.fetch(name)
77
- end
78
- end
79
- end
80
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'basic_model'
4
-
5
- module Redd
6
- module Models
7
- # The base class for lazily-initializable models.
8
- class LazyModel < BasicModel
9
- # Create a lazily initialized class.
10
- # @param client [APIClient] the client that the model uses to make requests
11
- # @param base_attributes [Hash] the already-known attributes that do not need to be looked up
12
- # @yield [client] the model's client
13
- # @yieldparam client [APIClient]
14
- # @yieldreturn [Hash] the response of "initializing" the lazy model
15
- def initialize(client, base_attributes = {}, &block)
16
- super(client, base_attributes)
17
- @lazy_loader = block
18
- @definitely_fully_loaded = false
19
- end
20
-
21
- # Force the object to make a request to reddit.
22
- # @return [self]
23
- def force_load
24
- @attributes.merge!(@lazy_loader ? @lazy_loader.call(@client) : default_loader)
25
- @definitely_fully_loaded = true
26
- after_initialize
27
- self
28
- end
29
- alias reload force_load
30
-
31
- # Convert the object to a hash, making a request to fetch additional attributes if needed.
32
- # @return [Hash]
33
- def to_h
34
- ensure_fully_loaded
35
- super
36
- end
37
-
38
- # Checks whether an attribute is supported by method_missing. Since we don't know whether an
39
- # attribute exists until we load it, we have to respond true until we load it.
40
- # @param method_name [Symbol] the method name or attribute to check
41
- # @param include_private [Boolean] whether to also include private methods
42
- # @return [Boolean] whether the method is handled by method_missing
43
- def respond_to_missing?(method_name, include_private = false)
44
- @definitely_fully_loaded ? super : true
45
- end
46
-
47
- # Return an attribute or raise a NoMethodError if it doesn't exist.
48
- # @param method_name [Symbol] the name of the attribute
49
- # @return [Object] the result of the attribute check
50
- def method_missing(method_name, *args, &block)
51
- ensure_fully_loaded unless @attributes.key?(method_name)
52
- super
53
- end
54
-
55
- private
56
-
57
- # @abstract A lazy loader to use when one is not provided.
58
- def default_loader
59
- {}
60
- end
61
-
62
- # Make sure the model is loaded at least once.
63
- def ensure_fully_loaded
64
- force_load unless @definitely_fully_loaded
65
- end
66
-
67
- # Gets the attribute and loads it if it may be available from the response.
68
- def get_attribute(name)
69
- # XXX: Replace get_attribute calls with simple method calls?
70
- ensure_fully_loaded unless @attributes.key?(name)
71
- super
72
- end
73
- end
74
- end
75
- end