brienw-linkedin 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.autotest +14 -0
  2. data/.document +5 -0
  3. data/.gemtest +0 -0
  4. data/.gitignore +41 -0
  5. data/.rspec +1 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE +20 -0
  9. data/README.markdown +78 -0
  10. data/Rakefile +19 -0
  11. data/changelog.markdown +71 -0
  12. data/examples/authenticate.rb +21 -0
  13. data/examples/network.rb +12 -0
  14. data/examples/profile.rb +18 -0
  15. data/examples/sinatra.rb +77 -0
  16. data/examples/status.rb +9 -0
  17. data/lib/linked_in/api.rb +6 -0
  18. data/lib/linked_in/api/query_methods.rb +73 -0
  19. data/lib/linked_in/api/update_methods.rb +55 -0
  20. data/lib/linked_in/client.rb +46 -0
  21. data/lib/linked_in/errors.rb +19 -0
  22. data/lib/linked_in/helpers.rb +6 -0
  23. data/lib/linked_in/helpers/authorization.rb +68 -0
  24. data/lib/linked_in/helpers/request.rb +80 -0
  25. data/lib/linked_in/mash.rb +68 -0
  26. data/lib/linked_in/search.rb +56 -0
  27. data/lib/linked_in/version.rb +11 -0
  28. data/lib/linkedin.rb +32 -0
  29. data/linkedin.gemspec +25 -0
  30. data/spec/cases/api_spec.rb +92 -0
  31. data/spec/cases/linkedin_spec.rb +37 -0
  32. data/spec/cases/mash_spec.rb +85 -0
  33. data/spec/cases/oauth_spec.rb +166 -0
  34. data/spec/cases/search_spec.rb +206 -0
  35. data/spec/fixtures/cassette_library/LinkedIn_Api/Company_API.yml +73 -0
  36. data/spec/fixtures/cassette_library/LinkedIn_Client/_authorize_from_request.yml +28 -0
  37. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token.yml +28 -0
  38. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/with_a_callback_url.yml +28 -0
  39. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/with_default_options.yml +28 -0
  40. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_company_name_option.yml +135 -0
  41. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options.yml +122 -0
  42. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options_with_fields.yml +72 -0
  43. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_keywords_string_parameter.yml +136 -0
  44. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_single_keywords_option.yml +136 -0
  45. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_single_keywords_option_with_pagination.yml +128 -0
  46. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_options_with_fields.yml +252 -0
  47. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_string_parameter.yml +73 -0
  48. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option.yml +71 -0
  49. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_a_facet.yml +111 -0
  50. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_facets_to_return.yml +71 -0
  51. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_single_keywords_option_with_pagination.yml +66 -0
  52. data/spec/helper.rb +30 -0
  53. metadata +295 -0
