timespeople 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2008 Jacob Harris
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ THESE LICENSE TERMS APPLY TO THE GEM SOFTWARE ONLY AND DO NOT SUPPLEMENT
23
+ OR ABROGATE THE TERMS OF SERVICE FOR THE TIMESPEOPLE API.
data/README ADDED
@@ -0,0 +1,8 @@
1
+ timespeople===========
2
+
3
+ A gem for interacting with the TimesPeople API. More documentation to come.
4
+
5
+ COPYRIGHT
6
+ =========
7
+
8
+ Copyright (c) 2008 Jacob Harris. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |s|
6
+ s.name = "timespeople"
7
+ s.summary = "A simple gem for the TimesPeople API"
8
+ s.email = "jharris@nytimes.com"
9
+ s.homepage = "http://github.com/harrisj/timespeople"
10
+ s.description = "A simple gem for the TimesPeople API"
11
+ s.authors = ["Jacob Harris"]
12
+ end
13
+ rescue LoadError
14
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
15
+ end
16
+
17
+ require 'rake/rdoctask'
18
+ Rake::RDocTask.new do |rdoc|
19
+ rdoc.rdoc_dir = 'rdoc'
20
+ rdoc.title = 'timespeople'
21
+ rdoc.options << '--line-numbers' << '--inline-source'
22
+ rdoc.rdoc_files.include('README*')
23
+ rdoc.rdoc_files.include('lib/**/*.rb')
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'lib' << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |t|
36
+ t.libs << 'test'
37
+ t.test_files = FileList['test/**/*_test.rb']
38
+ t.verbose = true
39
+ end
40
+ rescue LoadError
41
+ puts "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+
44
+ # begin
45
+ # require 'cucumber/rake/task'
46
+ # Cucumber::Rake::Task.new(:features)
47
+ # rescue LoadError
48
+ # puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
49
+ # end
50
+
51
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
4
+ :major: 0
File without changes
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'timespeople'
3
+
4
+ require 'test/unit/assertions'
5
+
6
+ require 'test/unit/assertions'
7
+
8
+ World do |world|
9
+
10
+ world.extend(Test::Unit::Assertions)
11
+
12
+ world
13
+ end
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
@@ -0,0 +1,3 @@
1
+ require File.join(File.dirname(__FILE__), 'times_people', 'exceptions')
2
+ require File.join(File.dirname(__FILE__), 'times_people', 'base')
3
+ require File.join(File.dirname(__FILE__), 'times_people', 'user')
@@ -0,0 +1,98 @@
1
+ require 'open-uri'
2
+ require 'json'
3
+ require 'htmlentities'
4
+
5
+ module TimesPeople
6
+ class Base
7
+ API_SERVER = 'api.nytimes.com'
8
+ API_VERSION = 'v1'
9
+ API_NAME = 'timespeople'
10
+
11
+ @@api_key = nil
12
+ @@debug = false
13
+
14
+ ##
15
+ # Set the API key used for operations. This needs to be called before any requests against the API. To obtain an API key, go to http://developer.nytimes.com/
16
+ def self.api_key=(key)
17
+ @@api_key = key
18
+ end
19
+
20
+ def self.debug=(flag)
21
+ @@debug = flag
22
+ end
23
+
24
+ ##
25
+ # Returns the current value of the API Key
26
+ def self.api_key
27
+ @@api_key
28
+ end
29
+
30
+ ##
31
+ # Builds a request URI to call the API server
32
+ def self.build_request_url(path, params)
33
+ URI::HTTP.build :host => API_SERVER,
34
+ :path => "/svc/#{API_NAME}/api/#{API_VERSION}/#{path}.js",
35
+ :query => params.map {|k,v| "#{URI.escape(k)}=#{URI.escape(v)}"}.join('&')
36
+ end
37
+
38
+ def self.text_field(value)
39
+ return nil if value.nil?
40
+ coder = HTMLEntities.new
41
+ coder.decode(value)
42
+ end
43
+
44
+ def self.integer_field(value)
45
+ return nil if value.nil?
46
+ value.to_i
47
+ end
48
+
49
+ def self.date_field(value)
50
+ return nil unless value =~ /^\d{8}$/
51
+ Date.strptime(value, "%Y%m%d")
52
+ end
53
+
54
+ def self.invoke(path, params={})
55
+ begin
56
+ if @@api_key.nil?
57
+ raise AuthenticationError, "You must initialize the API key before you run any API queries"
58
+ end
59
+
60
+ full_params = params.merge 'api-key' => @@api_key
61
+ uri = build_request_url(path, full_params)
62
+
63
+ puts "REQUEST: #{uri}" if @@debug
64
+
65
+ reply = uri.read
66
+ parsed_reply = JSON.parse reply
67
+
68
+ if parsed_reply.nil?
69
+ raise BadResponseError, "Empty reply returned from API"
70
+ end
71
+
72
+ #case parsed_reply['status']
73
+ # FIXME
74
+ #end
75
+
76
+ parsed_reply
77
+ rescue OpenURI::HTTPError => e
78
+ # FIXME: Return message from body?
79
+ case e.message
80
+ when /^400/
81
+ raise BadRequestError
82
+ when /^403/
83
+ raise AuthenticationError
84
+ when /^404/
85
+ return nil
86
+ when /^500/
87
+ raise ServerError
88
+ else
89
+ raise ConnectionError
90
+ end
91
+
92
+ raise "Error connecting to URL #{uri} #{e}"
93
+ rescue JSON::ParserError => e
94
+ raise BadResponseError, "Invalid JSON returned from API:\n#{reply}"
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,41 @@
1
+ module TimesPeople
2
+ ##
3
+ # The generic Error class from which all other Errors are derived.
4
+ class Error < ::RuntimeError
5
+ end
6
+
7
+ ##
8
+ # This error is thrown if there are problems authenticating your API key.
9
+ class AuthenticationError < Error
10
+ end
11
+
12
+ ##
13
+ # This error is thrown if the request was not parsable by the API server.
14
+ class BadRequestError < Error
15
+ end
16
+
17
+ ##
18
+ # This error is thrown if the response from the API server is not parsable.
19
+ class BadResponseError < Error
20
+ end
21
+
22
+ ##
23
+ # This error is thrown if there is an error connecting to the API server.
24
+ class ServerError < Error
25
+ end
26
+
27
+ ##
28
+ # This error is thrown if there is a timeout connecting to the server (to be implemented).
29
+ class TimeoutError < Error
30
+ end
31
+
32
+ ##
33
+ # This error is thrown for general connection errors to the API server.
34
+ class ConnectionError < Error
35
+ end
36
+
37
+ ##
38
+ # This error is thrown if the User was not found
39
+ class UserNotFoundError < Error
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ require 'digest/md5'
2
+
3
+ module TimesPeople
4
+ class User < Base
5
+ attr_reader :user_id, :display_name, :location, :picture_url, :following_count, :followers_count
6
+
7
+ def initialize(hash)
8
+ @user_id = hash[:user_id]
9
+ @display_name = hash[:display_name]
10
+ @location = hash[:location]
11
+ @picture_url = hash[:picture_url]
12
+ @following_count = hash[:following_count]
13
+ @followers_count = hash[:followers_count]
14
+ end
15
+
16
+ # http://api.nytimes.com/svc/timespeople/api/{version}/user/{hash}/id{.response-format}?api-key={your-API-key}
17
+ def self.find(email_addr)
18
+ digest = Digest::MD5.hexdigest(email_addr.downcase)
19
+
20
+ begin
21
+ reply = invoke("user/#{digest}/id")
22
+ if reply.nil?
23
+ raise UserNotFoundError, "No user with that email address was found in TimesPeople"
24
+ end
25
+
26
+ rescue ServerError
27
+ raise UserNotFoundError, "No user with that email address was found in TimesPeople"
28
+ end
29
+
30
+ # http://api.nytimes.com/svc/timespeople/api/{version}/user/{user-id}/{data-type}{.response-format}?api-key={your-API-key}
31
+ unless reply['results'].nil? || reply['results']['user_id'].nil?
32
+ user_id = reply['results']['user_id']
33
+ reply = invoke("user/#{user_id}/profile")
34
+ init_from_api(reply['results'])
35
+ end
36
+ end
37
+
38
+ def self.init_from_api(api_hash)
39
+ new :user_id => api_hash['user_id'],
40
+ :display_name => api_hash['user_displayname'],
41
+ :location => api_hash['location'],
42
+ :picture_url => api_hash['user_pic_url'],
43
+ :following_count => api_hash['following_count'],
44
+ :followers_count => api_hash['followers_count']
45
+ end
46
+ end
47
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'times_people')
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/timespeople.rb'}"
9
+ puts "Loading timespeople gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ gem 'chrisk-fakeweb'
6
+ require 'fake_web'
7
+
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require 'timespeople'
10
+
11
+ class Test::Unit::TestCase
12
+ API_KEY = '13e234323232222'
13
+
14
+ def init_test_key
15
+ TimesPeople::Base.api_key = API_KEY
16
+ end
17
+ end
18
+
19
+ module TestTimesPeople
20
+ end
@@ -0,0 +1,86 @@
1
+ require File.dirname(__FILE__) + '/../test_helper.rb'
2
+
3
+ class TestTimesPeople::TestBase < Test::Unit::TestCase
4
+ include TimesPeople
5
+
6
+ context "Base.build_request_url" do
7
+ end
8
+
9
+ context "Base.invoke" do
10
+ setup do
11
+ init_test_key
12
+ end
13
+
14
+ context "when the API key has not been set" do
15
+ setup do
16
+ Base.api_key = nil
17
+ end
18
+
19
+ should_eventually "raise an AuthenticationError" do
20
+ assert_raise(AuthenticationError) do
21
+ Base.invoke
22
+ end
23
+ end
24
+ end
25
+
26
+ context "when the Articles API returns a 403 forbidden error (API key issue)" do
27
+ setup do
28
+ FakeWeb.register_uri(api_url_for, :status => ["403", "Forbidden"])
29
+ end
30
+
31
+ should_eventually "raise an AuthenticationError" do
32
+ assert_raise(AuthenticationError) do
33
+ Base.invoke
34
+ end
35
+ end
36
+ end
37
+
38
+ context "when the Articles API returns a 400 bad request error" do
39
+ setup do
40
+ FakeWeb.register_uri(api_url_for, :status => ["400", "Bad Request"])
41
+ end
42
+
43
+ should_eventually "raise an BadRequestError" do
44
+ assert_raise(BadRequestError) do
45
+ Base.invoke
46
+ end
47
+ end
48
+ end
49
+
50
+ context "When calling the Articles API returns a 500 server error" do
51
+ setup do
52
+ FakeWeb.register_uri(api_url_for, :status => ["500", "Server Error"])
53
+ end
54
+
55
+ should_eventually "raise an ServerError" do
56
+ assert_raise(ServerError) do
57
+ Base.invoke
58
+ end
59
+ end
60
+ end
61
+
62
+ context "when the Articles API returns any other HTTP error" do
63
+ setup do
64
+ FakeWeb.register_uri(api_url_for, :status => ["502", "Random Error"])
65
+ end
66
+
67
+ should_eventually "raise an ConnectionError" do
68
+ assert_raise(ConnectionError) do
69
+ Base.invoke
70
+ end
71
+ end
72
+ end
73
+
74
+ context "When the Articles API returns JSON that can't be parsed" do
75
+ setup do
76
+ FakeWeb.register_uri(api_url_for, :text => "e2131421212121221 => 3i109sdfvinp;2 112")
77
+ end
78
+
79
+ should_eventually "raise an BadResponseError" do
80
+ assert_raise(BadResponseError) do
81
+ Base.invoke
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timespeople
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Jacob Harris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-25 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A simple gem for the TimesPeople API
17
+ email: jharris@nytimes.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README
25
+ files:
26
+ - .gitignore
27
+ - LICENSE
28
+ - README
29
+ - Rakefile
30
+ - VERSION.yml
31
+ - features/steps/timespeople_steps.rb
32
+ - features/support/env.rb
33
+ - features/timespeople.feature
34
+ - lib/times_people.rb
35
+ - lib/times_people/base.rb
36
+ - lib/times_people/exceptions.rb
37
+ - lib/times_people/user.rb
38
+ - lib/timespeople.rb
39
+ - script/console
40
+ - test/test_helper.rb
41
+ - test/times_people/test_base.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/harrisj/timespeople
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.2
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: A simple gem for the TimesPeople API
70
+ test_files:
71
+ - test/test_helper.rb
72
+ - test/times_people/test_base.rb