linkedin 0.4.6 → 0.4.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 (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