linkedin 0.0.1

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