linked_in 0.0.21

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/linked_in.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{linked_in}
5
+ s.version = "0.0.21"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Peter T. Brown"]
9
+ s.date = %q{2009-11-25}
10
+ s.summary = %q{The linked_in gem wraps the LinkedIn API making it easy to read and write profile information and messages on http://linked_in.com. Full support for OAuth is provided including a wrapper for Pelle's oauth-plugin (http://github.com/pelle/oauth-plugin/). This gem borrowed heavily from junemakers twitter gem (http://github.com/jnunemaker/twitter/).}
11
+ s.email = ["peter@flippyhead.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "docs/sample-oauth-plugin_token.rb", "lib/linked_in.rb", "lib/linked_in/base.rb", "lib/linked_in/oauth.rb", "lib/linked_in/request.rb", "linked_in.gemspec", "script/console", "script/destroy", "script/generate", "spec/fixtures/connections.xml", "spec/fixtures/connections_with_field_selectors.xml", "spec/fixtures/empty.xml", "spec/fixtures/error.xml", "spec/fixtures/network.xml", "spec/fixtures/people.xml", "spec/fixtures/profile.xml", "spec/linked_in/base_spec.rb", "spec/linked_in/oauth_spec.rb", "spec/linked_in/request_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/rspec.rake"]
14
+ s.post_install_message = %q{PostInstall.txt}
15
+ s.rdoc_options = ["--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.homepage = "http://github.com/flippyhead/linked_in"
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.description = %q{The linked_in gem wraps the LinkedIn API, including support for OAuth}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<hoe>, [">= 2.3.3"])
27
+ s.add_runtime_dependency(%q<oauth>, [">= 0.3.5"])
28
+ s.add_runtime_dependency(%q<jordi-xml-object>, [">= 0.9.91"])
29
+ s.add_development_dependency(%q<hoe>, [">= 2.3.3"])
30
+ s.add_development_dependency(%q<oauth>, [">= 0.3.5"])
31
+ s.add_development_dependency(%q<jordi-xml-object>, [">= 0.9.91"])
32
+ else
33
+ s.add_dependency(%q<hoe>, [">= 2.3.3"])
34
+ s.add_dependency(%q<oauth>, [">= 0.3.5"])
35
+ s.add_dependency(%q<jordi-xml-object>, [">= 0.9.91"])
36
+ end
37
+ else
38
+ s.add_dependency(%q<hoe>, [">= 2.3.3"])
39
+ s.add_dependency(%q<oauth>, [">= 0.3.5"])
40
+ s.add_dependency(%q<jordi-xml-object>, [">= 0.9.91"])
41
+ end
42
+ end
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/linkedin.rb'}"
9
+ puts "Loading linkedin gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <connections total="81">
3
+ <person>
4
+ <id>xxxxxxx</id>
5
+ <first-name>John</first-name>
6
+ <last-name>Doe</last-name>
7
+ <headline>Sr. Capital Accountant</headline>
8
+ <location>
9
+ <name>Greater Seattle Area</name>
10
+ <country>
11
+ <code>us</code>
12
+ </country>
13
+ </location>
14
+ <industry>Accounting</industry>
15
+ <api-standard-profile-request>
16
+ <url>http://api.linkedin.com/v1/people/xxxxxx:full</url>
17
+ <headers total="1">
18
+ <http-header>
19
+ <name>x-li-auth-token</name>
20
+ <value>name:DOKj</value>
21
+ </http-header>
22
+ </headers>
23
+ </api-standard-profile-request>
24
+ <site-standard-profile-request>
25
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=12345&amp;authToken=DOKj&amp;authType=name</url>
26
+ </site-standard-profile-request>
27
+ <picture-url>http://media.linkedin.com/mpr/mpr/shrink_80_80/p/3/000/001/059/xxxxxx.jpg</picture-url>
28
+ </person>
29
+ <person>
30
+ <id>yyyyyy</id>
31
+ <first-name>Jay</first-name>
32
+ <last-name>Johnson</last-name>
33
+ <headline>Media Executive</headline>
34
+ <location>
35
+ <name>Miami/Fort Lauderdale Area</name>
36
+ <country>
37
+ <code>us</code>
38
+ </country>
39
+ </location>
40
+ <industry>Online Media</industry>
41
+ <api-standard-profile-request>
42
+ <url>http://api.linkedin.com/v1/people/yyyyy:full</url>
43
+ <headers total="1">
44
+ <http-header>
45
+ <name>x-li-auth-token</name>
46
+ <value>name:nST3</value>
47
+ </http-header>
48
+ </headers>
49
+ </api-standard-profile-request>
50
+ <site-standard-profile-request>
51
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=123123123&amp;authToken=nST3&amp;authType=name</url>
52
+ </site-standard-profile-request>
53
+ <picture-url>http://media.linkedin.com/mpr/mpr/shrink_80_80/p/3/000/00e/216/xxxxx.jpg</picture-url>
54
+ </person>
55
+ </connections>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <connections total="2">
3
+ <person>
4
+ <id>xxxxx</id>
5
+ <first-name>Jeff</first-name>
6
+ </person>
7
+ <person>
8
+ <id>zzzzz</id>
9
+ <first-name>Jay</first-name>
10
+ </person>
11
+ </connections>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <empty/>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <error>
3
+ <status>400</status>
4
+ <timestamp>1256621178299</timestamp>
5
+ <error-code>0000</error-code>
6
+ <message>Did not understand query</message>
7
+ </error>
@@ -0,0 +1,99 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <network>
3
+ <network-stats total="2">
4
+ <property key="degree-1-count">81</property>
5
+ <property key="degree-2-count">34521</property>
6
+ </network-stats>
7
+ <updates total="126" start="0" count="2">
8
+ <update>
9
+ <timestamp>1257289874000</timestamp>
10
+ <update-type>CONN</update-type>
11
+ <update-content>
12
+ <person>
13
+ <id>123456</id>
14
+ <first-name>John</first-name>
15
+ <last-name>Smith</last-name>
16
+ <headline>Program Director</headline>
17
+ <connections total="1">
18
+ <person>
19
+ <id>123123</id>
20
+ <first-name>Joe</first-name>
21
+ <last-name>Green</last-name>
22
+ <headline>President</headline>
23
+ <api-standard-profile-request>
24
+ <url>http://api.linkedin.com/v1/people/xxxxx:full</url>
25
+ <headers total="1">
26
+ <http-header>
27
+ <name>x-li-auth-token</name>
28
+ <value>name:IWMR</value>
29
+ </http-header>
30
+ </headers>
31
+ </api-standard-profile-request>
32
+ <site-standard-profile-request>
33
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=1112234575&amp;authToken=IWMR&amp;authType=name</url>
34
+ </site-standard-profile-request>
35
+ </person>
36
+ </connections>
37
+ <api-standard-profile-request>
38
+ <url>http://api.linkedin.com/v1/people/yyyyy:full</url>
39
+ <headers total="1">
40
+ <http-header>
41
+ <name>x-li-auth-token</name>
42
+ <value>name:A0Kc</value>
43
+ </http-header>
44
+ </headers>
45
+ </api-standard-profile-request>
46
+ <site-standard-profile-request>
47
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=1234552564&amp;authToken=A0Kc&amp;authType=name</url>
48
+ </site-standard-profile-request>
49
+ </person>
50
+ </update-content>
51
+ <is-commentable>false</is-commentable>
52
+ </update>
53
+ <update>
54
+ <timestamp>1257289528000</timestamp>
55
+ <update-type>CONN</update-type>
56
+ <update-content>
57
+ <person>
58
+ <id>54033</id>
59
+ <first-name>Otis</first-name>
60
+ <last-name>Jones</last-name>
61
+ <headline>Rad headline</headline>
62
+ <connections total="1">
63
+ <person>
64
+ <id>12312312</id>
65
+ <first-name>Jane</first-name>
66
+ <last-name>Doe</last-name>
67
+ <headline>Business Development</headline>
68
+ <api-standard-profile-request>
69
+ <url>http://api.linkedin.com/v1/people/zzzzzz:full</url>
70
+ <headers total="1">
71
+ <http-header>
72
+ <name>x-li-auth-token</name>
73
+ <value>name:jBzG</value>
74
+ </http-header>
75
+ </headers>
76
+ </api-standard-profile-request>
77
+ <site-standard-profile-request>
78
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=54321&amp;authToken=jBzG&amp;authType=name</url>
79
+ </site-standard-profile-request>
80
+ </person>
81
+ </connections>
82
+ <api-standard-profile-request>
83
+ <url>http://api.linkedin.com/v1/people/rrrrrr:full</url>
84
+ <headers total="1">
85
+ <http-header>
86
+ <name>x-li-auth-token</name>
87
+ <value>name:iZgD</value>
88
+ </http-header>
89
+ </headers>
90
+ </api-standard-profile-request>
91
+ <site-standard-profile-request>
92
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=444454033&amp;authToken=iZgD&amp;authType=name</url>
93
+ </site-standard-profile-request>
94
+ </person>
95
+ </update-content>
96
+ <is-commentable>false</is-commentable>
97
+ </update>
98
+ </updates>
99
+ </network>
@@ -0,0 +1,100 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <people total="46441" start="0" count="2">
3
+ <person>
4
+ <id>EcTIwdTfXk</id>
5
+ <first-name>John</first-name>
6
+ <last-name>Doe</last-name>
7
+ <headline>Advertising</headline>
8
+ <location>
9
+ <name>Greater Seattle Area</name>
10
+ <country>
11
+ <code>us</code>
12
+ </country>
13
+ </location>
14
+ <industry>Newspapers</industry>
15
+ <connections total="224" />
16
+ <num-recommenders>0</num-recommenders>
17
+ <distance>1</distance>
18
+ <positions total="2">
19
+ <position>
20
+ <id>44074500</id>
21
+ <title>Advertising</title>
22
+ <start-date>
23
+ <year>2008</year>
24
+ <month>5</month>
25
+ </start-date>
26
+ <is-current>true</is-current>
27
+ <company>
28
+ <name>The Times</name>
29
+ </company>
30
+ </position>
31
+ <position>
32
+ <id>2353376126</id>
33
+ <title>Retail Advertising Manager</title>
34
+ <start-date>
35
+ <year>2004</year>
36
+ <month>10</month>
37
+ </start-date>
38
+ <is-current>true</is-current>
39
+ <company>
40
+ <name>Herald-Republic</name>
41
+ </company>
42
+ </position>
43
+ </positions>
44
+ <api-standard-profile-request>
45
+ <url>http://api.linkedin.com/v1/people/xxxxxx:full</url>
46
+ <headers total="1">
47
+ <http-header>
48
+ <name>x-li-auth-token</name>
49
+ <value>OUT_OF_NETWORK:0_t6</value>
50
+ </http-header>
51
+ </headers>
52
+ </api-standard-profile-request>
53
+ <site-standard-profile-request>
54
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=111140338&amp;authToken=0_t6&amp;authType=OUT_OF_NETWORK</url>
55
+ </site-standard-profile-request>
56
+ </person>
57
+ <person>
58
+ <id>xxxx</id>
59
+ <first-name>Andy</first-name>
60
+ <last-name>Hicks</last-name>
61
+ <headline>Resident Manager</headline>
62
+ <location>
63
+ <name>Greater Seattle Area</name>
64
+ <country>
65
+ <code>us</code>
66
+ </country>
67
+ </location>
68
+ <industry>Real Estate</industry>
69
+ <connections total="26" />
70
+ <num-recommenders>0</num-recommenders>
71
+ <distance>1</distance>
72
+ <positions total="1">
73
+ <position>
74
+ <id>23323423</id>
75
+ <title>Resident Manager</title>
76
+ <summary>Perform all duties of the Resident/Property Manager: Lease Administration, Rent Collection/Deposit, Respond to Tenant Requests, Site Maintenance, Marketing and Showing Apartments, Remodel and Tenant Improvement Oversight, Inventory Control/Purchasing, and General Upkeep of a Vintage Brick Apartment Building in West Seattle's Admiral District.</summary>
77
+ <start-date>
78
+ <year>2007</year>
79
+ <month>4</month>
80
+ </start-date>
81
+ <is-current>true</is-current>
82
+ <company>
83
+ <name>The J Apartments</name>
84
+ </company>
85
+ </position>
86
+ </positions>
87
+ <api-standard-profile-request>
88
+ <url>http://api.linkedin.com/v1/people/xxxxx:full</url>
89
+ <headers total="1">
90
+ <http-header>
91
+ <name>x-li-auth-token</name>
92
+ <value>OUT_OF_NETWORK:ATiX</value>
93
+ </http-header>
94
+ </headers>
95
+ </api-standard-profile-request>
96
+ <site-standard-profile-request>
97
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=11235833592&amp;authToken=ATiX&amp;authType=OUT_OF_NETWORK</url>
98
+ </site-standard-profile-request>
99
+ </person>
100
+ </people>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <person>
3
+ <first-name>Peter</first-name>
4
+ <last-name>Brown</last-name>
5
+ <headline>CTO at Pathable, Inc.</headline>
6
+ <site-standard-profile-request>
7
+ <url>http://www.linkedin.com/profile?viewProfile=&amp;key=280094&amp;authToken=GkV9&amp;authType=name</url>
8
+ </site-standard-profile-request>
9
+ </person>
@@ -0,0 +1,150 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe LinkedIn::Base, 'when doing CRUD' do
4
+ before do
5
+ oauth = LinkedIn::OAuth.new('token', 'secret')
6
+ @access_token = OAuth::AccessToken.new(oauth.consumer, 'atoken', 'asecret')
7
+ oauth.stub!(:access_token => @access_token)
8
+ @linkedin = LinkedIn::Base.new(oauth)
9
+ end
10
+
11
+ context "initialize" do
12
+ it "should require a client" do
13
+ @linkedin.client.should respond_to(:get)
14
+ @linkedin.client.should respond_to(:post)
15
+ end
16
+
17
+ it "should delegate get to the client" do
18
+ @access_token.should_receive(:get).with('/foo').and_return(nil)
19
+ @linkedin.get('/foo')
20
+ end
21
+
22
+ it "should delegate post to the client" do
23
+ @access_token.should_receive(:post).with('/foo', {:bar => 'baz'}).and_return(nil)
24
+ @linkedin.post('/foo', {:bar => 'baz'})
25
+ end
26
+ end
27
+
28
+ context "getting profiles" do
29
+ it "should get basic profile" do
30
+ stub_get('/v1/people/~', 'profile.xml')
31
+ profile = @linkedin.profile
32
+ profile['first-name'].should == 'Peter'
33
+ profile['last-name'].should == 'Brown'
34
+ profile['site-standard-profile-request'].url.should == 'http://www.linkedin.com/profile?viewProfile=&amp;key=280094&amp;authToken=GkV9&amp;authType=name'
35
+ end
36
+
37
+ it "should get full profile " do
38
+ stub_get('/v1/people/~:full', 'profile.xml')
39
+ profile = @linkedin.profile(:my, :full)
40
+ profile['first-name'].should == 'Peter'
41
+ end
42
+
43
+ it "should get profile with field selectors" do
44
+ stub_get('/v1/people/~:(first-name,last-name)', 'profile.xml')
45
+ profile = @linkedin.profile(:my, ['first-name', 'last-name'])
46
+ profile['first-name'].should == 'Peter'
47
+ end
48
+
49
+ it "should default to ~ (authenticated users profile)" do
50
+ @linkedin.should_receive(:perform_get).with('/v1/people/~', :query => {}).and_return(nil)
51
+ profile = @linkedin.profile
52
+ end
53
+
54
+ it "should get public profile from URL" do
55
+ stub_get('/v1/people/url=http://www.linkedin.com/pub/peter-brown/0/116/112', 'profile.xml')
56
+ profile = @linkedin.profile(:url => 'http://www.linkedin.com/pub/peter-brown/0/116/112')
57
+ profile['first-name'].should == 'Peter'
58
+ end
59
+
60
+ it "should get profile from ID" do
61
+ stub_get('/v1/people/id=12345', 'profile.xml')
62
+ profile = @linkedin.profile(:id => '12345')
63
+ profile['first-name'].should == 'Peter'
64
+ end
65
+
66
+ it "should get full public profile from ID" do
67
+ stub_get('/v1/people/id=12345:full', 'profile.xml')
68
+ profile = @linkedin.profile({:id => '12345'}, :full)
69
+ profile['first-name'].should == 'Peter'
70
+ end
71
+
72
+ it "should get profile from ID with field selectors" do
73
+ stub_get('/v1/people/id=12345:(first-name,last-name)', 'profile.xml')
74
+ profile = @linkedin.profile({:id => '12345'}, ['first-name', 'last-name'])
75
+ profile['first-name'].should == 'Peter'
76
+ end
77
+
78
+ end
79
+
80
+ context "getting connections" do
81
+ it "should get connections" do
82
+ stub_get('/v1/people/~/connections', 'connections.xml')
83
+ connections = @linkedin.connections
84
+ connections['total'].should == '81' # attribute
85
+ connections['person'].size.should == 2 # array of people
86
+ connections['person'][0]['first-name'].should == 'John'
87
+ end
88
+
89
+ it "should get connections with query params" do
90
+ stub_get('/v1/people/~/connections?count=20&start=0', 'connections.xml')
91
+ connections = @linkedin.connections(:my, nil, :start => 0, :count => 20)
92
+ connections['person'][0]['first-name'].should == 'John'
93
+ end
94
+
95
+ it "should get connections with field selectors" do
96
+ stub_get('/v1/people/~/connections:(id,first-name)', 'connections_with_field_selectors.xml')
97
+ connections = @linkedin.connections(:my, ['id', 'first-name'])
98
+ connections['person'][0]['first-name'].should == 'Jeff'
99
+ end
100
+ end
101
+
102
+ context "getting people" do
103
+ it "should get people" do
104
+ stub_get('/v1/people', 'people.xml')
105
+ people = @linkedin.people
106
+ people['total'].should == '46441' # attribute
107
+ people['person'].size.should == 2
108
+ end
109
+ end
110
+
111
+ context "getting network updates" do
112
+ it "should get full network update" do
113
+ stub_get('/v1/people/~/network', 'network.xml')
114
+ network = @linkedin.network
115
+ network['network-stats'].size.should == 2
116
+ end
117
+
118
+ it "should include stat properties" do
119
+ stub_get('/v1/people/~/network', 'network.xml')
120
+ network = @linkedin.network
121
+ network['network-stats']['property'].size.should == 2
122
+ end
123
+
124
+ it "should include first ten update details" do
125
+ stub_get('/v1/people/~/network', 'network.xml')
126
+ network = @linkedin.network
127
+ network['updates']['update'].size.should == 2
128
+ end
129
+
130
+ it "should get with query params" do
131
+ stub_get('/v1/people/~/network?count=20&start=0', 'network.xml')
132
+ network = @linkedin.network(:start => 0, :count => 20)
133
+ end
134
+ end
135
+
136
+ context 'posting network activity updates' do
137
+ it 'should post an update' do
138
+ stub_post('/v1/people/~/person-activities', 'empty.xml')
139
+ activities = @linkedin.person_activities('some update')
140
+ end
141
+ end
142
+
143
+ context 'putting current status updates' do
144
+ it 'should put current status update' do
145
+ stub_put('/v1/people/~/current-status', 'empty.xml')
146
+ @linkedin.current_status('some update')
147
+ end
148
+ end
149
+
150
+ end