linkedin 0.4.6 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/.yardopts +7 -0
  4. data/{changelog.markdown → CHANGELOG.md} +5 -1
  5. data/EXAMPLES.md +199 -0
  6. data/Gemfile +4 -0
  7. data/README.md +43 -0
  8. data/Rakefile +2 -7
  9. data/lib/linked_in/api.rb +34 -2
  10. data/lib/linked_in/api/communications.rb +44 -0
  11. data/lib/linked_in/api/companies.rb +128 -0
  12. data/lib/linked_in/api/groups.rb +115 -0
  13. data/lib/linked_in/api/jobs.rb +64 -0
  14. data/lib/linked_in/api/people.rb +72 -0
  15. data/lib/linked_in/api/query_helpers.rb +86 -0
  16. data/lib/linked_in/api/share_and_social_stream.rb +133 -0
  17. data/lib/linked_in/client.rb +7 -2
  18. data/lib/linked_in/errors.rb +12 -2
  19. data/lib/linked_in/mash.rb +31 -4
  20. data/lib/linked_in/search.rb +16 -1
  21. data/lib/linked_in/version.rb +1 -1
  22. data/lib/linkedin.rb +4 -1
  23. data/linkedin.gemspec +5 -3
  24. data/spec/cases/api_spec.rb +15 -5
  25. data/spec/cases/mash_spec.rb +30 -2
  26. data/spec/cases/oauth_spec.rb +5 -6
  27. data/spec/cases/search_spec.rb +53 -23
  28. data/spec/fixtures/cassette_library/LinkedIn_Api/Company_API.yml +3 -3
  29. data/spec/fixtures/cassette_library/LinkedIn_Api/Company_API/should_load_correct_company_data.yml +81 -0
  30. data/spec/fixtures/cassette_library/LinkedIn_Client/{_authorize_from_request.yml → _authorize_from_request/should_return_a_valid_access_token.yml} +0 -0
  31. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/{with_a_callback_url.yml → with_a_callback_url/should_return_a_valid_access_token.yml} +0 -0
  32. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token/{with_default_options.yml → with_default_options/should_return_a_valid_request_token.yml} +0 -0
  33. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/{by_company_name_option.yml → by_company_name_option/should_perform_a_search.yml} +8 -9
  34. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_email_address/should_perform_a_people_search.yml +57 -0
  35. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/{by_first_name_and_last_name_options.yml → by_first_name_and_last_name_options/should_perform_a_search.yml} +15 -15
  36. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options_with_fields/should_perform_a_search.yml +114 -0
  37. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/{by_keywords_string_parameter.yml → by_keywords_string_parameter/should_perform_a_search.yml} +8 -9
  38. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_multiple_email_address/should_perform_a_multi-email_search.yml +59 -0
  39. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/{by_single_keywords_option.yml → by_single_keywords_option/should_perform_a_search.yml} +8 -9
  40. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/{by_single_keywords_option_with_pagination.yml → by_single_keywords_option_with_pagination/should_perform_a_search.yml} +1 -3
  41. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/email_search_returns_unauthorized/should_raise_an_unauthorized_error.yml +59 -0
  42. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_options_with_fields/should_perform_a_search.yml +43 -0
  43. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/{by_keywords_string_parameter.yml → by_keywords_string_parameter/should_perform_a_company_search.yml} +19 -19
  44. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/{by_single_keywords_option.yml → by_single_keywords_option/should_perform_a_company_search.yml} +19 -19
  45. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/{by_single_keywords_option_with_facets_to_return.yml → by_single_keywords_option_with_facets_to_return/should_return_a_facet.yml} +14 -14
  46. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/{by_single_keywords_option_with_pagination.yml → by_single_keywords_option_with_pagination/should_perform_a_search.yml} +15 -15
  47. data/spec/helper.rb +9 -5
  48. metadata +76 -61
  49. data/.document +0 -5
  50. data/README.markdown +0 -84
  51. data/examples/authenticate.rb +0 -26
  52. data/examples/communication.rb +0 -7
  53. data/examples/network.rb +0 -12
  54. data/examples/profile.rb +0 -18
  55. data/examples/sinatra.rb +0 -77
  56. data/examples/status.rb +0 -6
  57. data/lib/linked_in/api/query_methods.rb +0 -176
  58. data/lib/linked_in/api/update_methods.rb +0 -85
  59. data/spec/fixtures/cassette_library/LinkedIn_Client/_request_token.yml +0 -37
  60. data/spec/fixtures/cassette_library/LinkedIn_Search/_search/by_first_name_and_last_name_options_with_fields.yml +0 -112
  61. data/spec/fixtures/cassette_library/LinkedIn_Search/_search_company/by_keywords_options_with_fields.yml +0 -232
