brienw-linkedin 0.3.7

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.
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