qoobaa-opensocial 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "net/http"
16
+ require "uri"
17
+
18
+ # Use json/pure if you opt-out of including the validation code in
19
+ # opensocial/auth. This gem adds standard to_json behavior for the
20
+ # request classes, instead of using ActiveSupport.
21
+ require "rubygems"
22
+
23
+ module OpenSocial #:nodoc:
24
+
25
+ # Provides base functionality for the OpenSocial child classes.
26
+ #
27
+
28
+ class Base
29
+
30
+ # Creates an attr_accessor for the specified variable name.
31
+ def add_attr(name)
32
+ self.class.class_eval "attr_accessor :#{name}"
33
+ end
34
+ end
35
+
36
+ # Wraps the functionality of an OpenSocial collection as defined by the
37
+ # specification. In practical uses, a Collection serves as a Hash (usually
38
+ # index by ID) with the added benefit of being convertable to an Array, when
39
+ # it's necessary to iterate over all of the values.
40
+ #
41
+
42
+ class Collection < Hash
43
+
44
+ # Converts the Collection to an Array by returning each of the values from
45
+ # key/value pairs.
46
+ def to_array
47
+ values
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,128 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenSocial #:nodoc:
16
+
17
+ # Describes a connection to an OpenSocial container, including the ability to
18
+ # declare an authorization mechanism and appropriate credentials.
19
+ #
20
+
21
+ class Connection
22
+ ORKUT = { :endpoint => "http://sandbox.orkut.com/social",
23
+ :rest => "rest/",
24
+ :rpc => "rpc/" }
25
+ IGOOGLE = { :endpoint => "http://gmodules.com/api",
26
+ :rest => "",
27
+ :rpc => "rpc" }
28
+ MYSPACE = { :endpoint => "http://api.myspace.com/v2",
29
+ :rest => "",
30
+ :rpc => "",
31
+ :base_uri => "http://api.myspace.com",
32
+ :request_token_path => "/request_token",
33
+ :authorize_path => "/authorize",
34
+ :access_token_path => "/access_token",
35
+ :http_method => :get }
36
+
37
+ AUTH_HMAC = 0
38
+ AUTH_ST = 1
39
+
40
+ DEFAULT_OPTIONS = { :container => ORKUT,
41
+ :st => "",
42
+ :consumer_key => "",
43
+ :consumer_secret => "",
44
+ :consumer_token => OAuth::Token.new("", ""),
45
+ :xoauth_requestor_id => "",
46
+ :auth => AUTH_HMAC }
47
+
48
+ # Defines the container that will be used in requests.
49
+ attr_accessor :container
50
+
51
+ # Defines the security token, for when OAuth is not in use.
52
+ attr_accessor :st
53
+
54
+ # Defines the consumer key for OAuth.
55
+ attr_accessor :consumer_key
56
+
57
+ # Defines the consumer secret for OAuth.
58
+ attr_accessor :consumer_secret
59
+
60
+ # Defines the consumer token for OAuth.
61
+ attr_accessor :consumer_token
62
+
63
+ # Defines the ID of the requestor (required by some implementations when
64
+ # using OAuth).
65
+ attr_accessor :xoauth_requestor_id
66
+
67
+ # Defines the authentication scheme: HMAC or security token.
68
+ attr_accessor :auth
69
+
70
+ # Initializes the Connection using the supplied options hash, or the
71
+ # defaults. Verifies that the supplied authentication type has proper
72
+ # (ie. non-blank) credentials, and that the authentication type is known.
73
+ def initialize(options = {})
74
+ options = DEFAULT_OPTIONS.merge(options)
75
+ options.each do |key, value|
76
+ self.send("#{key}=", value)
77
+ end
78
+
79
+ if @auth == AUTH_HMAC && !has_valid_hmac_double?
80
+ raise ArgumentError.new("Connection authentication is set to " +
81
+ "HMAC-SHA1, but a valid consumer_key and" +
82
+ "secret pair was not supplied.")
83
+ elsif @auth == AUTH_ST && @st.empty?
84
+ raise ArgumentError.new("Connection authentication is set to " +
85
+ "security token, but a security token was " +
86
+ "not supplied.")
87
+ elsif ![AUTH_HMAC, AUTH_ST].include?(@auth)
88
+ raise ArgumentError.new("Connection authentication is set to an " +
89
+ "unknown value.")
90
+ end
91
+ end
92
+
93
+ # Constructs a URI to the OpenSocial endpoint given a service, guid,
94
+ # selector, and pid.
95
+ def service_uri(service, guid, selector, pid, extra_fields = {})
96
+ uri = [@container[:endpoint], service, guid, selector, pid].compact.
97
+ join("/")
98
+
99
+ if @auth == AUTH_HMAC && !xoauth_requestor_id.empty?
100
+ uri << "?xoauth_requestor_id=" + @xoauth_requestor_id
101
+ elsif @auth == AUTH_ST
102
+ uri << "?st=" + self.st
103
+ end
104
+
105
+ extra_fields.each do |name, value|
106
+ uri << "&#{name}=#{value}"
107
+ end
108
+
109
+ URI.parse(uri)
110
+ end
111
+
112
+ # Signs a request using OAuth.
113
+ def sign!(http, req)
114
+ if @auth == AUTH_HMAC
115
+ consumer = OAuth::Consumer.new(@consumer_key, @consumer_secret)
116
+ req.oauth!(http, consumer, @consumer_token, :scheme => "query_string")
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ # Verifies that the consumer key, consumer secret and requestor id are all
123
+ # non-blank.
124
+ def has_valid_hmac_double?
125
+ return (!@consumer_key.empty? && !@consumer_secret.empty?)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,80 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenSocial #:nodoc:
16
+
17
+ # Acts as a wrapper for an OpenSocial group.
18
+ #
19
+ # The Group class takes input JSON as an initialization parameter, and
20
+ # iterates through each of the key/value pairs of that JSON. For each key
21
+ # that is found, an attr_accessor is constructed, allowing direct access
22
+ # to the value. Each value is stored in the attr_accessor, either as a
23
+ # String, Fixnum, Hash, or Array.
24
+ #
25
+
26
+ class Group < Base
27
+
28
+ # Initializes the Group based on the provided json fragment. If no JSON
29
+ # is provided, an empty object (with no attributes) is created.
30
+ def initialize(json)
31
+ if json
32
+ json.each do |key, value|
33
+ proper_key = key.snake_case
34
+ begin
35
+ self.send("#{proper_key}=", value)
36
+ rescue NoMethodError
37
+ add_attr(proper_key)
38
+ self.send("#{proper_key}=", value)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # Provides the ability to request a Collection of groups for a given
46
+ # user.
47
+ #
48
+ # The FetchGroupsRequest wraps a simple request to an OpenSocial
49
+ # endpoint for a collection of groups. As parameters, it accepts
50
+ # a user ID. This request may be used, standalone, by calling send, or
51
+ # bundled into an RpcRequest.
52
+ #
53
+
54
+ class FetchGroupsRequest < Request
55
+ # Defines the service fragment for use in constructing the request URL or
56
+ # JSON
57
+ SERVICE = "groups"
58
+
59
+ # Initializes a request to fetch groups for the specified user, or the
60
+ # default (@me). A valid Connection is not necessary if the request is to
61
+ # be used as part of an RpcRequest.
62
+ def initialize(connection = nil, guid = "@me")
63
+ super
64
+ end
65
+
66
+ # Sends the request, passing in the appropriate SERVICE and specified
67
+ # instance variables.
68
+ def send
69
+ json = send_request(SERVICE, @guid)
70
+
71
+ groups = Collection.new
72
+ for entry in json["entry"]
73
+ group = Group.new(entry)
74
+ groups[group.id] = group
75
+ end
76
+
77
+ return groups
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,197 @@
1
+ # Copyright (c) 2008 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Extends the OpenSocial module, providing a wrapper for OpenSocial people.
16
+ #
17
+ # Person: Acts as a wrapper for an OpenSocial person.
18
+ # FetchPersonRequest: Provides the ability to request a single person.
19
+ # FetchPeopleRequest: Provides the ability to request a collection of people
20
+ # by describing their relationship to a single person.
21
+ #
22
+
23
+ module OpenSocial #:nodoc:
24
+
25
+ # Acts as a wrapper for an OpenSocial person.
26
+ #
27
+ # The Person class takes input JSON as an initialization parameter, and
28
+ # iterates through each of the key/value pairs of that JSON. For each key
29
+ # that is found, an attr_accessor is constructed, allowing direct access
30
+ # to the value. Each value is stored in the attr_accessor, either as a
31
+ # String, Fixnum, Hash, or Array.
32
+ #
33
+
34
+ class Person < Base
35
+
36
+ # Initializes the Person based on the provided json fragment. If no JSON
37
+ # is provided, an empty object (with no attributes) is created.
38
+ def initialize(json)
39
+ if json
40
+ json.each do |key, value|
41
+ proper_key = key.snake_case
42
+ begin
43
+ self.send("#{proper_key}=", value)
44
+ rescue NoMethodError
45
+ add_attr(proper_key)
46
+ self.send("#{proper_key}=", value)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Returns the complete name of the Person, to the best ability, given
53
+ # available fields.
54
+ def long_name
55
+ if @name && @name["givenName"] && @name["familyName"]
56
+ return @name["givenName"] + " " + @name["familyName"]
57
+ elsif @nickname
58
+ return @nickname
59
+ else
60
+ return ""
61
+ end
62
+ end
63
+
64
+ # Returns the first name or nickname of the Person, to the best ability,
65
+ # given available fields.
66
+ def short_name
67
+ if @name && @name["givenName"]
68
+ return @name["givenName"]
69
+ elsif @nickname
70
+ return @nickname
71
+ else
72
+ return ""
73
+ end
74
+ end
75
+ end
76
+
77
+ # Provides the ability to request a single Person.
78
+ #
79
+ # The FetchPeopleRequests wraps a simple request to an OpenSocial
80
+ # endpoint for a single person. As parameters, it accepts a user ID and
81
+ # selector and optionally an ID of a particular person, in order to display
82
+ # the user ID"s view of that person. This request may be used, standalone,
83
+ # by calling send, or bundled into an RpcRequest.
84
+ #
85
+
86
+ class FetchPersonRequest < Request
87
+ # Defines the service fragment for use in constructing the request URL or
88
+ # JSON
89
+ SERVICE = "people"
90
+ DEFAULT_FIELDS = [:id, :dateOfBirth, :name, :emails, :gender, :state, :postalCode, :ethnicity, :relationshipStatus, :thumbnailUrl, :displayName]
91
+
92
+ # Initializes a request to the specified user, or the default (@me, @self).
93
+ # A valid Connection is not necessary if the request is to be used as part
94
+ # of an RpcRequest.
95
+ def initialize(connection = nil, guid = "@me", selector = "@self")
96
+ super
97
+ end
98
+
99
+ # Sends the request, passing in the appropriate SERVICE and specified
100
+ # instance variables.
101
+ def send
102
+ json = send_request(SERVICE, @guid, @selector, nil, false, :fields => DEFAULT_FIELDS.join(","))
103
+
104
+ return parse_response(json["entry"])
105
+ end
106
+
107
+ # Selects the appropriate fragment from the JSON response in order to
108
+ # create a native object.
109
+ def parse_rpc_response(response)
110
+ return parse_response(response["data"])
111
+ end
112
+
113
+ # Converts the request into a JSON fragment that can be used as part of a
114
+ # larger RpcRequest.
115
+ def to_json(*a)
116
+ value = {
117
+ "method" => SERVICE + GET,
118
+ "params" => {
119
+ "userId" => ["#{@guid}"],
120
+ "groupId" => "#{@selector}"
121
+ },
122
+ "id" => @key
123
+ }.to_json(*a)
124
+ end
125
+
126
+ private
127
+
128
+ # Converts the JSON response into a person.
129
+ def parse_response(response)
130
+ return Person.new(response)
131
+ end
132
+ end
133
+
134
+ # Provides the ability to request a Collection of people by describing their
135
+ # relationship to a single person.
136
+ #
137
+ # The FetchPeopleRequests wraps a simple request to an OpenSocial
138
+ # endpoint for a Collection of people. As parameters, it accepts
139
+ # a user ID and selector. This request may be used, standalone, by calling
140
+ # send, or bundled into an RpcRequest.
141
+ #
142
+
143
+ class FetchPeopleRequest < Request
144
+ # Defines the service fragment for use in constructing the request URL or
145
+ # JSON
146
+ SERVICE = "people"
147
+
148
+ # Initializes a request to the specified user's group, or the default (@me,
149
+ # @friends). A valid Connection is not necessary if the request is to be
150
+ # used as part of an RpcRequest.
151
+ def initialize(connection = nil, guid = "@me", selector = "@friends", extra_fields = {})
152
+ super
153
+ @extra_fields = extra_fields
154
+ end
155
+
156
+ # Sends the request, passing in the appropriate SERVICE and specified
157
+ # instance variables.
158
+ def send
159
+ @extra_fields[:fields] ||= FetchPersonRequest::DEFAULT_FIELDS.join(",")
160
+ json = send_request(SERVICE, @guid, @selector, nil, false, @extra_fields)
161
+
162
+ return parse_response(json["entry"])
163
+ end
164
+
165
+ # Selects the appropriate fragment from the JSON response in order to
166
+ # create a native object.
167
+ def parse_rpc_response(response)
168
+ return parse_response(response["data"]["list"])
169
+ end
170
+
171
+ # Converts the request into a JSON fragment that can be used as part of a
172
+ # larger RPC request.
173
+ def to_json(*a)
174
+ value = {
175
+ "method" => SERVICE + GET,
176
+ "params" => {
177
+ "userId" => ["#{@guid}"],
178
+ "groupId" => "#{@selector}"
179
+ },
180
+ "id" => @key
181
+ }.to_json(*a)
182
+ end
183
+
184
+ private
185
+
186
+ # Converts the JSON response into a Collection of people, indexed by id.
187
+ def parse_response(response)
188
+ people = Collection.new
189
+ for entry in response
190
+ person = Person.new(entry)
191
+ people[person.id] = person
192
+ end
193
+
194
+ return people
195
+ end
196
+ end
197
+ end