@@ -0,0 +1,115 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ # Groups API
5
+ #
6
+ # @see http://developer.linkedin.com/documents/groups-api Groups API
7
+ # @see http://developer.linkedin.com/documents/groups-fields Groups Fields
8
+ #
9
+ # The following API actions do not have corresponding methods in
10
+ # this module
11
+ #
12
+ # * PUT Change my Group Settings
13
+ # * POST Change my Group Settings
14
+ # * DELETE Leave a group
15
+ # * PUT Follow/unfollow a Group post
16
+ # * PUT Flag a Post as a Promotion or Job
17
+ # * DELETE Delete a Post
18
+ # * DELETE Flag a post as inappropriate
19
+ # * DELETE A comment or flag comment as inappropriate
20
+ # * DELETE Remove a Group Suggestion
21
+ #
22
+ # [(contribute here)](https://github.com/hexgnu/linkedin)
23
+ module Groups
24
+
25
+ # Retrieve group suggestions for the current user
26
+ #
27
+ # Permissions: r_fullprofile
28
+ #
29
+ # @see http://developer.linkedin.com/documents/job-bookmarks-and-suggestions
30
+ #
31
+ # @macro person_path_options
32
+ # @return [LinkedIn::Mash]
33
+ def group_suggestions(options = {})
34
+ path = "#{person_path(options)}/suggestions/groups"
35
+ simple_query(path, options)
36
+ end
37
+
38
+ # Retrieve the groups a current user belongs to
39
+ #
40
+ # Permissions: rw_groups
41
+ #
42
+ # @see http://developer.linkedin.com/documents/groups-api
43
+ #
44
+ # @macro person_path_options
45
+ # @return [LinkedIn::Mash]
46
+ def group_memberships(options = {})
47
+ path = "#{person_path(options)}/group-memberships"
48
+ simple_query(path, options)
49
+ end
50
+
51
+ # Retrieve the profile of a group
52
+ #
53
+ # Permissions: rw_groups
54
+ #
55
+ # @see http://developer.linkedin.com/documents/groups-api
56
+ #
57
+ # @param [Hash] options identifies the group or groups
58
+ # @optio options [String] :id identifier for the group
59
+ # @return [LinkedIn::Mash]
60
+ def group_profile(options)
61
+ path = group_path(options)
62
+ simple_query(path, options)
63
+ end
64
+
65
+ # Retrieve the posts in a group
66
+ #
67
+ # Permissions: rw_groups
68
+ #
69
+ # @see http://developer.linkedin.com/documents/groups-api
70
+ #
71
+ # @param [Hash] options identifies the group or groups
72
+ # @optio options [String] :id identifier for the group
73
+ # @optio options [String] :count
74
+ # @optio options [String] :start
75
+ # @return [LinkedIn::Mash]
76
+ def group_posts(options)
77
+ path = "#{group_path(options)}/posts"
78
+ simple_query(path, options)
79
+ end
80
+
81
+ # @deprecated Use {#add_group_share} instead
82
+ def post_group_discussion(group_id, discussion)
83
+ warn 'Use add_group_share over post_group_discussion. This will be taken out in future versions'
84
+ add_group_share(group_id, discussion)
85
+ end
86
+
87
+ # Create a share for a company that the authenticated user
88
+ # administers
89
+ #
90
+ # Permissions: rw_groups
91
+ #
92
+ # @see http://developer.linkedin.com/documents/groups-api#create
93
+ #
94
+ # @param [String] group_id Group ID
95
+ # @macro share_input_fields
96
+ # @return [void]
97
+ def add_group_share(group_id, share)
98
+ path = "/groups/#{group_id}/posts"
99
+ post(path, MultiJson.dump(share), "Content-Type" => "application/json")
100
+ end
101
+
102
+ # (Update) User joins, or requests to join, a group
103
+ #
104
+ # @see http://developer.linkedin.com/documents/groups-api#membergroups
105
+ #
106
+ # @param [String] group_id Group ID
107
+ # @return [void]
108
+ def join_group(group_id)
109
+ path = "/people/~/group-memberships/#{group_id}"
110
+ body = {'membership-state' => {'code' => 'member' }}
111
+ put(path, MultiJson.dump(body), "Content-Type" => "application/json")
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,64 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ # Jobs API
5
+ #
6
+ # @see http://developer.linkedin.com/documents/job-lookup-api-and-fields Job Lookup API and Fields
7
+ # @see http://developer.linkedin.com/documents/job-bookmarks-and-suggestions Job Bookmarks and Suggestions
8
+ #
9
+ # The following API actions do not have corresponding methods in
10
+ # this module
11
+ #
12
+ # * DELETE a Job Bookmark
13
+ #
14
+ # [(contribute here)](https://github.com/hexgnu/linkedin)
15
+ module Jobs
16
+
17
+ # Retrieve likes on a particular company update:
18
+ #
19
+ # @see http://developer.linkedin.com/reading-company-shares
20
+ #
21
+ # @param [Hash] options identifies the job
22
+ # @option options [String] id unique identifier for a job
23
+ # @return [LinkedIn::Mash]
24
+ def job(options = {})
25
+ path = jobs_path(options)
26
+ simple_query(path, options)
27
+ end
28
+
29
+ # Retrieve the current members' job bookmarks
30
+ #
31
+ # @see http://developer.linkedin.com/documents/job-bookmarks-and-suggestions
32
+ #
33
+ # @macro person_path_options
34
+ # @return [LinkedIn::Mash]
35
+ def job_bookmarks(options = {})
36
+ path = "#{person_path(options)}/job-bookmarks"
37
+ simple_query(path, options)
38
+ end
39
+
40
+ # Retrieve job suggestions for the current user
41
+ #
42
+ # @see http://developer.linkedin.com/documents/job-bookmarks-and-suggestions
43
+ #
44
+ # @macro person_path_options
45
+ # @return [LinkedIn::Mash]
46
+ def job_suggestions(options = {})
47
+ path = "#{person_path(options)}/suggestions/job-suggestions"
48
+ simple_query(path, options)
49
+ end
50
+
51
+ # Create a job bookmark for the authenticated user
52
+ #
53
+ # @see http://developer.linkedin.com/documents/job-bookmarks-and-suggestions
54
+ #
55
+ # @param [String] job_id Job ID
56
+ # @return [void]
57
+ def add_job_bookmark(job_id)
58
+ path = "/people/~/job-bookmarks"
59
+ body = {'job' => {'id' => job_id}}
60
+ post(path, MultiJson.dump(body), "Content-Type" => "application/json")
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,72 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ # People APIs
5
+ #
6
+ # @see http://developer.linkedin.com/documents/people People API
7
+ # @see http://developer.linkedin.com/documents/profile-fields Profile Fields
8
+ # @see http://developer.linkedin.com/documents/field-selectors Field Selectors
9
+ # @see http://developer.linkedin.com/documents/accessing-out-network-profiles Accessing Out of Network Profiles
10
+ module People
11
+
12
+ # Retrieve a member's LinkedIn profile.
13
+ #
14
+ # Permissions: r_basicprofile, r_fullprofile
15
+ #
16
+ # @see http://developer.linkedin.com/documents/profile-api
17
+ # @macro person_path_options
18
+ # @option options [string] :secure-urls if 'true' URLs in responses will be HTTPS
19
+ # @return [LinkedIn::Mash]
20
+ def profile(options={})
21
+ path = person_path(options)
22
+ simple_query(path, options)
23
+ end
24
+
25
+ # Retrieve a list of 1st degree connections for a user who has
26
+ # granted access to his/her account
27
+ #
28
+ # Permissions: r_network
29
+ #
30
+ # @see http://developer.linkedin.com/documents/connections-api
31
+ #
32
+ # @macro person_path_options
33
+ # @return [LinkedIn::Mash]
34
+ def connections(options={})
35
+ path = "#{person_path(options)}/connections"
36
+ simple_query(path, options)
37
+ end
38
+
39
+ # Retrieve a list of the latest set of 1st degree connections for a
40
+ # user
41
+ #
42
+ # Permissions: r_network
43
+ #
44
+ # @see http://developer.linkedin.com/documents/connections-api
45
+ #
46
+ # @param [String] modified_since timestamp indicating since when
47
+ # you want to retrieve new connections
48
+ # @macro person_path_options
49
+ # @return [LinkedIn::Mash]
50
+ def new_connections(modified_since, options={})
51
+ options.merge!('modified' => 'new', 'modified-since' => modified_since)
52
+ path = "#{person_path(options)}/connections"
53
+ simple_query(path, options)
54
+ end
55
+
56
+ # Retrieve the picture url
57
+ # http://api.linkedin.com/v1/people/~/picture-urls::(original)
58
+ #
59
+ # Permissions: r_network
60
+ #
61
+ # @options [String] :id, the id of the person for whom you want the profile picture
62
+ # @options [String] :picture_size, default: 'original'
63
+ #
64
+ # example for use in code: client.picture_urls(:id => 'id_of_connection')
65
+ def picture_urls(options={})
66
+ picture_size = options.delete(:picture_size) || 'original'
67
+ path = "#{picture_urls_path(options)}::(#{picture_size})"
68
+ simple_query(path, options)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,86 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ module QueryHelpers
5
+ private
6
+
7
+ def group_path(options)
8
+ path = "/groups"
9
+ if id = options.delete(:id)
10
+ path += "/#{id}"
11
+ end
12
+ end
13
+
14
+ def simple_query(path, options={})
15
+ fields = options.delete(:fields) || LinkedIn.default_profile_fields
16
+
17
+ if options.delete(:public)
18
+ path +=":public"
19
+ elsif fields
20
+ path +=":(#{build_fields_params(fields)})"
21
+ end
22
+
23
+ headers = options.delete(:headers) || {}
24
+ params = to_query(options)
25
+ path += "#{path.include?("?") ? "&" : "?"}#{params}" if !params.empty?
26
+
27
+ Mash.from_json(get(path, headers))
28
+ end
29
+
30
+ def build_fields_params(fields)
31
+ if fields.is_a?(Hash) && !fields.empty?
32
+ fields.map {|index,value| "#{index}:(#{build_fields_params(value)})" }.join(',')
33
+ elsif fields.respond_to?(:each)
34
+ fields.map {|field| build_fields_params(field) }.join(',')
35
+ else
36
+ fields.to_s.gsub("_", "-")
37
+ end
38
+ end
39
+
40
+ def person_path(options)
41
+ path = "/people"
42
+ if id = options.delete(:id)
43
+ path += "/id=#{id}"
44
+ elsif url = options.delete(:url)
45
+ path += "/url=#{CGI.escape(url)}"
46
+ elsif email = options.delete(:email)
47
+ path += "::(#{email})"
48
+ else
49
+ path += "/~"
50
+ end
51
+ end
52
+
53
+ def company_path(options)
54
+ path = "/companies"
55
+
56
+ if domain = options.delete(:domain)
57
+ path += "?email-domain=#{CGI.escape(domain)}"
58
+ elsif id = options.delete(:id)
59
+ path += "/id=#{id}"
60
+ elsif url = options.delete(:url)
61
+ path += "/url=#{CGI.escape(url)}"
62
+ elsif name = options.delete(:name)
63
+ path += "/universal-name=#{CGI.escape(name)}"
64
+ elsif is_admin = options.delete(:is_admin)
65
+ path += "?is-company-admin=#{CGI.escape(is_admin)}"
66
+ else
67
+ path += "/~"
68
+ end
69
+ end
70
+
71
+ def picture_urls_path(options)
72
+ path = person_path(options)
73
+ path += "/picture-urls"
74
+ end
75
+
76
+ def jobs_path(options)
77
+ path = "/jobs"
78
+ if id = options.delete(:id)
79
+ path += "/id=#{id}"
80
+ else
81
+ path += "/~"
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,133 @@
1
+ module LinkedIn
2
+ module Api
3
+
4
+ # Share and Social Stream APIs
5
+ #
6
+ # @see http://developer.linkedin.com/documents/share-and-social-stream
7
+ # @see http://developer.linkedin.com/documents/share-api Share API
8
+ #
9
+ # The following API actions do not have corresponding methods in
10
+ # this module
11
+ #
12
+ # * GET Network Statistics
13
+ # * POST Post Network Update
14
+ #
15
+ # [(contribute here)](https://github.com/hexgnu/linkedin)
16
+ module ShareAndSocialStream
17
+
18
+ # Retrieve the authenticated users network updates
19
+ #
20
+ # Permissions: rw_nus
21
+ #
22
+ # @see http://developer.linkedin.com/documents/get-network-updates-and-statistics-api
23
+ # @see http://developer.linkedin.com/documents/network-update-types Network Update Types
24
+ #
25
+ # @macro person_path_options
26
+ # @option options [String] :scope
27
+ # @option options [String] :type
28
+ # @option options [String] :count
29
+ # @option options [String] :start
30
+ # @option options [String] :after
31
+ # @option options [String] :before
32
+ # @option options [String] :show-hidden-members
33
+ # @return [LinkedIn::Mash]
34
+ def network_updates(options={})
35
+ path = "#{person_path(options)}/network/updates"
36
+ simple_query(path, options)
37
+ end
38
+
39
+ # TODO refactor to use #network_updates
40
+ def shares(options={})
41
+ path = "#{person_path(options)}/network/updates"
42
+ simple_query(path, {:type => "SHAR", :scope => "self"}.merge(options))
43
+ end
44
+
45
+ # Retrieve all comments for a particular network update
46
+ #
47
+ # @note The first 5 comments are included in the response to #network_updates
48
+ #
49
+ # Permissions: rw_nus
50
+ #
51
+ # @see http://developer.linkedin.com/documents/commenting-reading-comments-and-likes-network-updates
52
+ #
53
+ # @param [String] update_key a update/update-key representing a
54
+ # particular network update
55
+ # @macro person_path_options
56
+ # @return [LinkedIn::Mash]
57
+ def share_comments(update_key, options={})
58
+ path = "#{person_path(options)}/network/updates/key=#{update_key}/update-comments"
59
+ simple_query(path, options)
60
+ end
61
+
62
+ # Retrieve all likes for a particular network update
63
+ #
64
+ # @note Some likes are included in the response to #network_updates
65
+ #
66
+ # Permissions: rw_nus
67
+ #
68
+ # @see http://developer.linkedin.com/documents/commenting-reading-comments-and-likes-network-updates
69
+ #
70
+ # @param [String] update_key a update/update-key representing a
71
+ # particular network update
72
+ # @macro person_path_options
73
+ # @return [LinkedIn::Mash]
74
+ def share_likes(update_key, options={})
75
+ path = "#{person_path(options)}/network/updates/key=#{update_key}/likes"
76
+ simple_query(path, options)
77
+ end
78
+
79
+ # Create a share for the authenticated user
80
+ #
81
+ # Permissions: rw_nus
82
+ #
83
+ # @see http://developer.linkedin.com/documents/share-api
84
+ #
85
+ # @macro share_input_fields
86
+ # @return [void]
87
+ def add_share(share)
88
+ path = "/people/~/shares"
89
+ defaults = {:visibility => {:code => "anyone"}}
90
+ post(path, MultiJson.dump(defaults.merge(share)), "Content-Type" => "application/json")
91
+ end
92
+
93
+ # Create a comment on an update from the authenticated user
94
+ #
95
+ # @see http://developer.linkedin.com/documents/commenting-reading-comments-and-likes-network-updates
96
+ #
97
+ # @param [String] update_key a update/update-key representing a
98
+ # particular network update
99
+ # @param [String] comment The text of the comment
100
+ # @return [void]
101
+ def update_comment(update_key, comment)
102
+ path = "/people/~/network/updates/key=#{update_key}/update-comments"
103
+ body = {'comment' => comment}
104
+ post(path, MultiJson.dump(body), "Content-Type" => "application/json")
105
+ end
106
+
107
+ # (Update) like an update as the authenticated user
108
+ #
109
+ # @see http://developer.linkedin.com/documents/commenting-reading-comments-and-likes-network-updates
110
+ #
111
+ # @param [String] update_key a update/update-key representing a
112
+ # particular network update
113
+ # @return [void]
114
+ def like_share(update_key)
115
+ path = "/people/~/network/updates/key=#{update_key}/is-liked"
116
+ put(path, 'true', "Content-Type" => "application/json")
117
+ end
118
+
119
+ # (Destroy) unlike an update the authenticated user previously
120
+ # liked
121
+ #
122
+ # @see http://developer.linkedin.com/documents/commenting-reading-comments-and-likes-network-updates
123
+ #
124
+ # @param [String] update_key a update/update-key representing a
125
+ # particular network update
126
+ # @return [void]
127
+ def unlike_share(update_key)
128
+ path = "/people/~/network/updates/key=#{update_key}/is-liked"
129
+ put(path, 'false', "Content-Type" => "application/json")
130
+ end
131
+ end
132
+ end
133
+ end