collegiatelink 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ module CollegiateLink
2
+
3
+ # The Client is what makes the requests to CollegiateLink.
4
+ class Client
5
+ ##
6
+ # Creates a CollegiateLink client.
7
+ #
8
+ # ==== Parameters:
9
+ # * +apikey+ - The CollegiateLink "apikey" for your institution. For example, at Case Western Reserve University we go to http://casewestern.collegiatelink.net, so our "apikey" is "casewestern"
10
+ # * +ip+ - The IP address that the +sharedkey+ is approved for.
11
+ # * +sharedkey+ - The shared key granted by CollegiateLink to your IP and institution.
12
+ #
13
+ def initialize(apikey, ip, sharedkey)
14
+ @params = {
15
+ apikey: apikey,
16
+ ip: ip,
17
+ }
18
+ @opts = {
19
+ sharedkey: sharedkey,
20
+ }
21
+ end
22
+
23
+ def self.proxy
24
+ @@proxy || Net::HTTP
25
+ end
26
+
27
+ def use_socks_proxy(host, port)
28
+ @@proxy = Net::HTTP.SOCKSProxy(host, port)
29
+ end
30
+
31
+ ##
32
+ # Return a complete list of CollegiateLink::Organization instances for your
33
+ # institution.
34
+ #
35
+ # ==== Required Parameters:
36
+ # None
37
+ #
38
+ # ==== Optional Parameters:
39
+ # See CollegiateLink::Request#initialize for a list of optional parameters
40
+ #
41
+ def organizations(params = {})
42
+ orgs = request('organization/list', params)
43
+ orgs.map{ |o| CollegiateLink::Organization.parse(o.to_s) }
44
+ end
45
+
46
+ ##
47
+ # Return a complete list of CollegiateLink::Event instances for your
48
+ # institution.
49
+ #
50
+ # ==== Required Parameters:
51
+ # * <tt>:startdate</tt> - Time instance or the Unix integral timestamp for the beginning of results.
52
+ # * <tt>:enddate</tt> - Time instance or the Unix integral timestamp for the end of results.
53
+ #
54
+ # ==== Optional Parameters:
55
+ # See CollegiateLink::Request#initialize for a list of additional parameters
56
+ # that requests can use.
57
+ def events(params = {})
58
+ # Default to showing events in the past 7 days
59
+ seven_days = 7 * 24 * 60 * 60
60
+ params[:startdate] ||= (Time.now.to_i - seven_days)
61
+ params[:enddate] ||= (Time.now.to_i)
62
+
63
+ # Convert to milliseconds...
64
+ params[:startdate] = params[:startdate].to_i * 1000
65
+ params[:enddate] = params[:enddate].to_i * 1000
66
+
67
+ events = request('event/list', params)
68
+ events.map{ |o| CollegiateLink::Event.parse(o.to_s) }
69
+ end
70
+
71
+ private
72
+
73
+ def request(action, params = {})
74
+ cl_request = CollegiateLink::Request.new(action, params.merge(@params), @opts)
75
+ cl_resp = cl_request.perform
76
+
77
+ all_items = cl_resp.items
78
+
79
+ while cl_resp.has_next_page?
80
+ cl_resp = cl_request.request_for_next_page.perform
81
+ all_items += cl_resp.items
82
+ end
83
+
84
+ all_items
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,103 @@
1
+ module CollegiateLink
2
+ ##
3
+ # Address object returned by CollegiateLink as part of an Organization or
4
+ # Event record.
5
+ #
6
+ # ==== Properties:
7
+ # * <tt>:city </tt> - String
8
+ # * <tt>:country </tt> - String
9
+ # * <tt>:postalcode</tt> - String
10
+ # * <tt>:state </tt> - String
11
+ # * <tt>:street1 </tt> - String
12
+ # * <tt>:street2 </tt> - String
13
+ # * <tt>:type </tt> - Integer
14
+ class Address
15
+ include HappyMapper
16
+
17
+ element :city, String
18
+ element :country, String
19
+ element :postalcode, String
20
+ element :state, String
21
+ element :street1, String
22
+ element :street2, String
23
+ element :type, Integer
24
+ end
25
+
26
+ ##
27
+ # Category object returned by CollegiateLink as part of an Organization record
28
+ # See: # http://support.collegiatelink.net/entries/332558-web-services-developer-documentation#orgList
29
+ #
30
+ # ==== Properties:
31
+ # * <tt>:id </tt> - Integer
32
+ # * <tt>:ishidden</tt> - String
33
+ # * <tt>:name </tt> - String
34
+ class Category
35
+ include HappyMapper
36
+
37
+ element :id, Integer
38
+ element :ishidden, String
39
+ element :name, String
40
+ end
41
+
42
+ ##
43
+ # An Organization record returned by CollegiateLink
44
+ # See: http://support.collegiatelink.net/entries/332558-web-services-developer-documentation#orgList
45
+ #
46
+ # ==== Properties:
47
+ # * <tt>:id </tt> - Integer
48
+ # * <tt>:parentId</tt> - Integer
49
+ # * <tt>:name </tt> - String
50
+ # * <tt>:description </tt> - String
51
+ # * <tt>:shortName </tt> - String
52
+ # * <tt>:siteUrl </tt> - String
53
+ # * <tt>:status </tt> - String
54
+ # * <tt>:type </tt> - String
55
+ # * <tt>:addresses </tt> - Array of CollegiateLink::Address
56
+ # * <tt>:categories </tt> - Array of CollegiateLink::Category
57
+ class Organization
58
+ include HappyMapper
59
+
60
+ element :id, Integer
61
+ element :parentId, Integer
62
+ element :name, String
63
+ element :description, String
64
+ element :shortName, String
65
+ element :siteUrl, String
66
+ element :status, String
67
+ element :type, String
68
+ has_many :addresses, Address
69
+ has_many :categories, Category
70
+ end
71
+
72
+ ##
73
+ # An Event record returned by CollegiateLink
74
+ # See: http://support.collegiatelink.net/entries/332558-web-services-developer-documentation#eventList
75
+ #
76
+ # ==== Properties:
77
+ # * <tt>:id </tt> - Integer
78
+ # * <tt>:name </tt> - String
79
+ # * <tt>:description</tt> - String
80
+ # * <tt>:startDate </tt> - Integer
81
+ # * <tt>:endDate </tt> - Integer
82
+ # * <tt>:location </tt> - String
83
+ # * <tt>:status </tt> - String
84
+ # * <tt>:urlLarge </tt> - String
85
+ # * <tt>:urlSmall </tt> - String
86
+ # * <tt>:organization</tt> - The hosting Organization
87
+ #
88
+ class Event
89
+ include HappyMapper
90
+
91
+ element :id, Integer
92
+ element :name, String
93
+ element :description, String
94
+ element :startDate, Integer
95
+ element :endDate, Integer
96
+ element :location, String
97
+ element :status, String
98
+ element :urlLarge, String
99
+ element :urlSmall, String
100
+
101
+ has_one :organization, Organization
102
+ end
103
+ end
@@ -0,0 +1,125 @@
1
+ module CollegiateLink
2
+ ##
3
+ # Represents a single HTTP request to the CollegiateLink API.
4
+ #
5
+ class Request
6
+ ##
7
+ # Create a new Request instance. See +CollegiateLink::ACTIONS+ for a list of
8
+ # eligible actions.
9
+ #
10
+ # ==== Parameters:
11
+ # All parameters are provided in the URL of the request to CollegiateLink.
12
+ #
13
+ # * <tt>:page</tt> - The desired page number of results. (default = 1)
14
+ # * <tt>:pagesize</tt> - The desired number of records to return (default = 100)
15
+ # * <tt>:modelformatting</tt> - Either "normal" or "humanreadable". (default = "normal")
16
+ #
17
+ # ==== Options:
18
+ # Options are ways to pass in additional parameters about the request. The
19
+ # following options are supported.
20
+ #
21
+ # * <tt>:sharedkey</tt> - (Required) The shared key which is used, but not included in the URL of requests
22
+ # * <tt>:debug</tt> - Print debug information as the request happens.
23
+ #
24
+ def initialize(action, params = {}, opts = {})
25
+ raise UnknownAction unless ACTIONS.include?(action)
26
+ raise AuthenticationException unless opts.include?(:sharedkey)
27
+
28
+ @action = action
29
+ @params = params
30
+ @opts = opts
31
+
32
+ # URL Query String Parameters
33
+ @params[:page] ||= 1
34
+ @params[:pagesize] ||= 100
35
+ @params[:modelformatting] ||= 'normal'
36
+
37
+ # Default values for optional parameters
38
+ @opts[:url_base] ||= 'https://%s.collegiatelink.net/ws/' % @params[:apikey]
39
+ end
40
+
41
+ ##
42
+ # Execute the request by sending the HTTP request.
43
+ #
44
+ def perform
45
+ # First, add the time-sensitive bits...
46
+ request_params = @params.merge({
47
+ time: Time.now.to_i * 1000,
48
+ random: Guid.new
49
+ })
50
+ request_params[:hash] = hash(request_params.merge(sharedkey: @opts[:sharedkey]))
51
+
52
+ # Then, compute the URL...
53
+ url = URI([
54
+ @opts[:url_base],
55
+ @action,
56
+ '?',
57
+ URI.encode_www_form(request_params),
58
+ ].join)
59
+
60
+ puts "requesting: \n#{url}" if @opts[:debug]
61
+
62
+ # Make the Request!
63
+ res = CollegiateLink::Client.proxy.new(url.host, url.port)
64
+ res.use_ssl = true
65
+ res.verify_mode = OpenSSL::SSL::VERIFY_NONE
66
+
67
+ resp = res.start { |h|
68
+ h.request_get(url.to_s);
69
+ }
70
+
71
+ case resp
72
+ when Net::HTTPSuccess
73
+ return parse_response(resp.body)
74
+ when Net::HTTPError
75
+ raise NetworkException
76
+ else
77
+ raise UnknownException
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Increment the page number and return a request instance that would receive
83
+ # the next bunch of pages.
84
+ #
85
+ def request_for_next_page
86
+ Request.new(@action, @params.merge(page: @params[:page] + 1), @opts)
87
+ end
88
+
89
+ private
90
+
91
+ def parse_response(body)
92
+ d = Nokogiri::XML::Document.parse(body)
93
+
94
+ # Parse exceptions
95
+ if d.xpath("//results/error").length > 0
96
+ type = d.xpath('//results/error/type').inner_html
97
+ message = d.xpath('//results/error/message').inner_html
98
+ case type
99
+ when 'AUTHENTICATION_ERROR'
100
+ raise AuthenticationException, message
101
+ when 'VALIDATION_ERROR'
102
+ raise ValidationException, message
103
+ when 'UNKNOWN_SERVICE'
104
+ raise UnknownAction, message
105
+ when 'GENERAL_ERROR'
106
+ raise UnknownException, message
107
+ else
108
+ raise UnknownException, message
109
+ end
110
+ end
111
+
112
+ Response.new(d)
113
+ end
114
+
115
+ def hash(params = {})
116
+ Digest::MD5.hexdigest [
117
+ params[:apikey],
118
+ params[:ip],
119
+ params[:time].to_i,
120
+ params[:random],
121
+ params[:sharedkey],
122
+ ].join
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,30 @@
1
+ module CollegiateLink
2
+ ##
3
+ # Container for the XML gunk returned from CollegiateLink
4
+ #
5
+ class Response
6
+ # Create the response.
7
+ #
8
+ # ==== Parameters:
9
+ # * +document+ - The Nokogiri document of the returned XML
10
+ def initialize(document)
11
+ raise UnknownException unless document.xpath('//results/page')
12
+
13
+ @document = document
14
+ @page_size = document.xpath('//results/page/pageSize').inner_html.to_i
15
+ @page_number = document.xpath('//results/page/pageNumber').inner_html.to_i
16
+ @total_items = document.xpath('//results/page/totalItems').inner_html.to_i
17
+ @total_pages = document.xpath('//results/page/totalPages').inner_html.to_i
18
+ end
19
+
20
+ # Extract the items from the response. Returns a Nokogiri NodeSet.
21
+ def items
22
+ @document.xpath('//results/page/items/*')
23
+ end
24
+
25
+ # Utility method to determine if the request has another page to retrieve.
26
+ def has_next_page?
27
+ @page_number < @total_pages
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ require 'digest'
2
+ require 'net/https'
3
+ require 'net/ssh'
4
+ require 'guid'
5
+ require 'nokogiri'
6
+ require 'happymapper'
7
+ require 'socksify/http'
8
+
9
+ require 'collegiatelink/response'
10
+ require 'collegiatelink/request'
11
+ require 'collegiatelink/client'
12
+ require 'collegiatelink/organization'
13
+
14
+ ##
15
+ # This gem provides a CollegiateLink API client in Ruby. It's still under
16
+ # development, so let me know if you plan to use it. (tomdooner@gmail.com)
17
+ #
18
+ module CollegiateLink
19
+ # Currently-supported CollegiateLink action request types
20
+ ACTIONS = [
21
+ 'organization/list',
22
+ 'organization/roster',
23
+ #'user/memberships',
24
+ #'user/position',
25
+ 'event/list',
26
+ ]
27
+
28
+ # Raised when performing a CollegiateLink::Request for an action that is not
29
+ # supported by the gem (as defined by CollegiateLink::ACTIONS).
30
+ class UnknownAction < Exception; end
31
+
32
+ # Raised when something unexpected goes wrong.
33
+ class UnknownException < Exception; end
34
+
35
+ # Raised when the CollegiateLink::Request HTTP request fails.
36
+ class NetworkException < Exception; end
37
+
38
+ # Raised when CollegiateLink returns that the combination of IP and SSL fails.
39
+ class AuthenticationException < Exception; end
40
+
41
+ # Raised for the CollegiateLink VALIDATION_ERROR case.
42
+ class ValidationException < Exception; end
43
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: collegiatelink
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tom Dooner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guid
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: happymapper
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: socksify
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: net-ssh
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description:
111
+ email: ted27@case.edu
112
+ executables: []
113
+ extensions: []
114
+ extra_rdoc_files: []
115
+ files:
116
+ - lib/collegiatelink.rb
117
+ - lib/collegiatelink/request.rb
118
+ - lib/collegiatelink/response.rb
119
+ - lib/collegiatelink/client.rb
120
+ - lib/collegiatelink/organization.rb
121
+ homepage:
122
+ licenses: []
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 1.8.24
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: CollegiateLink Client Gem
145
+ test_files: []