forrst 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+