rplatform 0.0.1
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.
- data/CHANGELOG +0 -0
- data/HISTORY.txt +3 -0
- data/README.txt +41 -0
- data/Rakefile +21 -0
- data/lib/facebook_desktop_session.rb +124 -0
- data/lib/facebook_session.rb +397 -0
- data/lib/facebook_web_session.rb +124 -0
- data/lib/facepricot.rb +135 -0
- data/lib/rfacebook.rb +5 -0
- data/test/facebook_desktop_session_test.rb +54 -0
- data/test/facebook_session_test_methods.rb +106 -0
- data/test/facebook_web_session_test.rb +48 -0
- data/test/test_helper.rb +218 -0
- metadata +75 -0
data/CHANGELOG
ADDED
File without changes
|
data/HISTORY.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
============================== DOCUMENTATION ==============================
|
2
|
+
This project was continued on from rfacebook. For now, consult the rfacebook homepage for usage info.
|
3
|
+
|
4
|
+
http://rfacebook.rubyforge.org
|
5
|
+
|
6
|
+
|
7
|
+
============================== LICENSE ==============================
|
8
|
+
|
9
|
+
Copyright (c) 2007, Curtis Edmond (www.okwithfailure.com)
|
10
|
+
All rights reserved.
|
11
|
+
|
12
|
+
Redistribution and use in source and binary forms, with or without modification,
|
13
|
+
are permitted provided that the following conditions are met:
|
14
|
+
|
15
|
+
Redistributions of source code must retain the above copyright notice,
|
16
|
+
this list of conditions and the following disclaimer.
|
17
|
+
|
18
|
+
Redistributions in binary form must reproduce the above copyright notice,
|
19
|
+
this list of conditions and the following disclaimer in the documentation
|
20
|
+
and/or other materials provided with the distribution.
|
21
|
+
|
22
|
+
Neither the name of the original author nor the names of contributors
|
23
|
+
may be used to endorse or promote products derived from this software
|
24
|
+
without specific prior written permission.
|
25
|
+
|
26
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
27
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
28
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
29
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
30
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
31
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
32
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
33
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
34
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
35
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
36
|
+
|
37
|
+
|
38
|
+
============================== RELEASE NOTES ==============================
|
39
|
+
|
40
|
+
0.1.0 - initial import of rfacebook with support for bebo (thnx to Michael Kovacs from http://javathehutt.blogspot.com/2008/01/rails-realities-part-27-facebook-and.html and
|
41
|
+
Matt Pizzimenti, blog at http://www.livelearncode.com/, for rfacebook)
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
4
|
+
require 'rfacebook'
|
5
|
+
|
6
|
+
Hoe.new('rplatform', RPlatform::VERSION) do |p|
|
7
|
+
p.name = "rplatform"
|
8
|
+
p.author = "Curtis Edmond"
|
9
|
+
p.description = "ruby interface for Facebook's Platform API."
|
10
|
+
p.email = 'curtis.edmond@gmail.com'
|
11
|
+
p.summary = "ruby interface for Facebook's Platform API.."
|
12
|
+
p.url = "http://rplatform.rubyforge.org/"
|
13
|
+
p.clean_globs = ['test/actual'] # Remove this directory on "rake clean"
|
14
|
+
p.remote_rdoc_dir = '' # Release to root
|
15
|
+
p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
|
16
|
+
# * extra_deps - An array of rubygem dependencies.
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
desc "Release and publish documentation"
|
21
|
+
task :repubdoc => [:release, :publish_docs]
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# Copyright (c) 2007, Matt Pizzimenti (www.livelearncode.com)
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# Neither the name of the original author nor the names of contributors
|
15
|
+
# may be used to endorse or promote products derived from this software
|
16
|
+
# without specific prior written permission.
|
17
|
+
#
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
21
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
22
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
#
|
29
|
+
|
30
|
+
require "facebook_session"
|
31
|
+
|
32
|
+
module RFacebook
|
33
|
+
|
34
|
+
class FacebookDesktopSession < FacebookSession
|
35
|
+
|
36
|
+
# you should need this for infinite desktop sessions
|
37
|
+
attr_reader :session_secret
|
38
|
+
|
39
|
+
# Constructs a FacebookDesktopSession, calling the API to grab an auth_token.
|
40
|
+
#
|
41
|
+
# api_key:: your API key
|
42
|
+
# api_secret:: your API secret
|
43
|
+
# quiet:: boolean, set to true if you don't want errors to be thrown (defaults to false)
|
44
|
+
def initialize(api_key, api_secret, quiet = false)
|
45
|
+
super(api_key, api_secret, quiet)
|
46
|
+
result = remote_call("auth.createToken", {})
|
47
|
+
@desktop_auth_token = result.at("auth_createToken_response")
|
48
|
+
@desktop_auth_token = @desktop_auth_token.nil? ? nil : @desktop_auth_token.inner_html.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gets the authentication URL
|
52
|
+
#
|
53
|
+
# options.next:: the page to redirect to after login
|
54
|
+
# options.popup:: boolean, whether or not to use the popup style (defaults to true)
|
55
|
+
# options.skipcookie:: boolean, whether to force new Facebook login (defaults to false)
|
56
|
+
# options.hidecheckbox:: boolean, whether to show the "infinite session" option checkbox (defaults to false)
|
57
|
+
def get_login_url(options={})
|
58
|
+
# options
|
59
|
+
path_next = options[:next] ||= nil
|
60
|
+
popup = (options[:popup] == nil) ? true : false
|
61
|
+
skipcookie = (options[:skipcookie] == nil) ? false : true
|
62
|
+
hidecheckbox = (options[:hidecheckbox] == nil) ? false : true
|
63
|
+
|
64
|
+
# get some extra portions of the URL
|
65
|
+
optionalNext = (path_next == nil) ? "" : "&next=#{CGI.escape(path_next.to_s)}"
|
66
|
+
optionalPopup = (popup == true) ? "&popup=true" : ""
|
67
|
+
optionalSkipCookie = (skipcookie == true) ? "&skipcookie=true" : ""
|
68
|
+
optionalHideCheckbox = (hidecheckbox == true) ? "&hide_checkbox=true" : ""
|
69
|
+
|
70
|
+
# build and return URL
|
71
|
+
return "http://#{get_network_param(:www_host)}#{get_network_param(:www_path_login)}?v=1.0&api_key=#{@api_key}&auth_token=#{@desktop_auth_token}#{optionalPopup}#{optionalNext}#{optionalSkipCookie}#{optionalHideCheckbox}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Activates the session and makes it ready for usage. Call this method only after
|
75
|
+
# the user has logged in via the login URL.
|
76
|
+
def activate
|
77
|
+
result = remote_call("auth.getSession", {:auth_token => @desktop_auth_token}, true)
|
78
|
+
if result != nil
|
79
|
+
@session_user_id = result.at("uid").inner_html
|
80
|
+
@session_key = result.at("session_key").inner_html
|
81
|
+
@session_secret = result.at("secret").inner_html
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Activate using the session key and secret directly (for example, if you have an infinite session)
|
86
|
+
#
|
87
|
+
# key:: the session key to use
|
88
|
+
# secret:: the session secret to use
|
89
|
+
def activate_with_previous_session(key, secret)
|
90
|
+
# set the session key and secret
|
91
|
+
@session_key = key
|
92
|
+
@session_secret = secret
|
93
|
+
|
94
|
+
# determine the current user's id
|
95
|
+
result = remote_call("users.getLoggedInUser")
|
96
|
+
@session_user_id = result.at("users_getLoggedInUser_response").inner_html
|
97
|
+
end
|
98
|
+
|
99
|
+
# returns true if this session is completely ready to be used and make API calls
|
100
|
+
def ready?
|
101
|
+
return (@session_key != nil and @session_secret != nil and !expired?)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Used for signing a set of parameters in the way that Facebook
|
105
|
+
# specifies: <http://developers.facebook.com/documentation.php?v=1.0&doc=auth>
|
106
|
+
#
|
107
|
+
# params:: a Hash containing the parameters to sign
|
108
|
+
def signature(params)
|
109
|
+
# choose the proper secret
|
110
|
+
signatureSecret = nil
|
111
|
+
unless (params[:method] == "facebook.auth.getSession" or params[:method] == "facebook.auth.createToken")
|
112
|
+
signatureSecret = @session_secret
|
113
|
+
else
|
114
|
+
signatureSecret = @api_secret
|
115
|
+
end
|
116
|
+
|
117
|
+
# sign the parameters with that secret
|
118
|
+
return signature_helper(params, signatureSecret)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
@@ -0,0 +1,397 @@
|
|
1
|
+
# Copyright (c) 2007, Matt Pizzimenti (www.livelearncode.com)
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# Neither the name of the original author nor the names of contributors
|
15
|
+
# may be used to endorse or promote products derived from this software
|
16
|
+
# without specific prior written permission.
|
17
|
+
#
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
21
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
22
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
#
|
29
|
+
|
30
|
+
require "digest/md5"
|
31
|
+
require "net/https"
|
32
|
+
require "cgi"
|
33
|
+
require "facepricot"
|
34
|
+
|
35
|
+
module RFacebook
|
36
|
+
|
37
|
+
# TODO: better handling of session expiration
|
38
|
+
|
39
|
+
|
40
|
+
# API_VERSION = "1.0"
|
41
|
+
#
|
42
|
+
# API_HOST = "api.facebook.com"
|
43
|
+
# API_PATH_REST = "/restserver.php"
|
44
|
+
#
|
45
|
+
# WWW_HOST = "www.facebook.com"
|
46
|
+
# WWW_PATH_LOGIN = "/login.php"
|
47
|
+
# WWW_PATH_ADD = "/add.php"
|
48
|
+
# WWW_PATH_INSTALL = "/install.php"
|
49
|
+
|
50
|
+
HOST_CONSTANTS = { 'facebook' => { :api_version => "1.0",
|
51
|
+
:api_host => "api.facebook.com",
|
52
|
+
:api_path_rest => "/restserver.php",
|
53
|
+
:www_host => "www.facebook.com",
|
54
|
+
:www_path_login => "/login.php",
|
55
|
+
:www_path_add => "/add.php",
|
56
|
+
:www_path_install => "/install.php"},
|
57
|
+
'bebo' => { :api_version => "1.0",
|
58
|
+
:api_host => "apps.bebo.com",
|
59
|
+
:api_path_rest => "/restserver.php",
|
60
|
+
:www_host => "bebo.com",
|
61
|
+
:www_path_login => "/SignIn.jsp",
|
62
|
+
:www_path_add => "/add.php",
|
63
|
+
:www_path_install => "/c/apps/add"}}
|
64
|
+
|
65
|
+
|
66
|
+
class FacebookSession
|
67
|
+
|
68
|
+
################################################################################################
|
69
|
+
################################################################################################
|
70
|
+
# :section: Error classes
|
71
|
+
################################################################################################
|
72
|
+
|
73
|
+
# TODO: better exception classes in v1.0?
|
74
|
+
class RemoteStandardError < StandardError
|
75
|
+
attr_reader :code
|
76
|
+
def initialize(message, code)
|
77
|
+
@code = code
|
78
|
+
end
|
79
|
+
end
|
80
|
+
class ExpiredSessionStandardError < RemoteStandardError; end
|
81
|
+
class NotActivatedStandardError < StandardError; end
|
82
|
+
|
83
|
+
################################################################################################
|
84
|
+
################################################################################################
|
85
|
+
# :section: Properties
|
86
|
+
################################################################################################
|
87
|
+
|
88
|
+
# The network this session is being used on (Bebo, Facebook, etc)
|
89
|
+
attr_accessor :network
|
90
|
+
|
91
|
+
# The user id of the user associated with this sesssion.
|
92
|
+
attr_reader :session_user_id
|
93
|
+
|
94
|
+
# The key for this session. You will need to save this for infinite sessions.
|
95
|
+
attr_reader :session_key
|
96
|
+
|
97
|
+
# The expiration time of this session, as given from Facebook API login.
|
98
|
+
attr_reader :session_expires
|
99
|
+
|
100
|
+
# Can be set to any valid logger (for example, RAIL_DEFAULT_LOGGER)
|
101
|
+
attr_accessor :logger
|
102
|
+
|
103
|
+
################################################################################################
|
104
|
+
################################################################################################
|
105
|
+
# :section: Public Interface
|
106
|
+
################################################################################################
|
107
|
+
|
108
|
+
# Constructs a FacebookSession.
|
109
|
+
#
|
110
|
+
# api_key:: your API key
|
111
|
+
# api_secret:: your API secret
|
112
|
+
# quiet:: boolean, set to true if you don't want exceptions to be thrown (defaults to false)
|
113
|
+
def initialize(api_key, api_secret, quiet = false)
|
114
|
+
# required parameters
|
115
|
+
@api_key = api_key
|
116
|
+
@api_secret = api_secret
|
117
|
+
|
118
|
+
# optional parameters
|
119
|
+
@quiet = quiet
|
120
|
+
|
121
|
+
# initialize internal state
|
122
|
+
@last_error_message = nil # DEPRECATED
|
123
|
+
@last_error_code = nil # DEPRECATED
|
124
|
+
@expired = false
|
125
|
+
end
|
126
|
+
|
127
|
+
# Template method. Returns true when the session is definitely prepared to make API calls.
|
128
|
+
def ready?
|
129
|
+
raise NotImplementedError
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns true if the session is expired (will often mean that the session is not ready as well)
|
133
|
+
def expired?
|
134
|
+
return @expired
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns true if exceptions are being suppressed in favor of log messages
|
138
|
+
def quiet?
|
139
|
+
return @quiet
|
140
|
+
end
|
141
|
+
|
142
|
+
# Sets whether or not we suppress exceptions from being thrown
|
143
|
+
def quiet=(val)
|
144
|
+
@quiet = val
|
145
|
+
end
|
146
|
+
|
147
|
+
# Template method. Used for signing a set of parameters in the way that Facebook
|
148
|
+
# specifies: <http://developers.facebook.com/documentation.php?v=1.0&doc=auth>
|
149
|
+
#
|
150
|
+
# params:: a Hash containing the parameters to sign
|
151
|
+
def signature(params)
|
152
|
+
raise NotImplementedError
|
153
|
+
end
|
154
|
+
|
155
|
+
protected
|
156
|
+
def get_network_param(name)
|
157
|
+
HOST_CONSTANTS[network][name]
|
158
|
+
end
|
159
|
+
|
160
|
+
################################################################################################
|
161
|
+
################################################################################################
|
162
|
+
# :section: Utility methods
|
163
|
+
################################################################################################
|
164
|
+
private
|
165
|
+
|
166
|
+
# This allows *any* Facebook method to be called, using the Ruby
|
167
|
+
# mechanism for responding to unimplemented methods. Basically,
|
168
|
+
# this converts a call to "auth_getSession" to "auth.getSession"
|
169
|
+
# and does the proper API call using the parameter hash given.
|
170
|
+
#
|
171
|
+
# This allows you to call an API method such as facebook.users.getInfo
|
172
|
+
# by calling "fbsession.users_getInfo"
|
173
|
+
def method_missing(methodSymbol, *params)
|
174
|
+
# get the remote method name
|
175
|
+
remoteMethod = methodSymbol.to_s.gsub("_", ".")
|
176
|
+
if methodSymbol.to_s.match(/cached_(.*)/)
|
177
|
+
log_debug "** RFACEBOOK(GEM) - DEPRECATION NOTICE - cached methods are deprecated, making a raw call without caching."
|
178
|
+
tokens.shift
|
179
|
+
end
|
180
|
+
|
181
|
+
# there can only be one parameter, a Hash, for remote methods
|
182
|
+
unless (params.size == 1 and params.first.is_a?(Hash))
|
183
|
+
log_debug "** RFACEBOOK(GEM) - when you call a remote Facebook method"
|
184
|
+
end
|
185
|
+
|
186
|
+
# make the remote method call
|
187
|
+
return remote_call(remoteMethod, params.first)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Sets everything up to make a POST request to Facebook's API servers.
|
191
|
+
#
|
192
|
+
# method:: i.e. "users.getInfo"
|
193
|
+
# params:: hash of key,value pairs for the parameters to this method
|
194
|
+
# useSSL:: set to true if the call will be made over SSL
|
195
|
+
def remote_call(method, params={}, useSSL=false) # :nodoc:
|
196
|
+
|
197
|
+
log_debug "** RFACEBOOK(GEM) - RFacebook::FacebookSession\#remote_call - #{method}(#{params.inspect}) - making remote call"
|
198
|
+
|
199
|
+
# set up the parameters
|
200
|
+
params = (params || {}).dup
|
201
|
+
params[:method] = "facebook.#{method}"
|
202
|
+
params[:api_key] = @api_key
|
203
|
+
params[:v] = API_VERSION
|
204
|
+
# params[:format] ||= @response_format # TODO: consider JSON capability
|
205
|
+
|
206
|
+
# non-auth methods get special consideration
|
207
|
+
unless(method == "auth.getSession" or method == "auth.createToken")
|
208
|
+
# session must be activated for non-auth methods
|
209
|
+
raise NotActivatedStandardError, "You must activate the session before using it." unless ready?
|
210
|
+
|
211
|
+
# secret and call ID must be set for non-auth methods
|
212
|
+
params[:session_key] = session_key
|
213
|
+
params[:call_id] = Time.now.to_f.to_s
|
214
|
+
end
|
215
|
+
|
216
|
+
# in the parameters, all arrays must be converted to comma-separated lists
|
217
|
+
params.each{|k,v| params[k] = v.join(",") if v.is_a?(Array)}
|
218
|
+
|
219
|
+
# sign the parameter list by adding a proper sig
|
220
|
+
params[:sig] = signature(params)
|
221
|
+
|
222
|
+
# make the remote call and contain the results in a Facepricot XML object
|
223
|
+
xml = post_request(params, useSSL)
|
224
|
+
return handle_xml_response(xml)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Wraps an XML response in a Facepricot XML document, and checks for
|
228
|
+
# an error response (raising or logging errors as needed)
|
229
|
+
#
|
230
|
+
# NOTE: Facepricot chaining may be deprecated in the 1.0 release
|
231
|
+
def handle_xml_response(rawXML)
|
232
|
+
facepricotXML = Facepricot.new(rawXML)
|
233
|
+
|
234
|
+
# error checking
|
235
|
+
if facepricotXML.at("error_response")
|
236
|
+
|
237
|
+
# get the error code
|
238
|
+
errorCode = facepricotXML.at("error_code").inner_html.to_i
|
239
|
+
errorMessage = facepricotXML.at("error_msg").inner_html
|
240
|
+
log_debug "** RFACEBOOK(GEM) - RFacebook::FacebookSession\#remote_call - remote call failed (#{errorCode}: #{errorMessage})"
|
241
|
+
|
242
|
+
# TODO: remove these 2 lines
|
243
|
+
@last_error_message = "ERROR #{errorCode}: #{errorMessage}" # DEPRECATED
|
244
|
+
@last_error_code = errorCode # DEPRECATED
|
245
|
+
|
246
|
+
# check to see if this error was an expired session error
|
247
|
+
case errorCode
|
248
|
+
|
249
|
+
# the remote method did not exist, convert that to a standard Ruby no-method error
|
250
|
+
when 3
|
251
|
+
raise NoMethodError, errorMessage unless quiet? == true
|
252
|
+
|
253
|
+
# the parameters were wrong, or not enough parameters...convert that to a standard Ruby argument error
|
254
|
+
when 100,606
|
255
|
+
raise ArgumentError, errorMessage unless quiet? == true
|
256
|
+
|
257
|
+
# when the session expires, we need to record that internally
|
258
|
+
when 102
|
259
|
+
@expired = true
|
260
|
+
raise ExpiredSessionStandardError.new(errorMessage, errorCode) unless quiet? == true
|
261
|
+
|
262
|
+
# otherwise, just raise a regular remote error with the error code
|
263
|
+
else
|
264
|
+
raise RemoteStandardError.new(errorMessage, errorCode) unless quiet? == true
|
265
|
+
end
|
266
|
+
|
267
|
+
# since the quiet flag may have been activated, we may not have thrown
|
268
|
+
# an actual exception, so we still need to return nil here
|
269
|
+
return nil
|
270
|
+
end
|
271
|
+
|
272
|
+
# everything was just fine, return the Facepricot XML response
|
273
|
+
return facepricotXML
|
274
|
+
end
|
275
|
+
|
276
|
+
# Posts a request to the remote Facebook API servers, and returns the
|
277
|
+
# raw text body of the result
|
278
|
+
#
|
279
|
+
# params:: a Hash of the post parameters to send to the REST API
|
280
|
+
# useSSL:: defaults to false, set to true if you want to use SSL for the POST
|
281
|
+
def post_request(params, useSSL=false)
|
282
|
+
# get a server handle
|
283
|
+
port = (useSSL == true) ? 443 : 80
|
284
|
+
http_server = Net::HTTP.new(API_HOST, port)
|
285
|
+
http_server.use_ssl = useSSL
|
286
|
+
|
287
|
+
# build a request
|
288
|
+
http_request = Net::HTTP::Post.new(API_PATH_REST)
|
289
|
+
http_request.form_data = params
|
290
|
+
|
291
|
+
# get the response XML
|
292
|
+
return http_server.start{|http| http.request(http_request)}.body
|
293
|
+
end
|
294
|
+
|
295
|
+
# Generates a proper Facebook signature.
|
296
|
+
#
|
297
|
+
# params:: a Hash containing the parameters to sign
|
298
|
+
# secret:: the secret to use to sign the parameters
|
299
|
+
def signature_helper(params, secret) # :nodoc:
|
300
|
+
args = []
|
301
|
+
params.each{|k,v| args << "#{k}=#{v}"}
|
302
|
+
sortedArray = args.sort
|
303
|
+
requestStr = sortedArray.join("")
|
304
|
+
return Digest::MD5.hexdigest("#{requestStr}#{secret}")
|
305
|
+
end
|
306
|
+
|
307
|
+
# log a debug message
|
308
|
+
def log_debug(message) # :nodoc:
|
309
|
+
@logger.debug(message) if @logger
|
310
|
+
end
|
311
|
+
|
312
|
+
# log an informational message
|
313
|
+
def log_info(message) # :nodoc:
|
314
|
+
@logger.info(message) if @logger
|
315
|
+
end
|
316
|
+
|
317
|
+
################################################################################################
|
318
|
+
################################################################################################
|
319
|
+
# :section: Serialization
|
320
|
+
################################################################################################
|
321
|
+
public
|
322
|
+
|
323
|
+
# dump to a serialized string, removing the logger object (which cannot be serialized)
|
324
|
+
def _dump(depth) # :nodoc:
|
325
|
+
instanceVarHash = {}
|
326
|
+
self.instance_variables.each { |k| instanceVarHash[k] = self.instance_variable_get(k) }
|
327
|
+
return Marshal.dump(instanceVarHash.delete_if{|k,v| k == "@logger"})
|
328
|
+
end
|
329
|
+
|
330
|
+
# load from a serialized string
|
331
|
+
def self._load(dumpedStr) # :nodoc:
|
332
|
+
instance = self.new(nil,nil)
|
333
|
+
dumped = Marshal.load(dumpedStr)
|
334
|
+
dumped.each do |k,v|
|
335
|
+
instance.instance_variable_set(k,v)
|
336
|
+
end
|
337
|
+
return instance
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
################################################################################################
|
342
|
+
################################################################################################
|
343
|
+
# :section: Deprecated Methods
|
344
|
+
################################################################################################
|
345
|
+
public
|
346
|
+
|
347
|
+
# DEPRECATED
|
348
|
+
def is_expired? # :nodoc:
|
349
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: is_expired? is deprecated, use expired? instead"
|
350
|
+
return expired?
|
351
|
+
end
|
352
|
+
|
353
|
+
# DEPRECATED
|
354
|
+
def is_activated? # :nodoc:
|
355
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: is_activated? is deprecated, use ready? instead"
|
356
|
+
return ready?
|
357
|
+
end
|
358
|
+
|
359
|
+
# DEPRECATED
|
360
|
+
def is_valid? # :nodoc:
|
361
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: is_valid? is deprecated, use ready? instead"
|
362
|
+
return ready?
|
363
|
+
end
|
364
|
+
|
365
|
+
# DEPRECATED
|
366
|
+
def is_ready? # :nodoc:
|
367
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: is_valid? is deprecated, use ready? instead"
|
368
|
+
return ready?
|
369
|
+
end
|
370
|
+
|
371
|
+
# DEPRECATED
|
372
|
+
def last_error_message # :nodoc:
|
373
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: last_error_message is deprecated"
|
374
|
+
return @last_error_message
|
375
|
+
end
|
376
|
+
|
377
|
+
# DEPRECATED
|
378
|
+
def last_error_code # :nodoc:
|
379
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: last_error_code is deprecated"
|
380
|
+
return @last_error_code
|
381
|
+
end
|
382
|
+
|
383
|
+
# DEPRECATED
|
384
|
+
def suppress_errors # :nodoc:
|
385
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: suppress_errors is deprecated, use quiet? instead"
|
386
|
+
return quiet?
|
387
|
+
end
|
388
|
+
|
389
|
+
# DEPRECATED
|
390
|
+
def suppress_errors=(val) # :nodoc:
|
391
|
+
RAILS_DEFAULT_LOGGER.info "** RFACEBOOK(GEM) DEPRECATION WARNING: suppress_errors= is deprecated, use quiet= instead"
|
392
|
+
@quiet=val
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
|
397
|
+
end
|