@@ -0,0 +1,14 @@
1
+ Autotest.add_hook(:initialize) do |at|
2
+ at.add_exception(".git")
3
+ end
4
+
5
+ Autotest.add_hook(:initialize) do |at|
6
+ at.clear_mappings
7
+
8
+ at.add_mapping %r%/^lib/(.*)\.rb$% do |_, m|
9
+ possible = File.basename(m[1])
10
+ files_matching %r%^test/.*(#{possible}_test|test_#{possible})\.rb$%
11
+ end
12
+
13
+ at.add_mapping(%r%^test/.*\.rb$%) {|filename, _| filename }
14
+ end
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
File without changes
@@ -0,0 +1,41 @@
1
+ *.gem
2
+ *.rbc
3
+ *.sw[a-p]
4
+ *.tmproj
5
+ *.tmproject
6
+ *.un~
7
+ *~
8
+ .DS_Store
9
+ .Spotlight-V100
10
+ .Trashes
11
+ ._*
12
+ .bundle
13
+ .config
14
+ .directory
15
+ .elc
16
+ .redcar
17
+ .yardoc
18
+ .rvmrc
19
+ /.emacs.desktop
20
+ /.emacs.desktop.lock
21
+ Desktop.ini
22
+ Gemfile.lock
23
+ Icon?
24
+ InstalledFiles
25
+ Session.vim
26
+ Thumbs.db
27
+ \#*\#
28
+ _yardoc
29
+ auto-save-list
30
+ coverage
31
+ doc/
32
+ lib/bundler/man
33
+ pkg
34
+ pkg/*
35
+ rdoc
36
+ spec/reports
37
+ test/tmp
38
+ test/version_tmp
39
+ tmp
40
+ tmtags
41
+ tramp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ platforms :jruby do
4
+ gem 'jruby-openssl', '~> 0.7'
5
+ end
6
+
7
+ gemspec
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,78 @@
1
+ # LinkedIn
2
+
3
+ Ruby wrapper for the [LinkedIn API](http://developer.linkedin.com). Heavily inspired by [John Nunemaker's](http://github.com/jnunemaker) [Twitter gem](http://github.com/jnunemaker/twitter), the LinkedIn gem provides an easy-to-use wrapper for LinkedIn's Oauth/XML APIs.
4
+
5
+ Travis CI : [![Build Status](https://secure.travis-ci.org/pengwynn/linkedin.png)](http://travis-ci.org/pengwynn/linkedin)
6
+
7
+ ## Installation
8
+
9
+ [sudo] gem install linkedin
10
+
11
+ ## Usage
12
+
13
+ ### Authenticate
14
+
15
+ LinkedIn's API uses Oauth for authentication. Luckily, the LinkedIn gem hides most of the gory details from you.
16
+
17
+ require 'rubygems'
18
+ require 'linkedin'
19
+
20
+ # get your api keys at https://www.linkedin.com/secure/developer
21
+ client = LinkedIn::Client.new('your_consumer_key', 'your_consumer_secret')
22
+ rtoken = client.request_token.token
23
+ rsecret = client.request_token.secret
24
+
25
+ # to test from your desktop, open the following url in your browser
26
+ # and record the pin it gives you
27
+ client.request_token.authorize_url
28
+ => "https://api.linkedin.com/uas/oauth/authorize?oauth_token=<generated_token>"
29
+
30
+ # then fetch your access keys
31
+ client.authorize_from_request(rtoken, rsecret, pin)
32
+ => ["OU812", "8675309"] # <= save these for future requests
33
+
34
+ # or authorize from previously fetched access keys
35
+ c.authorize_from_access("OU812", "8675309")
36
+
37
+ # you're now free to move about the cabin, call any API method
38
+
39
+ ### Profile examples
40
+
41
+ # get the profile for the authenticated user
42
+ client.profile
43
+
44
+ # get a profile for someone found in network via ID
45
+ client.profile(:id => 'gNma67_AdI')
46
+
47
+ # get a profile for someone via their public profile url
48
+ client.profile(:url => 'http://www.linkedin.com/in/netherland')
49
+
50
+
51
+
52
+ More examples in the [examples folder](http://github.com/pengwynn/linkedin/blob/master/examples).
53
+
54
+ For a nice example on using this in a [Rails App](http://pivotallabs.com/users/will/blog/articles/1096-linkedin-gem-for-a-web-app).
55
+
56
+ If you want to play with the LinkedIn api without using the gem, have a look at the [apigee LinkedIn console](http://app.apigee.com/console/linkedin).
57
+
58
+ ## TODO
59
+
60
+ * Change to json api
61
+ * Update and correct test suite
62
+ * Change to Faraday for authentication
63
+ * Implement Messaging APIs
64
+
65
+ ## Note on Patches/Pull Requests
66
+
67
+ * Fork the project.
68
+ * Make your feature addition or bug fix.
69
+ * Add tests for it. This is important so I don't break it in a
70
+ future version unintentionally.
71
+ * Commit, do not mess with rakefile, version, or history.
72
+ (if you want to have your own version, that is fine but
73
+ bump version in a commit by itself I can ignore when I pull)
74
+ * Send me a pull request. Bonus points for topic branches.
75
+
76
+ ## Copyright
77
+
78
+ Copyright (c) 2009-11 [Wynn Netherland](http://wynnnetherland.com). See LICENSE for details.
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :test => :spec
10
+ task :default => :spec
11
+
12
+ require 'rdoc/task'
13
+ require File.expand_path('../lib/linked_in/version', __FILE__)
14
+ RDoc::Task.new do |rdoc|
15
+ rdoc.rdoc_dir = 'rdoc'
16
+ rdoc.title = "linkedin #{LinkedIn::VERSION::STRING}"
17
+ rdoc.rdoc_files.include('README*')
18
+ rdoc.rdoc_files.include('lib/**/*.rb')
19
+ end
@@ -0,0 +1,71 @@
1
+ # Changelog
2
+
3
+ ## 0.2.x - March x, 2010
4
+
5
+ * Removed Crack as a dependency, Nokogiri FTW
6
+
7
+ ## 0.2.1 - March 1, 2010
8
+
9
+ * Big dependency clean up, only OAuth and Nokogiri are really needed.
10
+
11
+ * Use Nokogiri for xml generation (thanks Leonid Shevtsov - leonid-shevtsov)
12
+
13
+ * Like and Likes supported
14
+
15
+ * Escape querystring args
16
+
17
+ * General coding cleanup
18
+
19
+ * Added Languages, Skills, Publications, Patents and Phone Numbers (thanks Tadas Tamošauskas - medwezys)
20
+
21
+ * Extra fields added to profile (thanks Tadas Tamošauskas - medwezys)
22
+
23
+ * public\_profile\_field added to Profile (thanks troysteinbauer)
24
+
25
+ * Added recommendations (thanks Erol)
26
+
27
+ * Added current-share
28
+
29
+ * Added default\_profile\__fields config option
30
+
31
+ ## 0.1.7 - February 5, 2010
32
+
33
+ * New group join status support JGRP from Terry Ray
34
+
35
+ ## 0.1.6 - January 20, 2010
36
+
37
+ * Fixed bug with network status update connection collections - thanks Terry Ray
38
+
39
+ ## 0.1.5 - January 13, 2010
40
+
41
+ * Added education and profile fields missing from updated LinkedIn docs
42
+
43
+ ## 0.1.4 - January 13, 2010
44
+
45
+ * Applied patch for position end month/year from @holman
46
+
47
+ ## 0.1.3 - December 24, 2009
48
+
49
+ * Added configure block for easier initialization of consumer token, secret
50
+
51
+ ## 0.1.1 - December 8, 2009
52
+
53
+ * Applied patch from [nfo](http://github.com/nfo) to fix error handling
54
+
55
+ ## 0.1.0 - November 25, 2009
56
+
57
+ * Network updates API support
58
+
59
+ * Search API support
60
+
61
+ * Updates API support
62
+
63
+ ## 0.0.2 - November 25, 2009
64
+
65
+ * Swapped out Crack for ROXML for prettier object access
66
+
67
+ * Added more tests for Profile API
68
+
69
+ ## 0.0.1 - November 24, 2009
70
+
71
+ * Initial release
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'linkedin'
3
+
4
+ # get your api keys at https://www.linkedin.com/secure/developer
5
+ client = LinkedIn::Client.new('your_consumer_key', 'your_consumer_secret')
6
+ rtoken = client.request_token.token
7
+ rsecret = client.request_token.secret
8
+
9
+ # to test from your desktop, open the following url in your browser
10
+ # and record the pin it gives you
11
+ client.request_token.authorize_url
12
+ => "https://api.linkedin.com/uas/oauth/authorize?oauth_token=<generated_token>"
13
+
14
+ # then fetch your access keys
15
+ client.authorize_from_request(rtoken, rsecret, pin)
16
+ => ["OU812", "8675309"] # <= save these for future requests
17
+
18
+ # or authorize from previously fetched access keys
19
+ c.authorize_from_access("OU812", "8675309")
20
+
21
+ # you're now free to move about the cabin, call any API method
@@ -0,0 +1,12 @@
1
+ # AUTHENTICATE FIRST found in examples/authenticate.rb
2
+
3
+ # client is a LinkedIn::Client
4
+
5
+ # get network updates for the authenticated user
6
+ client.network_updates
7
+
8
+ # get profile picture changes
9
+ client.network_updates(:type => 'PICT')
10
+
11
+ # view connections for the currently authenticated user
12
+ client.connections
@@ -0,0 +1,18 @@
1
+ # AUTHENTICATE FIRST found in examples/authenticate.rb
2
+
3
+ # client is a LinkedIn::Client
4
+
5
+ # get the profile for the authenticated user
6
+ client.profile
7
+
8
+ # get a profile for someone found in network via ID
9
+ client.profile(:id => 'gNma67_AdI')
10
+
11
+ # get a profile for someone via their public profile url
12
+ client.profile(:url => 'http://www.linkedin.com/in/netherland')
13
+
14
+ # provides the ability to access authenticated user's company field in the profile
15
+ user = client.profile(:fields => %w(positions))
16
+ companies = user.positions.all.map{|t| t.company}
17
+ # Example: most recent company can be accessed via companies[0]
18
+
@@ -0,0 +1,77 @@
1
+ require "rubygems"
2
+ require "haml"
3
+ require "sinatra"
4
+ require "linkedin"
5
+
6
+ enable :sessions
7
+
8
+ helpers do
9
+ def login?
10
+ session[:atoken].nil?
11
+ end
12
+
13
+ def profile
14
+ linkedin_client.profile unless session[:atoken].nil?
15
+ end
16
+
17
+ def connections
18
+ linkedin_client.connections unless session[:atoken].nil?
19
+ end
20
+
21
+ private
22
+ def linkedin_client
23
+ client = LinkedIn::Client.new(settings.api, settings.secret)
24
+ client.authorize_from_access(session[:atoken], session[:asecret])
25
+ client
26
+ end
27
+
28
+ end
29
+
30
+ configure do
31
+ # get your api keys at https://www.linkedin.com/secure/developer
32
+ set :api, "your_api_key"
33
+ set :secret, "your_secret"
34
+ end
35
+
36
+ get "/" do
37
+ haml :index
38
+ end
39
+
40
+ get "/auth" do
41
+ client = LinkedIn::Client.new(settings.api, settings.secret)
42
+ request_token = client.request_token(:oauth_callback => "http://#{request.host}:#{request.port}/auth/callback")
43
+ session[:rtoken] = request_token.token
44
+ session[:rsecret] = request_token.secret
45
+
46
+ redirect client.request_token.authorize_url
47
+ end
48
+
49
+ get "/auth/logout" do
50
+ session[:atoken] = nil
51
+ redirect "/"
52
+ end
53
+
54
+ get "/auth/callback" do
55
+ client = LinkedIn::Client.new(settings.api, settings.secret)
56
+ if session[:atoken].nil?
57
+ pin = params[:oauth_verifier]
58
+ atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
59
+ session[:atoken] = atoken
60
+ session[:asecret] = asecret
61
+ end
62
+ redirect "/"
63
+ end
64
+
65
+
66
+ __END__
67
+ @@index
68
+ -if login?
69
+ %p Welcome #{profile.first_name}!
70
+ %a{:href => "/auth/logout"} Logout
71
+ %p= profile.headline
72
+ %br
73
+ %div= "You have #{connections.total} connections!"
74
+ -connections.all.each do |c|
75
+ %div= "#{c.first_name} #{c.last_name} - #{c.headline}"
76
+ -else
77
+ %a{:href => "/auth"} Login using LinkedIn
@@ -0,0 +1,9 @@
1
+ # AUTHENTICATE FIRST found in examples/authenticate.rb
2
+
3
+ # client is a LinkedIn::Client
4
+
5
+ # update status for the authenticated user
6
+ client.update_status('is playing with the LinkedIn Ruby gem')
7
+
8
+ # clear status for the currently logged in user
9
+ client.clear_status
@@ -0,0 +1,6 @@
1
+ module LinkedIn
2
+ module Api
3
+ autoload :QueryMethods, "linked_in/api/query_methods"
4
+ autoload :UpdateMethods, "linked_in/api/update_methods"
5
+ end
6
+ end
@@ -0,0 +1,73 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ module QueryMethods
5
+
6
+ def profile(options={})
7
+ path = person_path(options)
8
+ simple_query(path, options)
9
+ end
10
+
11
+ def connections(options={})
12
+ path = "#{person_path(options)}/connections"
13
+ simple_query(path, options)
14
+ end
15
+
16
+ def network_updates(options={})
17
+ path = "#{person_path(options)}/network/updates"
18
+ simple_query(path, options)
19
+ end
20
+
21
+ def company(options = {})
22
+ path = company_path(options)
23
+ simple_query(path, options)
24
+ end
25
+
26
+ private
27
+
28
+ def simple_query(path, options={})
29
+ fields = options.delete(:fields) || LinkedIn.default_profile_fields
30
+
31
+ if options.delete(:public)
32
+ path +=":public"
33
+ elsif fields
34
+ path +=":(#{fields.map{ |f| f.to_s.gsub("_","-") }.join(',')})"
35
+ end
36
+
37
+ headers = options.delete(:headers) || {}
38
+ params = options.map { |k,v| "#{k}=#{v}" }.join("&")
39
+ path += "?#{params}" if not params.empty?
40
+
41
+ Mash.from_json(get(path, headers))
42
+ end
43
+
44
+ def person_path(options)
45
+ path = "/people/"
46
+ if id = options.delete(:id)
47
+ path += "id=#{id}"
48
+ elsif url = options.delete(:url)
49
+ path += "url=#{CGI.escape(url)}"
50
+ else
51
+ path += "~"
52
+ end
53
+ end
54
+
55
+ def company_path(options)
56
+ path = "/companies/"
57
+ if id = options.delete(:id)
58
+ path += "id=#{id}"
59
+ elsif url = options.delete(:url)
60
+ path += "url=#{CGI.escape(url)}"
61
+ elsif name = options.delete(:name)
62
+ path += "universal-name=#{CGI.escape(name)}"
63
+ elsif domain = options.delete(:domain)
64
+ path += "email-domain=#{CGI.escape(domain)}"
65
+ else
66
+ path += "~"
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end