forrst 0.1.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.
data/.gems ADDED
@@ -0,0 +1,17 @@
1
+ # .gems generated gem export file. Note that any env variable settings will be missing. Append these after using a ';' field separator
2
+ addressable -v2.2.6
3
+ bundler -v1.0.14
4
+ diff-lcs -v1.1.2
5
+ faraday -v0.6.1
6
+ forrst -v0.1a
7
+ json -v1.5.1
8
+ multi_json -v1.0.3
9
+ multipart-post -v1.1.2
10
+ oauth2 -v0.4.1
11
+ rack -v1.3.0
12
+ rake -v0.9.1
13
+ rspec -v2.6.0
14
+ rspec-core -v2.6.3
15
+ rspec-expectations -v2.6.0
16
+ rspec-mocks -v2.6.0
17
+ yard -v0.7.1
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create 1.9.2@forrst
@@ -0,0 +1,10 @@
1
+ script: "rvm gemset import .gems; rake test"
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.8.7
5
+ - rbx
6
+ - jruby
7
+
8
+ notifications:
9
+ recipients:
10
+ - info@yorickpeterse.com
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.1 - June 5th, 2011
4
+
5
+ The first public release of the library.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011, Yorick Peterse
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ .gems
2
+ .rvmrc
3
+ .travis.yml
4
+ CHANGELOG.md
5
+ LICENSE
6
+ MANIFEST
7
+ README.md
8
+ Rakefile
9
+ lib/.gitkeep
10
+ lib/forrst/.gitkeep
11
+ lib/forrst/comment.rb
12
+ lib/forrst/monkeys/hash.rb
13
+ lib/forrst/post.rb
14
+ lib/forrst/user.rb
15
+ lib/forrst/version.rb
16
+ lib/forrst.rb
17
+ task/build.rake
18
+ task/test.rake
@@ -0,0 +1,79 @@
1
+ # Forrst
2
+
3
+ **IMPORTANT:** this library is still in the early stages of development. More details will
4
+ be added once it reaches a stable version.
5
+
6
+ forrst is a Ruby library for the [Forrst][forrst] API. This implementation aims to become
7
+ an implementation that focuses on ease of use, minimal amount of dependencies and
8
+ stability. I'm also aiming for support of all Ruby distributions such as JRuby and MRI.
9
+
10
+ ## Example
11
+
12
+ require 'rubygems'
13
+ require 'forrst'
14
+
15
+ Forrst.configure do |config|
16
+ config.id = '123'
17
+ config.secret = '123'
18
+ config.access_token = '123'
19
+ end
20
+
21
+ # Get a single user
22
+ user = Forrst::User['YorickPeterse']
23
+ user.name # => 'Yorick Peterse'
24
+ user.twitter # => 'YorickPeterse'
25
+
26
+ # Get a bunch of posts
27
+ posts = Forrst::Post.find(:type => :code, :sort => :popular)
28
+ posts.each do |post|
29
+ puts post.title
30
+ puts post.user.username
31
+ end
32
+
33
+ # Or get a single post by it's ID or tiny ID
34
+ post = Forrst::Post[123]
35
+ post = Forrst::Post['YJp']
36
+
37
+ post.title # => 'Some post title'
38
+
39
+ post.comments.each do |comment|
40
+ puts comment.body
41
+ end
42
+
43
+ ## Requirements & Installation
44
+
45
+ * Ruby 1.8.7, Rubinius, JRuby or Ruby 1.9.2 (1.9.1 and 1.9 are untested)
46
+ * An authenticated application (not available at the moment)
47
+ * RVM (when developing the library itself)
48
+
49
+ Installing the gem can be done in a single command:
50
+
51
+ $ gem install forrst
52
+
53
+ If you want to submit pull requests or just check out the source code you should run the
54
+ following commands instead:
55
+
56
+ $ git clone git://github.com/YorickPeterse/Forrst.git forrst
57
+ $ cd forrst
58
+ $ rvm gemset import .gems
59
+ $ rake test
60
+
61
+ The command `rake test` is not required but recommended as it will check to see if your
62
+ environment is running the tests properly.
63
+
64
+ ## Contributing
65
+
66
+ Contributions are more than welcome as long as they follow the following guidelines:
67
+
68
+ * Don't break compatibility with Ruby distributions such as JRuby and Rubinius.
69
+ * Document your code.
70
+ * Use Unix line endings (`\n`)
71
+ * Don't add bullshit code just because you like the way it's named or because you're used
72
+ to. New code (or modified code) should be useful.
73
+
74
+ ## License
75
+
76
+ This API is licensed under the MIT license. A copy of this license can be found in the
77
+ file "LICENSE".
78
+
79
+ [forrst]: http://forrst.com/
@@ -0,0 +1,7 @@
1
+ require File.expand_path('../lib/forrst', __FILE__)
2
+
3
+ task_dir = File.expand_path('../task', __FILE__)
4
+
5
+ Dir.glob("#{task_dir}/*.rake").each do |f|
6
+ import(f)
7
+ end
File without changes
@@ -0,0 +1,96 @@
1
+ require 'rubygems'
2
+ require 'oauth2'
3
+ require 'json'
4
+ require 'date'
5
+
6
+ ['version', 'monkeys/hash', 'user', 'post', 'comment'].each do |file|
7
+ require File.expand_path("../forrst/#{file}", __FILE__)
8
+ end
9
+
10
+ ##
11
+ # The Forrst gem is an API library for the Forrst API that focuses on stability, ease of
12
+ # use and minimal dependencies.
13
+ #
14
+ # @author Yorick Peterse
15
+ # @since 0.1a
16
+ #
17
+ module Forrst
18
+ ##
19
+ # The URL to the API endpoint.
20
+ #
21
+ # @author Yorick Peterse
22
+ # @since 0.1a
23
+ #
24
+ URL = 'http://forrst.com/api/v2/'
25
+
26
+ ##
27
+ # URL relative to Forrst::URL that contains all the API statistics.
28
+ #
29
+ # @author Yorick Peterse
30
+ # @since 0.1a
31
+ #
32
+ StatisticsURL = '/stats'
33
+
34
+ ##
35
+ # A string containing the date format used for all dates returned by the API.
36
+ #
37
+ # @author Yorick Peterse
38
+ # @since 0.1a
39
+ #
40
+ DateFormat = '%Y-%m-%d %H:%M:%S'
41
+
42
+ class << self
43
+ # The access token returned once a client has been authorized.
44
+ attr_accessor :access_token
45
+
46
+ # The ID of the application as provided by Forrst.
47
+ attr_accessor :id
48
+
49
+ # The secret of the application as provided by Forrst.
50
+ attr_accessor :secret
51
+
52
+ # Instance of OAuth2::Client.
53
+ attr_accessor :oauth
54
+
55
+ ##
56
+ # Sets various configuration options in the module so that they can be used by other
57
+ # parts of this gem.
58
+ #
59
+ # @example
60
+ # Forrst.configure do |client|
61
+ # client.access_token = '1234abc'
62
+ # end
63
+ #
64
+ # @author Yorick Peterse
65
+ # @since 0.1a
66
+ # @yield self
67
+ #
68
+ def configure
69
+ yield self
70
+
71
+ @oauth = OAuth2::Client.new(@id, @secret, :site => URL)
72
+ end
73
+
74
+ ##
75
+ # Gets a set of statistics from the API server.
76
+ #
77
+ # @example
78
+ # stats = Forrst.statistics
79
+ # stats[:limit] # => 150
80
+ #
81
+ # @author Yorick Peterse
82
+ # @since 0.1a
83
+ # @return [Hash]
84
+ #
85
+ def statistics
86
+ response = @oauth.request(:get, StatisticsURL)
87
+ response = JSON.load(response)
88
+ hash = {
89
+ :limit => response['resp']['rate_limit'].to_i,
90
+ :calls => response['resp']['calls_made'].to_i
91
+ }
92
+
93
+ return hash
94
+ end
95
+ end # class << self
96
+ end # Forrst
File without changes
@@ -0,0 +1,69 @@
1
+ module Forrst
2
+ ##
3
+ # Forrst::Comment is a class used for individual comments.
4
+ #
5
+ # @author Yorick Peterse
6
+ # @since 0.1a
7
+ #
8
+ class Comment
9
+ ##
10
+ # The ID of the comment.
11
+ #
12
+ # @author Yorick Peterse
13
+ # @since 0.1a
14
+ #
15
+ attr_reader :comment_id
16
+
17
+ ##
18
+ # An instance of Forrst::User containing the details of the user.
19
+ #
20
+ # @author Yorick Peterse
21
+ # @since 0.1a
22
+ #
23
+ attr_reader :user
24
+
25
+ ##
26
+ # The body of the comment.
27
+ #
28
+ # @author Yorick Peterse
29
+ # @since 0.1a
30
+ #
31
+ attr_reader :body
32
+
33
+ ##
34
+ # The date and time on which the comment was created.
35
+ #
36
+ # @author Yorick Peterse
37
+ # @since 0.1a
38
+ #
39
+ attr_reader :created_at
40
+
41
+ ##
42
+ # The date and time on which the comment was updated.
43
+ #
44
+ # @author Yorick Peterse
45
+ # @since 0.1a
46
+ #
47
+ attr_reader :updated_at
48
+
49
+ ##
50
+ # Creates a new instance of Forrst::Comment and parses the response (either in JSON or
51
+ # as a has).
52
+ #
53
+ # @author Yorick Peterse
54
+ # @since 0.1a
55
+ # @param [String/Hash] response The API response sent back from the server.
56
+ #
57
+ def initialize(response)
58
+ if response.class != Hash
59
+ response = JSON.load(response)
60
+ end
61
+
62
+ @comment_id = response['id']
63
+ @user = Forrst::User.new(response['user'])
64
+ @body = response['body']
65
+ @created_at = Date.strptime(response['created_at'], Forrst::DateFormat)
66
+ @updated_at = Date.strptime(response['updated_at'], Forrst::DateFormat)
67
+ end
68
+ end # Comment
69
+ end # Forrst
@@ -0,0 +1,26 @@
1
+ #:nodoc:
2
+ class Hash < Object
3
+ ##
4
+ # Given a set of keys this method will create a new hash with those keys and their
5
+ # values.
6
+ #
7
+ # @example
8
+ # {:name => "Chuck Norris", :age => 71}.subset(:age) # => {:age => 71}
9
+ #
10
+ # @author Yorick Peterse
11
+ # @since 0.1a
12
+ # @param [Array] keys The keys to retrieve from the hash.
13
+ # @return [Hash]
14
+ #
15
+ def subset(*keys)
16
+ new_hash = {}
17
+
18
+ keys.each do |k|
19
+ if self.key?(k)
20
+ new_hash[k] = self[k]
21
+ end
22
+ end
23
+
24
+ return new_hash
25
+ end
26
+ end # Hash
@@ -0,0 +1,405 @@
1
+ module Forrst
2
+ ##
3
+ # Forrst::Post is the class that represents a single post. Posts can be one of the
4
+ # following types:
5
+ #
6
+ # * code
7
+ # * snap
8
+ # * question
9
+ # * link
10
+ #
11
+ # Based on these types certain fields may not be set. For example, the description()
12
+ # method will return a nil value in case the post type is set to "question" as those
13
+ # don't get an extra description.
14
+ #
15
+ # Retrieving a single post or multiple posts can be done using Forrst::Post.[] and
16
+ # Forrst::Post.find(). If you want to retrieve multiple posts you'll have to use find(),
17
+ # if you only want to retrieve a single post you use []():
18
+ #
19
+ # # Retrieves all code posts.
20
+ # Forrst::Post.find(:type => :code).each do |post|
21
+ # puts post.title
22
+ # end
23
+ #
24
+ # # Retrieve's the post with ID 123
25
+ # post = Forrst::Post[123]
26
+ # puts post.title
27
+ #
28
+ # Each post will also contain the method comments(). This method sends an authenticated
29
+ # GET request to the Forrst server to retrieve all comments for the specified posts.
30
+ # This works as following:
31
+ #
32
+ # post.comments.each do |comment|
33
+ # puts comment.body
34
+ # end
35
+ #
36
+ # Note that similar to Forrst::User#posts all comments are lazy-loaded as the API
37
+ # provides no means of eager loading all comments. Use with care or you might risk
38
+ # getting your ass blocked.
39
+ #
40
+ # Just like the class Forrst::User this class has a few shortcut methods for checking
41
+ # the type of post:
42
+ #
43
+ # * code?
44
+ # * snap?
45
+ # * question?
46
+ # * link?
47
+ #
48
+ # All of these will return true or false depending on the post type.
49
+ #
50
+ # @author Yorick Peterse
51
+ # @since 0.1a
52
+ #
53
+ class Post
54
+ ##
55
+ # URL relative to Forrst::URL that contains the details of a single post.
56
+ #
57
+ # @author Yorick Peterse
58
+ # @since 0.1a
59
+ #
60
+ ShowURL = '/posts/show'
61
+
62
+ ##
63
+ # URL relative to Forrst::URL that contains a list of all posts.
64
+ #
65
+ # @author Yorick Peterse
66
+ # @since 0.1
67
+ #
68
+ ListURL = '/posts/list'
69
+
70
+ ##
71
+ # URL relative to Forrst::URL that contains all the comments for a given post.
72
+ #
73
+ # @author Yorick Peterse
74
+ # @since 0.1a
75
+ #
76
+ CommentsURL = '/posts/comments'
77
+
78
+ ##
79
+ # The ID of the post.
80
+ #
81
+ # @author Yorick Peterse
82
+ # @since 0.1a
83
+ #
84
+ attr_reader :post_id
85
+
86
+ ##
87
+ # The "slug" that's added to the URL.
88
+ #
89
+ # @author Yorick Peterse
90
+ # @since 0.1a
91
+ #
92
+ attr_reader :tiny_id
93
+
94
+ ##
95
+ # The type of post ("code" for example).
96
+ #
97
+ # @author Yorick Peterse
98
+ # @since 0.1a
99
+ #
100
+ attr_reader :type
101
+
102
+ ##
103
+ # The URL to the post on Forrst.
104
+ #
105
+ # @author Yorick Peterse
106
+ # @since 0.1a
107
+ #
108
+ attr_reader :post_url
109
+
110
+ ##
111
+ # The date and time on which the post was created. The value of this attribute is an
112
+ # instance of the Date class.
113
+ #
114
+ # @author Yorick Peterse
115
+ # @since 0.1a
116
+ #
117
+ attr_reader :created_at
118
+
119
+ ##
120
+ # The date and time on which the post was updated. The value of this attribute is an
121
+ # instance of the Date class.
122
+ #
123
+ # @author Yorick Peterse
124
+ # @since 0.1a
125
+ #
126
+ attr_reader :updated_at
127
+
128
+ ##
129
+ # The author of the post.
130
+ #
131
+ # @author Yorick Peterse
132
+ # @since 0.1a
133
+ #
134
+ attr_reader :user
135
+
136
+ ##
137
+ # Boolean that indicates if the post has been published or not.
138
+ #
139
+ # @author Yorick Peterse
140
+ # @since 0.1a
141
+ #
142
+ attr_reader :published
143
+
144
+ ##
145
+ # Boolean that indicates if the post is a public post or requires users to log in.
146
+ #
147
+ # @author Yorick Peterse
148
+ # @since 0.1a
149
+ #
150
+ attr_reader :public
151
+
152
+ ##
153
+ # The title of the post.
154
+ #
155
+ # @author Yorick Peterse
156
+ # @since 0.1a
157
+ #
158
+ attr_reader :title
159
+
160
+ ##
161
+ # If the post type was a link this field will contain the URL to the external page.
162
+ #
163
+ # @author Yorick Peterse
164
+ # @since 0.1a
165
+ #
166
+ attr_reader :url
167
+
168
+ ##
169
+ # The content of the post. If it's a question this field contains the question, if
170
+ # it's a code post it will contain the code attached to the post.
171
+ #
172
+ # @author Yorick Peterse
173
+ # @since 0.1a
174
+ #
175
+ attr_reader :content
176
+
177
+ ##
178
+ # Field containing the description of the post, not used for questions.
179
+ #
180
+ # @author Yorick Peterse
181
+ # @since 0.1a
182
+ #
183
+ attr_reader :description
184
+
185
+ ##
186
+ # The description in HTML.
187
+ #
188
+ # @author Yorick Peterse
189
+ # @since 0.1a
190
+ #
191
+ attr_reader :formatted_description
192
+
193
+ ##
194
+ # The content in HTML.
195
+ #
196
+ # @author Yorick Peterse
197
+ # @since 0.1a
198
+ #
199
+ attr_reader :formatted_content
200
+
201
+ ##
202
+ # A hash containing the number of comments, likes, etc.
203
+ #
204
+ # @author Yorick Peterse
205
+ # @since 0.1a
206
+ #
207
+ attr_reader :statistics
208
+
209
+ ##
210
+ # An array of all the tags used in the post.
211
+ #
212
+ # @author Yorick Peterse
213
+ # @since 0.1a
214
+ #
215
+ attr_reader :tags
216
+
217
+ ##
218
+ # A hash containing the URLs to various sizes of the snap in case the post type is
219
+ # "snap".
220
+ #
221
+ # @author Yorick Peterse
222
+ # @since 0.1a
223
+ #
224
+ attr_reader :snaps
225
+
226
+ ##
227
+ # Given a custom set of options this method will retrieve a list of posts. It's
228
+ # important to remember that the keys of the hash passed to this method should be
229
+ # symbols and *not* strings.
230
+ #
231
+ # Note that this method will always return an array of posts, if you want to retrieve
232
+ # a single post use Forrst::Post[] instead.
233
+ #
234
+ # @example
235
+ # Forrst::Post.find(:type => :question)
236
+ # Forrst::Post.find(:type => :code, :sort => :recent)
237
+ #
238
+ # @author Yorick Peterse
239
+ # @since 0.1a
240
+ # @param [Hash] options
241
+ # @option options [Symbol] :type The type of posts to retrieve. Can be one of
242
+ # the following: code, snap, link or question.
243
+ # @option options [Symbol] :sort The sort order to use, can be any of the
244
+ # following: recent, popular or best.
245
+ # @option options [Fixnum] :page The page to use. Each page contains a (currently
246
+ # unknown) number of posts.
247
+ # @return [Array]
248
+ #
249
+ def self.find(options)
250
+ # Set the correct keys for the API call
251
+ query_items = {}
252
+ query_items[:post_type] = options[:type].to_s if options.key?(:type)
253
+ query_items[:sort] = options[:sort].to_s if options.key?(:sort)
254
+ query_items[:page] = options[:page].to_s if options.key?(:page)
255
+
256
+ response = Forrst.oauth.request(:get, ListURL, query_items)
257
+ response = JSON.load(response)
258
+
259
+ return response['resp']['posts'].map do |post|
260
+ Post.new(post)
261
+ end
262
+ end
263
+
264
+ ##
265
+ # Retrieves a single post by it's ID or tiny ID. If the parameter given is a Fixnum
266
+ # this method assumes is the ID, if it's a string it assumes it's the tiny ID.
267
+ #
268
+ # @author Yorick Peterse
269
+ # @since 0.1a
270
+ # @param [Fixnum/String] id The ID or the tiny ID.
271
+ # @return [Forrst::Post]
272
+ #
273
+ def self.[](id)
274
+ if id.class == Fixnum
275
+ query_items = {:id => id}
276
+ elsif id.class == String
277
+ query_items = {:tiny_id => id}
278
+ else
279
+ raise(TypeError, "Got #{id.class} but expected Fixnum or String")
280
+ end
281
+
282
+ response = Forrst.oauth.request(:get, ShowURL, query_items)
283
+ response = JSON.load(response)
284
+
285
+ return Post.new(response['resp'])
286
+ end
287
+
288
+ ##
289
+ # Creates a new instance of Forrst::Post and optionally decodes a JSON response. If a
290
+ # response is already decoded it's data is merely assigned to the current instance.
291
+ #
292
+ # @author Yorick Peterse
293
+ # @since 0.1a
294
+ # @param [String/Hash] response The API response in either JSON format or a hash.
295
+ # @return [Forrst::Post]
296
+ #
297
+ def initialize(response)
298
+ if response.class != Hash
299
+ response = JSON.load(response)
300
+ end
301
+
302
+ @post_id = response['id'].to_i
303
+ @tiny_id = response['id']
304
+ @type = response['post_type']
305
+ @post_url = response['post_url']
306
+ @created_at = Date.strptime(response['created_at'], Forrst::DateFormat)
307
+ @updated_at = Date.strptime(response['updated_at'], Forrst::DateFormat)
308
+ @user = Forrst::User.new(response['user'])
309
+ @published = response['published']
310
+ @public = response['public']
311
+ @title = response['title']
312
+ @url = response['url']
313
+ @content = response['content']
314
+
315
+ @description = response['description']
316
+ @formatted_description = response['formatted_description']
317
+ @formatted_content = response['formatted_content']
318
+ @tags = response['tags']
319
+
320
+ @statistics = {
321
+ :comments => response['comment_count'].to_i,
322
+ :likes => response['like_count'].to_i
323
+ }
324
+
325
+ # Get all the snaps
326
+ @snaps = {}
327
+
328
+ if response.key?('snaps')
329
+ @snaps[:extra_large] = response['snaps']['mega_url']
330
+ @snaps[:keith] = response['snaps']['keith_url'] # The fuck is a keith?
331
+ @snaps[:large] = response['snaps']['large_url']
332
+ @snaps[:medium] = response['snaps']['medium_url']
333
+ @snaps[:small] = response['snaps']['small_url']
334
+ @snaps[:thumbnail] = response['snaps']['thumb_url']
335
+ @snaps[:original] = response['snaps']['original_url']
336
+ end
337
+ end
338
+
339
+ ##
340
+ # Retrieves all the comments for the current post.
341
+ #
342
+ # @example
343
+ # post = Forrst::Post[10]
344
+ # post.comments.each do |comment|
345
+ # puts comment.body
346
+ # end
347
+ #
348
+ # @author Yorick Peterse
349
+ # @since 0.1a
350
+ # @return [Array]
351
+ #
352
+ def comments
353
+ response = Forrst.oauth.request(:get, CommentsURL, :id => @post_id)
354
+ response = JSON.load(response)
355
+
356
+ return response['comments'].map do |comment|
357
+ Forrst::Comment.new(comment)
358
+ end
359
+ end
360
+
361
+ ##
362
+ # Checks if the post is a question.
363
+ #
364
+ # @author Yorick Peterse
365
+ # @since 0.1a
366
+ # @return [TrueClass/FalseClass]
367
+ #
368
+ def question?
369
+ return @type === 'question'
370
+ end
371
+
372
+ ##
373
+ # Checks if the post is a snap.
374
+ #
375
+ # @author Yorick Peterse
376
+ # @since 0.1a
377
+ # @return [TrueClass/FalseClass]
378
+ #
379
+ def snap?
380
+ return @type === 'snap'
381
+ end
382
+
383
+ ##
384
+ # Checks if the post is a code post.
385
+ #
386
+ # @author Yorick Peterse
387
+ # @since 0.1a
388
+ # @return [TrueClass/FalseClass]
389
+ #
390
+ def code?
391
+ return @type === 'code'
392
+ end
393
+
394
+ ##
395
+ # Checks if the post is a link post.
396
+ #
397
+ # @author Yorick Peterse
398
+ # @since 0.1a
399
+ # @return [TrueClass/FalseClass]
400
+ #
401
+ def link?
402
+ return @type === 'link'
403
+ end
404
+ end # Post
405
+ end # Forrst)
@@ -0,0 +1,319 @@
1
+ module Forrst
2
+ ##
3
+ # Forrst::User is the class used for retrieving details about a particular user. A user
4
+ # is retrieved by calling Forrst::User[] and passing a username or ID to it:
5
+ #
6
+ # user = Forrst::User['yorickpeterse'] => #<Forrst::User:0x1234567>
7
+ #
8
+ # Once an instance has been created you can retrieve various details, such as the
9
+ # username, simply by calling methods on the resulting object:
10
+ #
11
+ # user.username => 'YorickPeterse'
12
+ #
13
+ # When retrieving a user you can retrieve the user's posts by calling Forrst::User#posts
14
+ # as following:
15
+ #
16
+ # user.posts.each do |post|
17
+ # puts post.title
18
+ # end
19
+ #
20
+ # When retrieving the user's posts the library will use the class Forrst::Post which
21
+ # allows you to retrieve post related data such as all the comments:
22
+ #
23
+ # user.posts.each do |post|
24
+ # post.comments.each do |comment|
25
+ # puts comment.body
26
+ # end
27
+ # end
28
+ #
29
+ # Note that comments are lazy loaded. This means that for each iteration in the posts
30
+ # array a GET request is fired to the Forrst API. Currently there's no way to work
31
+ # around this so you'll have to be careful with using this method.
32
+ #
33
+ # This class also provides the following shortcut methods for figuring out the type of
34
+ # user:
35
+ #
36
+ # * developer?
37
+ # * designer?
38
+ # * developer_and_designer?
39
+ #
40
+ # These can be used as following:
41
+ #
42
+ # if user.developer?
43
+ # puts "It's a nerd!"
44
+ # elsif user.designer?
45
+ # puts "It's a hippie!"
46
+ # end
47
+ #
48
+ # @author Yorick Peterse
49
+ # @since 0.1a
50
+ #
51
+ class User
52
+ ##
53
+ # URL relative to Forrst::URL for retrieving user information.
54
+ #
55
+ # @author Yorick Peterse
56
+ # @since 0.1a
57
+ #
58
+ InfoURL = '/users/info'
59
+
60
+ ##
61
+ # URL relative to Forrst::URL for retrieving the posts of a user.
62
+ #
63
+ # @author Yorick Peterse
64
+ # @since 0.1a
65
+ #
66
+ PostsURL = '/users/posts'
67
+
68
+ ##
69
+ # The user's ID.
70
+ #
71
+ # @author Yorick Peterse
72
+ # @since 0.1a
73
+ #
74
+ attr_reader :user_id
75
+
76
+ ##
77
+ # The username as used on Forrst.
78
+ #
79
+ # @author Yorick Peterse
80
+ # @since 0.1a
81
+ #
82
+ attr_reader :username
83
+
84
+ ##
85
+ # The real name of the user.
86
+ #
87
+ # @author Yorick Peterse
88
+ # @since 0.1a
89
+ #
90
+ attr_reader :name
91
+
92
+ ##
93
+ # The URL to the Forrst profile of the user.
94
+ #
95
+ # @author Yorick Peterse
96
+ # @since 0.1a
97
+ #
98
+ attr_reader :url
99
+
100
+ ##
101
+ # A hash containing various statistics such as the amount of comments, likes, etc.
102
+ # Note that the keys of this hash are symbols, not strings.
103
+ #
104
+ # @author Yorick Peterse
105
+ # @since 0.1a
106
+ #
107
+ attr_reader :statistics
108
+
109
+ ##
110
+ # The description of the user.
111
+ #
112
+ # @author Yorick Peterse
113
+ # @since 0.1a
114
+ #
115
+ attr_reader :bio
116
+
117
+ ##
118
+ # The Twitter username of the user.
119
+ #
120
+ # @author Yorick Peterse
121
+ # @since 0.1a
122
+ #
123
+ attr_reader :twitter
124
+
125
+ ##
126
+ # A hash containing all the photos of the user. All the keys of this hash are symbols
127
+ # just like the statistics hash.
128
+ #
129
+ # @author Yorick Peterse
130
+ # @since 0.1a
131
+ #
132
+ attr_reader :photos
133
+
134
+ ##
135
+ # An array containing the types of the user. Can be any of the following:
136
+ #
137
+ # * ['developer']
138
+ # * ['designer']
139
+ # * ['developer', 'designer']
140
+ #
141
+ # @author Yorick Peterse
142
+ # @since 0.1a
143
+ #
144
+ attr_reader :type
145
+
146
+ ##
147
+ # The URL to the user's website.
148
+ #
149
+ # @author Yorick Peterse
150
+ # @since 0.1a
151
+ #
152
+ attr_reader :homepage
153
+
154
+ ##
155
+ # A boolean that indicates if the user is listed in the Forrst.me directory or not.
156
+ #
157
+ # @author Yorick Peterse
158
+ # @since 0.1a
159
+ #
160
+ attr_reader :listed
161
+
162
+ ##
163
+ # An array of tags for the user.
164
+ #
165
+ # @author Yorick Peterse
166
+ # @since 0.1a
167
+ #
168
+ attr_reader :tags
169
+
170
+ ##
171
+ # Retrieves a single user by it's username or ID and returns a new instance of
172
+ # Forrst::User with these details.
173
+ #
174
+ # @example
175
+ # Forrst::User['yorickpeterse']
176
+ # Forrst::User[6998]
177
+ #
178
+ # @author Yorick Peterse
179
+ # @since 0.1a
180
+ # @param [String/Fixnum] options
181
+ # @return [Forrst::User]
182
+ #
183
+ def self.[](options)
184
+ if options.class == String
185
+ options = {:username => options}
186
+ elsif options.class == Fixnum
187
+ options = {:id => options.to_s}
188
+ else
189
+ raise(TypeError, "Expected Hash or Fixnum but got #{options.class} instead")
190
+ end
191
+
192
+ response = Forrst.oauth.request(:get, InfoURL, options)
193
+
194
+ return User.new(response)
195
+ end
196
+
197
+ ##
198
+ # Given a JSON response (as a string) this method will parse it using the JSON gem and
199
+ # return a new instance of Forrst::User with all the details set.
200
+ #
201
+ # @author Yorick Peterse
202
+ # @since 0.1a
203
+ # @param [String/Hash] response A string containing a JSON response sent back by the
204
+ # Forrst server or an instance of Hash in case the response has already been parsed.
205
+ # @return [Forrst::User]
206
+ #
207
+ def initialize(response)
208
+ if response.class != Hash
209
+ response = JSON.load(response)
210
+ response = response['resp']
211
+ end
212
+
213
+ # We're not directly setting Forrst::User#id as that will trigger warnings in both
214
+ # JRuby and Rubinius.
215
+ @user_id = response['id']
216
+ @username = response['username']
217
+ @name = response['name']
218
+ @url = response['url']
219
+ @homepage = response['homepage_url']
220
+ @listed = response['in_directory']
221
+ @twitter = response['twitter']
222
+ @bio = response['bio']
223
+
224
+ @statistics = {
225
+ :comments => response['comments'].to_i,
226
+ :likes => response['likes'].to_i,
227
+ :followers => response['followers'].to_i,
228
+ :following => response['following'].to_i,
229
+ :posts => response['posts'].to_i
230
+ }
231
+
232
+ # Photos come as a hash with rather wacky keys so those need to be changed as well.
233
+ @photos = {
234
+ :extra_large => response['photos']['xl_url'],
235
+ :large => response['photos']['large_url'],
236
+ :medium => response['photos']['medium_url'],
237
+ :small => response['photos']['small_url'],
238
+ :thumbnail => response['photos']['thumb_url']
239
+ }
240
+
241
+ # Tags aren't always present
242
+ if response.key?('tag_string')
243
+ @tags = response['tag_string'].split(',')
244
+ else
245
+ @tags = []
246
+ end
247
+
248
+ # Last but not least, the user type!
249
+ @type = response['is_a'].split('&').map { |i| i.strip }
250
+ end
251
+
252
+ ##
253
+ # Retrieves all the posts for the current user. Each post is an instance of
254
+ # Forrst::Post.
255
+ #
256
+ # @author Yorick Peterse
257
+ # @since 0.1a
258
+ # @param [Hash] options A hash with additional options to use when retrieving all the
259
+ # posts.
260
+ # @option options [String/Symbol] :type The type of posts to retrieve such as :code or
261
+ # :question.
262
+ # @option options [Fixnum] :limit The amount of posts to retrieve.
263
+ # @option options [After] :after An ID offset used for retrieving a set of posts
264
+ # after the given ID.
265
+ # @return [Array]
266
+ #
267
+ def posts(options = {})
268
+ options = {
269
+ :username => @username
270
+ }.merge(options.subset(:limit, :type, :after))
271
+
272
+ response = Forrst.oauth.request(:get, PostsURL, options)
273
+ response = JSON.load(response)
274
+
275
+ return response['resp'].map do |post|
276
+ Forrst::Post.new(post)
277
+ end
278
+ end
279
+
280
+ ##
281
+ # Checks if the user is a developer or not.
282
+ #
283
+ # @author Yorick Peterse
284
+ # @since 0.1
285
+ # @return [TrueClass/FalseClass]
286
+ #
287
+ def developer?
288
+ return @type === ['developer']
289
+ end
290
+
291
+ ##
292
+ # Checks if the user is a designer or not.
293
+ #
294
+ # @author Yorick Peterse
295
+ # @since 0.1
296
+ # @return [TrueClass/FalseClass]
297
+ #
298
+ def designer?
299
+ return @type === ['designer']
300
+ end
301
+
302
+ ##
303
+ # Checks if the user is a developer and a designer.
304
+ #
305
+ # @author Yorick Peterse
306
+ # @since 0.1
307
+ # @return [TrueClass/FalseClass]
308
+ #
309
+ def developer_and_designer?
310
+ # The shorthand "return A and B" generates a void error so we'll have to do it this
311
+ # way.
312
+ if @type.include?('designer') and @type.include?('developer')
313
+ return true
314
+ else
315
+ return false
316
+ end
317
+ end
318
+ end # User
319
+ end # Forrst
@@ -0,0 +1,3 @@
1
+ module Forrst
2
+ Version = '0.1.1'
3
+ end
@@ -0,0 +1,55 @@
1
+ require 'find'
2
+
3
+ namespace :build do
4
+
5
+ desc 'Builds the documentation using YARD'
6
+ task :doc do
7
+ gem_path = File.expand_path('../../', __FILE__)
8
+ command = "yard doc #{gem_path}/lib -m markdown -M rdiscount -o #{gem_path}/doc "
9
+ command += "-r #{gem_path}/README.md --private --protected "
10
+ command += "--files #{gem_path}/LICENSE"
11
+
12
+ sh(command)
13
+ end
14
+
15
+ desc 'Builds a new Gem and installs it'
16
+ task :gem do
17
+ gem_path = File.expand_path('../../', __FILE__)
18
+
19
+ # Build and install the gem
20
+ sh("gem build #{gem_path}/forrst.gemspec")
21
+ sh("mv #{gem_path}/forrst-#{Forrst::Version}.gem #{gem_path}/pkg")
22
+ sh("gem install #{gem_path}/pkg/forrst-#{Forrst::Version}.gem")
23
+ end
24
+
25
+ desc 'Builds the MANIFEST file'
26
+ task :manifest do
27
+ gem_path = File.expand_path('../../', __FILE__)
28
+ ignore_exts = ['.gem', '.gemspec', '.swp']
29
+ ignore_files = ['.DS_Store', '.gitignore']
30
+ ignore_dirs = ['.git', '.yardoc', 'spec', 'pkg', 'doc']
31
+ files = ''
32
+
33
+ Find.find(gem_path) do |f|
34
+ f[gem_path] = ''
35
+ f.gsub!(/^\//, '')
36
+
37
+ # Ignore directories
38
+ if !File.directory?(f) and !ignore_exts.include?(File.extname(f)) and !ignore_files.include?(File.basename(f))
39
+ files += "#{f}\n"
40
+ else
41
+ Find.prune if ignore_dirs.include?(f)
42
+ end
43
+ end
44
+
45
+ # Time to write the MANIFEST file
46
+ begin
47
+ handle = File.open 'MANIFEST', 'w'
48
+ handle.write files.strip
49
+ puts "The MANIFEST file has been updated."
50
+ rescue
51
+ abort "The MANIFEST file could not be written."
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,5 @@
1
+ desc 'Runs all the tests'
2
+ task :test do
3
+ spec_path = File.expand_path('../../spec/', __FILE__)
4
+ sh("cd #{spec_path}; ruby forrst/all.rb")
5
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: forrst
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.1
6
+ platform: ruby
7
+ authors:
8
+ - Yorick Peterse
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-04 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: json
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 1.5.1
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: oauth2
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 0.4.1
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rake
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.8.7
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: 2.6.0
58
+ type: :development
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: yard
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.7.1
69
+ type: :development
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: rdiscount
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: 1.6.8
80
+ type: :development
81
+ version_requirements: *id006
82
+ description: A Ruby library for the Forrst API.
83
+ email: info@yorickpeterse.com
84
+ executables: []
85
+
86
+ extensions: []
87
+
88
+ extra_rdoc_files: []
89
+
90
+ files:
91
+ - .gems
92
+ - .rvmrc
93
+ - .travis.yml
94
+ - CHANGELOG.md
95
+ - LICENSE
96
+ - MANIFEST
97
+ - README.md
98
+ - Rakefile
99
+ - lib/.gitkeep
100
+ - lib/forrst/.gitkeep
101
+ - lib/forrst/comment.rb
102
+ - lib/forrst/monkeys/hash.rb
103
+ - lib/forrst/post.rb
104
+ - lib/forrst/user.rb
105
+ - lib/forrst/version.rb
106
+ - lib/forrst.rb
107
+ - task/build.rake
108
+ - task/test.rake
109
+ has_rdoc: yard
110
+ homepage: https://github.com/yorickpeterse/forrst
111
+ licenses: []
112
+
113
+ post_install_message:
114
+ rdoc_options: []
115
+
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: "0"
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: "0"
130
+ requirements: []
131
+
132
+ rubyforge_project:
133
+ rubygems_version: 1.6.2
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: Ruby API for Forrst
137
+ test_files: []
138
+