linkedin 0.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Wynn Netherland
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.
@@ -0,0 +1,22 @@
1
+ # linkedin
2
+
3
+ Ruby wrapper for the [LinkedIn API](http://developer.linkedin.com)
4
+
5
+ ## TODO
6
+ * Implement Search, Status, Invitation APIs
7
+ * Swap Crack for ROXML for cleaner attribute access
8
+
9
+ ## Note on Patches/Pull Requests
10
+
11
+ * Fork the project.
12
+ * Make your feature addition or bug fix.
13
+ * Add tests for it. This is important so I don't break it in a
14
+ future version unintentionally.
15
+ * Commit, do not mess with rakefile, version, or history.
16
+ (if you want to have your own version, that is fine but
17
+ bump version in a commit by itself I can ignore when I pull)
18
+ * Send me a pull request. Bonus points for topic branches.
19
+
20
+ ## Copyright
21
+
22
+ Copyright (c) 2009 [Wynn Netherland](http://wynnnetherland.com). See LICENSE for details.
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "linkedin"
8
+ gem.summary = %Q{Ruby wrapper for the LinkedIn API}
9
+ gem.description = %Q{Ruby wrapper for the LinkedIn API}
10
+ gem.email = "wynn.netherland@gmail.com"
11
+ gem.homepage = "http://github.com/pengwynn/linkedin"
12
+ gem.authors = ["Wynn Netherland"]
13
+ gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
14
+
15
+
16
+ gem.add_dependency('oauth', '~> 0.3.5')
17
+ gem.add_dependency('hashie', '~> 0.1.3')
18
+ gem.add_dependency('crack', '~> 0.1.4')
19
+
20
+ gem.add_development_dependency('thoughtbot-shoulda', '>= 2.10.1')
21
+ gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
22
+ gem.add_development_dependency('mocha', '0.9.4')
23
+ gem.add_development_dependency('fakeweb', '>= 1.2.5')
24
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
25
+ end
26
+ Jeweler::GemcutterTasks.new
27
+ rescue LoadError
28
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
29
+ end
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'test'
34
+ test.ruby_opts << '-rubygems'
35
+ test.pattern = 'test/**/*_test.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ begin
40
+ require 'rcov/rcovtask'
41
+ Rcov::RcovTask.new do |test|
42
+ test.libs << 'test'
43
+ test.pattern = 'test/**/test_*.rb'
44
+ test.verbose = true
45
+ end
46
+ rescue LoadError
47
+ task :rcov do
48
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
49
+ end
50
+ end
51
+
52
+ task :test => :check_dependencies
53
+
54
+ task :default => :test
55
+
56
+ require 'rake/rdoctask'
57
+ Rake::RDocTask.new do |rdoc|
58
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
59
+
60
+ rdoc.rdoc_dir = 'rdoc'
61
+ rdoc.title = "linkedin #{version}"
62
+ rdoc.rdoc_files.include('README*')
63
+ rdoc.rdoc_files.include('lib/**/*.rb')
64
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,130 @@
1
+ module LinkedIn
2
+ class Client
3
+
4
+ attr_reader :ctoken, :csecret, :consumer_options
5
+
6
+ def initialize(ctoken, csecret, options={})
7
+ opts = {
8
+ :request_token_path => "/uas/oauth/requestToken",
9
+ :access_token_path => "/uas/oauth/accessToken",
10
+ :authorize_path => "/uas/oauth/authorize"
11
+ }
12
+ @ctoken, @csecret, @consumer_options = ctoken, csecret, opts.merge(options)
13
+ end
14
+
15
+ def consumer
16
+ @consumer ||= ::OAuth::Consumer.new(@ctoken, @csecret, {:site => 'https://api.linkedin.com'}.merge(consumer_options))
17
+ end
18
+
19
+ def set_callback_url(url)
20
+ clear_request_token
21
+ request_token(:oauth_callback => url)
22
+ end
23
+
24
+ # Note: If using oauth with a web app, be sure to provide :oauth_callback.
25
+ # Options:
26
+ # :oauth_callback => String, url that twitter should redirect to
27
+ def request_token(options={})
28
+ @request_token ||= consumer.get_request_token(options)
29
+ end
30
+
31
+ # For web apps use params[:oauth_verifier], for desktop apps,
32
+ # use the verifier is the pin that twitter gives users.
33
+ def authorize_from_request(rtoken, rsecret, verifier_or_pin)
34
+ request_token = ::OAuth::RequestToken.new(consumer, rtoken, rsecret)
35
+ access_token = request_token.get_access_token(:oauth_verifier => verifier_or_pin)
36
+ @atoken, @asecret = access_token.token, access_token.secret
37
+ end
38
+
39
+ def access_token
40
+ @access_token ||= ::OAuth::AccessToken.new(consumer, @atoken, @asecret)
41
+ end
42
+
43
+ def authorize_from_access(atoken, asecret)
44
+ @atoken, @asecret = atoken, asecret
45
+ end
46
+
47
+ def get(path, options={})
48
+ path = "/v1#{path}"
49
+ puts path
50
+ response = access_token.get(path, options)
51
+ raise_errors(response)
52
+ parse(response)
53
+ end
54
+
55
+
56
+ def profile(options={})
57
+
58
+ path = person_path(options)
59
+
60
+ unless options[:fields].nil?
61
+ if options[:public]
62
+ path +=":public"
63
+ else
64
+ path +=":(#{options[:fields].map{|f| f.to_s}.join(',')})"
65
+ end
66
+ end
67
+ data = Hashie::Mash.new(get(path))
68
+
69
+ if data.errors.nil?
70
+ data.person
71
+ else
72
+ data
73
+ end
74
+
75
+ end
76
+
77
+ def connections(options={})
78
+ path = "#{person_path(options)}/connections"
79
+
80
+ unless options[:fields].nil?
81
+ if options[:public]
82
+ path +=":public"
83
+ else
84
+ path +=":(#{options[:fields].map{|f| f.to_s}.join(',')})"
85
+ end
86
+ end
87
+
88
+ data = Hashie::Mash.new(get(path))
89
+
90
+ if data.errors.nil?
91
+ data.connections
92
+ else
93
+ data
94
+ end
95
+
96
+ end
97
+
98
+ private
99
+ def clear_request_token
100
+ @request_token = nil
101
+ end
102
+
103
+ def raise_errors(response)
104
+ case response.code.to_i
105
+ when 502..503
106
+ raise Unavailable, "(#{response.code}): #{response.message}"
107
+ end
108
+ end
109
+
110
+ def parse(response)
111
+ Crack::XML.parse(response.body)
112
+ end
113
+
114
+ def person_path(options)
115
+ path = "/people/"
116
+ if options[:id]
117
+ path += "id=#{options[:id]}"
118
+ elsif options[:email]
119
+ path += "email=#{options[:email]}"
120
+ elsif options[:url]
121
+ path += "url=#{CGI.escape(options[:url])}"
122
+ else
123
+ path += "~"
124
+ end
125
+ end
126
+
127
+
128
+
129
+ end
130
+ end
@@ -0,0 +1,17 @@
1
+ require 'forwardable'
2
+ require 'rubygems'
3
+
4
+ gem 'oauth', '~> 0.3.5'
5
+ require 'oauth'
6
+
7
+ gem 'hashie', '~> 0.1.3'
8
+ require 'hashie'
9
+
10
+ gem 'crack', '~> 0.1.4'
11
+ require 'crack'
12
+
13
+ require 'cgi'
14
+
15
+ directory = File.expand_path(File.dirname(__FILE__))
16
+
17
+ require File.join(directory, 'linked_in', 'client')
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+
3
+ class OAuthTest < Test::Unit::TestCase
4
+ should "initialize with consumer token and secret" do
5
+ linkedin = LinkedIn::Client.new('token', 'secret')
6
+
7
+ linkedin.ctoken.should == 'token'
8
+ linkedin.csecret.should == 'secret'
9
+ end
10
+
11
+ should "set authorization path to '/uas/oauth/authorize' by default" do
12
+ linkedin = LinkedIn::Client.new('token', 'secret')
13
+ linkedin.consumer.options[:authorize_path].should == '/uas/oauth/authorize'
14
+ end
15
+
16
+ should "have a consumer" do
17
+ consumer = mock('oauth consumer')
18
+ options = {
19
+ :request_token_path => "/uas/oauth/requestToken",
20
+ :access_token_path => "/uas/oauth/accessToken",
21
+ :authorize_path => "/uas/oauth/authorize",
22
+ :site => 'https://api.linkedin.com'
23
+ }
24
+ OAuth::Consumer.expects(:new).with('token', 'secret', options).returns(consumer)
25
+ linkedin = LinkedIn::Client.new('token', 'secret')
26
+
27
+ linkedin.consumer.should == consumer
28
+ end
29
+
30
+ should "have a request token from the consumer" do
31
+ options = {
32
+ :request_token_path => "/uas/oauth/requestToken",
33
+ :access_token_path => "/uas/oauth/accessToken",
34
+ :authorize_path => "/uas/oauth/authorize",
35
+ :site => 'https://api.linkedin.com'
36
+ }
37
+ consumer = mock('oauth consumer')
38
+ request_token = mock('request token')
39
+ consumer.expects(:get_request_token).returns(request_token)
40
+ OAuth::Consumer.expects(:new).with('token', 'secret', options).returns(consumer)
41
+ linkedin = LinkedIn::Client.new('token', 'secret')
42
+
43
+ linkedin.request_token.should == request_token
44
+ end
45
+
46
+ context "set_callback_url" do
47
+ should "clear request token and set the callback url" do
48
+ consumer = mock('oauth consumer')
49
+ request_token = mock('request token')
50
+ options = {
51
+ :request_token_path => "/uas/oauth/requestToken",
52
+ :access_token_path => "/uas/oauth/accessToken",
53
+ :authorize_path => "/uas/oauth/authorize",
54
+ :site => 'https://api.linkedin.com'
55
+ }
56
+ OAuth::Consumer.
57
+ expects(:new).
58
+ with('token', 'secret', options).
59
+ returns(consumer)
60
+
61
+ linkedin = LinkedIn::Client.new('token', 'secret')
62
+
63
+ consumer.
64
+ expects(:get_request_token).
65
+ with({:oauth_callback => 'http://myapp.com/oauth_callback'})
66
+
67
+ linkedin.set_callback_url('http://myapp.com/oauth_callback')
68
+ end
69
+ end
70
+
71
+ should "be able to create access token from request token, request secret and verifier" do
72
+ linkedin = LinkedIn::Client.new('token', 'secret')
73
+ consumer = OAuth::Consumer.new('token', 'secret', {:site => 'https://api.linkedin.com'})
74
+ linkedin.stubs(:consumer).returns(consumer)
75
+
76
+ access_token = mock('access token', :token => 'atoken', :secret => 'asecret')
77
+ request_token = mock('request token')
78
+ request_token.
79
+ expects(:get_access_token).
80
+ with(:oauth_verifier => 'verifier').
81
+ returns(access_token)
82
+
83
+ OAuth::RequestToken.
84
+ expects(:new).
85
+ with(consumer, 'rtoken', 'rsecret').
86
+ returns(request_token)
87
+
88
+ linkedin.authorize_from_request('rtoken', 'rsecret', 'verifier')
89
+ linkedin.access_token.class.should be(OAuth::AccessToken)
90
+ linkedin.access_token.token.should == 'atoken'
91
+ linkedin.access_token.secret.should == 'asecret'
92
+ end
93
+
94
+ should "be able to create access token from access token and secret" do
95
+ linkedin = LinkedIn::Client.new('token', 'secret')
96
+ consumer = OAuth::Consumer.new('token', 'secret', {:site => 'https://api.linkedin.com'})
97
+ linkedin.stubs(:consumer).returns(consumer)
98
+
99
+ linkedin.authorize_from_access('atoken', 'asecret')
100
+ linkedin.access_token.class.should be(OAuth::AccessToken)
101
+ linkedin.access_token.token.should == 'atoken'
102
+ linkedin.access_token.secret.should == 'asecret'
103
+ end
104
+
105
+
106
+ end
@@ -0,0 +1,51 @@
1
+ require 'test/unit'
2
+ require 'pathname'
3
+ require 'rubygems'
4
+
5
+ gem 'thoughtbot-shoulda', '>= 2.10.1'
6
+ gem 'jnunemaker-matchy', '0.4.0'
7
+ gem 'mocha', '0.9.4'
8
+ gem 'fakeweb', '>= 1.2.5'
9
+
10
+ require 'shoulda'
11
+ require 'matchy'
12
+ require 'mocha'
13
+ require 'fakeweb'
14
+
15
+ FakeWeb.allow_net_connect = false
16
+
17
+ dir = (Pathname(__FILE__).dirname + '../lib').expand_path
18
+ require dir + 'linkedin'
19
+
20
+ class Test::Unit::TestCase
21
+ end
22
+
23
+ def fixture_file(filename)
24
+ return '' if filename == ''
25
+ file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
26
+ File.read(file_path)
27
+ end
28
+
29
+ def linkedin_url(url)
30
+ url =~ /^http/ ? url : "https://api.linkedin.com:80#{url}"
31
+ end
32
+
33
+ def stub_get(url, filename, status=nil)
34
+ options = {:body => fixture_file(filename)}
35
+ options.merge!({:status => status}) unless status.nil?
36
+
37
+ FakeWeb.register_uri(:get, linkedin_url(url), options)
38
+ end
39
+
40
+ def stub_post(url, filename)
41
+ FakeWeb.register_uri(:post, linkedin_url(url), :body => fixture_file(filename))
42
+ end
43
+
44
+ def stub_put(url, filename)
45
+ FakeWeb.register_uri(:put, linkedin_url(url), :body => fixture_file(filename))
46
+ end
47
+
48
+ def stub_delete(url, filename)
49
+ FakeWeb.register_uri(:delete, linkedin_url(url), :body => fixture_file(filename))
50
+
51
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: linkedin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Wynn Netherland
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-24 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: oauth
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 0.3.5
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hashie
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.3
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: crack
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.1.4
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: thoughtbot-shoulda
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.10.1
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: jnunemaker-matchy
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.4.0
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: mocha
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.9.4
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: fakeweb
77
+ type: :development
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 1.2.5
84
+ version:
85
+ description: Ruby wrapper for the LinkedIn API
86
+ email: wynn.netherland@gmail.com
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files:
92
+ - LICENSE
93
+ - README.markdown
94
+ files:
95
+ - LICENSE
96
+ - README.markdown
97
+ - Rakefile
98
+ - VERSION
99
+ - lib/linked_in/client.rb
100
+ - lib/linkedin.rb
101
+ - test/oauth_test.rb
102
+ - test/test_helper.rb
103
+ has_rdoc: true
104
+ homepage: http://github.com/pengwynn/linkedin
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options:
109
+ - --charset=UTF-8
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: "0"
117
+ version:
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ version:
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.3.5
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Ruby wrapper for the LinkedIn API
131
+ test_files:
132
+ - test/oauth_test.rb
133
+ - test/test_helper.rb