djanowski-facebooker 1.0.7 → 1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -1
- data/Manifest.txt +1 -0
- data/README.txt +17 -1
- data/generators/facebook/templates/config/facebooker.yml +6 -1
- data/lib/facebooker.rb +61 -33
- data/lib/facebooker/models/user.rb +33 -4
- data/lib/facebooker/rails/controller.rb +10 -3
- data/lib/facebooker/rails/facebook_url_helper.rb +191 -0
- data/lib/facebooker/rails/helpers.rb +41 -2
- data/lib/facebooker/rails/publisher.rb +5 -2
- data/lib/facebooker/service.rb +64 -3
- data/lib/facebooker/session.rb +5 -3
- data/test/facebook_admin_test.rb +1 -0
- data/test/facebook_cache_test.rb +1 -0
- data/test/facebook_data_test.rb +2 -0
- data/test/rails_integration_test.rb +4 -1
- data/test/session_test.rb +26 -0
- metadata +2 -1
data/History.txt
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
=== x.x.x /
|
1
|
+
=== x.x.x / 2009-xx-xx
|
2
2
|
|
3
|
+
* Modified fql_query to return results as Hashes as a last resort [Alan Larkin]
|
3
4
|
* fixed typo in set app properties parser [Andrew Grim, shane]
|
4
5
|
* Removed actor_id param from templatized feed [shane]
|
5
6
|
* Added admin.get_allocation [shane]
|
data/Manifest.txt
CHANGED
@@ -75,6 +75,7 @@ lib/facebooker/rails/facebook_form_builder.rb
|
|
75
75
|
lib/facebooker/rails/facebook_pretty_errors.rb
|
76
76
|
lib/facebooker/rails/facebook_request_fix.rb
|
77
77
|
lib/facebooker/rails/facebook_session_handling.rb
|
78
|
+
lib/facebooker/rails/facebook_url_helper.rb
|
78
79
|
lib/facebooker/rails/facebook_url_rewriting.rb
|
79
80
|
lib/facebooker/rails/helpers.rb
|
80
81
|
lib/facebooker/rails/helpers/fb_connect.rb
|
data/README.txt
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
Facebooker is a Ruby wrapper over the Facebook[http://facebook.com] {REST API}[http://
|
7
|
+
Facebooker is a Ruby wrapper over the Facebook[http://facebook.com] {REST API}[http://wiki.developers.facebook.com/index.php/API]. Its goals are:
|
8
8
|
|
9
9
|
* Idiomatic Ruby
|
10
10
|
* No dependencies outside of the Ruby standard library (This is true with Rails 2.1. Previous Rails versions require the JSON gem)
|
@@ -55,6 +55,22 @@ Your application users will need to have added the application in facebook to ac
|
|
55
55
|
|
56
56
|
to your application controller.
|
57
57
|
|
58
|
+
== using MemCache session
|
59
|
+
|
60
|
+
Facebook uses some non alphanum characters in the session identifier which interfere with memcache stored sessions. If you want to use MemCache for storing sessions, you can override the valid session id method on memcache by placing the following code in an initializer:
|
61
|
+
|
62
|
+
# add - as an okay key
|
63
|
+
class CGI
|
64
|
+
class Session
|
65
|
+
class MemCacheStore
|
66
|
+
def check_id(id) #:nodoc:#
|
67
|
+
/[^0-9a-zA-Z\-\._]+/ =~ id.to_s ? false : true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
58
74
|
== LICENSE:
|
59
75
|
|
60
76
|
(The MIT License)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# The api key, secret key, and canvas page name are required to get started
|
2
2
|
# Tunnel configuration is only needed if you are going to use the facebooker:tunnel Rake tasks
|
3
3
|
# Your callback url in Facebook should be set to http://public_host:public_port
|
4
|
+
# If you're building a Facebook connect site,
|
5
|
+
# change the value of set_asset_host_to_callback_url to false
|
4
6
|
# To develop for the new profile design, add the following key..
|
5
7
|
# api: new
|
6
8
|
# remove the key or set it to anything else to use the old facebook design.
|
@@ -12,6 +14,7 @@ development:
|
|
12
14
|
canvas_page_name:
|
13
15
|
callback_url:
|
14
16
|
pretty_errors: true
|
17
|
+
set_asset_host_to_callback_url: true
|
15
18
|
tunnel:
|
16
19
|
public_host_username:
|
17
20
|
public_host:
|
@@ -23,6 +26,7 @@ test:
|
|
23
26
|
secret_key:
|
24
27
|
canvas_page_name:
|
25
28
|
callback_url:
|
29
|
+
set_asset_host_to_callback_url: true
|
26
30
|
tunnel:
|
27
31
|
public_host_username:
|
28
32
|
public_host:
|
@@ -33,7 +37,8 @@ production:
|
|
33
37
|
api_key:
|
34
38
|
secret_key:
|
35
39
|
canvas_page_name:
|
36
|
-
callback_url:
|
40
|
+
callback_url:
|
41
|
+
set_asset_host_to_callback_url: true
|
37
42
|
tunnel:
|
38
43
|
public_host_username:
|
39
44
|
public_host:
|
data/lib/facebooker.rb
CHANGED
@@ -19,37 +19,7 @@ end
|
|
19
19
|
require 'zlib'
|
20
20
|
require 'digest/md5'
|
21
21
|
|
22
|
-
|
23
|
-
require 'facebooker/feed'
|
24
|
-
require 'facebooker/logging'
|
25
|
-
require 'facebooker/model'
|
26
|
-
require 'facebooker/parser'
|
27
|
-
require 'facebooker/service'
|
28
|
-
require 'facebooker/server_cache'
|
29
|
-
require 'facebooker/data'
|
30
|
-
require 'facebooker/admin'
|
31
|
-
require 'facebooker/session'
|
32
|
-
require 'facebooker/version'
|
33
|
-
require 'facebooker/models/location'
|
34
|
-
require 'facebooker/models/affiliation'
|
35
|
-
require 'facebooker/models/album'
|
36
|
-
require 'facebooker/models/education_info'
|
37
|
-
require 'facebooker/models/work_info'
|
38
|
-
require 'facebooker/models/event'
|
39
|
-
require 'facebooker/models/group'
|
40
|
-
require 'facebooker/models/notifications'
|
41
|
-
require 'facebooker/models/page'
|
42
|
-
require 'facebooker/models/photo'
|
43
|
-
require 'facebooker/models/cookie'
|
44
|
-
require 'facebooker/models/applicationproperties'
|
45
|
-
require 'facebooker/models/tag'
|
46
|
-
require 'facebooker/models/user'
|
47
|
-
require 'facebooker/models/info_item'
|
48
|
-
require 'facebooker/models/info_section'
|
49
|
-
require 'facebooker/adapters/adapter_base'
|
50
|
-
require 'facebooker/adapters/facebook_adapter'
|
51
|
-
require 'facebooker/adapters/bebo_adapter'
|
52
|
-
require 'facebooker/models/friend_list'
|
22
|
+
|
53
23
|
|
54
24
|
module Facebooker
|
55
25
|
|
@@ -66,8 +36,12 @@ module Facebooker
|
|
66
36
|
ENV['FACEBOOK_SECRET_KEY'] = facebooker['secret_key']
|
67
37
|
ENV['FACEBOOKER_RELATIVE_URL_ROOT'] = facebooker['canvas_page_name']
|
68
38
|
ENV['FACEBOOKER_API'] = facebooker['api']
|
39
|
+
if facebooker.has_key?('set_asset_host_to_callback_url')
|
40
|
+
Facebooker.set_asset_host_to_callback_url = facebooker['set_asset_host_to_callback_url']
|
41
|
+
end
|
42
|
+
Facebooker.timeout = facebooker['timeout']
|
69
43
|
if Object.const_defined?("ActionController")
|
70
|
-
ActionController::Base.asset_host = facebooker['callback_url'] if(ActionController::Base.asset_host.blank?)
|
44
|
+
ActionController::Base.asset_host = facebooker['callback_url'] if(ActionController::Base.asset_host.blank?) && Facebooker.set_asset_host_to_callback_url
|
71
45
|
end
|
72
46
|
@facebooker_configuration = facebooker
|
73
47
|
end
|
@@ -102,7 +76,29 @@ module Facebooker
|
|
102
76
|
current_adapter.is_for?(application_container)
|
103
77
|
end
|
104
78
|
|
105
|
-
|
79
|
+
def set_asset_host_to_callback_url=(val)
|
80
|
+
@set_asset_host_to_callback_url=val
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_asset_host_to_callback_url
|
84
|
+
@set_asset_host_to_callback_url.nil? ? true : @set_asset_host_to_callback_url
|
85
|
+
end
|
86
|
+
|
87
|
+
def use_curl=(val)
|
88
|
+
@use_curl=val
|
89
|
+
end
|
90
|
+
|
91
|
+
def use_curl?
|
92
|
+
@use_curl
|
93
|
+
end
|
94
|
+
|
95
|
+
def timeout=(val)
|
96
|
+
@timeout = val.to_i
|
97
|
+
end
|
98
|
+
|
99
|
+
def timeout
|
100
|
+
@timeout
|
101
|
+
end
|
106
102
|
|
107
103
|
[:api_key,:secret_key, :www_server_base_url,:login_url_base,:install_url_base,:api_rest_path,:api_server_base,:api_server_base_url,:canvas_server_base].each do |delegated_method|
|
108
104
|
define_method(delegated_method){ return current_adapter.send(delegated_method)}
|
@@ -141,3 +137,35 @@ module Facebooker
|
|
141
137
|
end
|
142
138
|
end
|
143
139
|
end
|
140
|
+
|
141
|
+
require 'facebooker/batch_request'
|
142
|
+
require 'facebooker/feed'
|
143
|
+
require 'facebooker/logging'
|
144
|
+
require 'facebooker/model'
|
145
|
+
require 'facebooker/parser'
|
146
|
+
require 'facebooker/service'
|
147
|
+
require 'facebooker/server_cache'
|
148
|
+
require 'facebooker/data'
|
149
|
+
require 'facebooker/admin'
|
150
|
+
require 'facebooker/session'
|
151
|
+
require 'facebooker/version'
|
152
|
+
require 'facebooker/models/location'
|
153
|
+
require 'facebooker/models/affiliation'
|
154
|
+
require 'facebooker/models/album'
|
155
|
+
require 'facebooker/models/education_info'
|
156
|
+
require 'facebooker/models/work_info'
|
157
|
+
require 'facebooker/models/event'
|
158
|
+
require 'facebooker/models/group'
|
159
|
+
require 'facebooker/models/notifications'
|
160
|
+
require 'facebooker/models/page'
|
161
|
+
require 'facebooker/models/photo'
|
162
|
+
require 'facebooker/models/cookie'
|
163
|
+
require 'facebooker/models/applicationproperties'
|
164
|
+
require 'facebooker/models/tag'
|
165
|
+
require 'facebooker/models/user'
|
166
|
+
require 'facebooker/models/info_item'
|
167
|
+
require 'facebooker/models/info_section'
|
168
|
+
require 'facebooker/adapters/adapter_base'
|
169
|
+
require 'facebooker/adapters/facebook_adapter'
|
170
|
+
require 'facebooker/adapters/bebo_adapter'
|
171
|
+
require 'facebooker/models/friend_list'
|
@@ -10,7 +10,7 @@ module Facebooker
|
|
10
10
|
include Model
|
11
11
|
attr_accessor :message, :time, :status_id
|
12
12
|
end
|
13
|
-
FIELDS = [:status, :political, :pic_small, :name, :quotes, :is_app_user, :tv, :profile_update_time, :meeting_sex, :hs_info, :timezone, :relationship_status, :hometown_location, :about_me, :wall_count, :significant_other_id, :pic_big, :music, :uid, :work_history, :sex, :religion, :notes_count, :activities, :pic_square, :movies, :has_added_app, :education_history, :birthday, :first_name, :meeting_for, :last_name, :interests, :current_location, :pic, :books, :affiliations, :locale, :profile_url, :proxied_email]
|
13
|
+
FIELDS = [:status, :political, :pic_small, :name, :quotes, :is_app_user, :tv, :profile_update_time, :meeting_sex, :hs_info, :timezone, :relationship_status, :hometown_location, :about_me, :wall_count, :significant_other_id, :pic_big, :music, :uid, :work_history, :sex, :religion, :notes_count, :activities, :pic_square, :movies, :has_added_app, :education_history, :birthday, :first_name, :meeting_for, :last_name, :interests, :current_location, :pic, :books, :affiliations, :locale, :profile_url, :proxied_email,:email_hashes]
|
14
14
|
STANDARD_FIELDS = [:uid, :first_name, :last_name, :name, :timezone, :birthday, :sex, :affiliations, :locale, :profile_url]
|
15
15
|
attr_accessor :id, :session
|
16
16
|
populating_attr_accessor *FIELDS
|
@@ -86,7 +86,9 @@ module Facebooker
|
|
86
86
|
|
87
87
|
#use __blank instead of nil so that this is cached
|
88
88
|
cache_key = flid||"__blank"
|
89
|
-
|
89
|
+
options = {:uid=>@id}
|
90
|
+
options[:flid] = flid unless flid.nil?
|
91
|
+
@friends_hash[cache_key] ||= @session.post('facebook.friends.get', options,false).map do |uid|
|
90
92
|
User.new(uid, @session)
|
91
93
|
end
|
92
94
|
@friends_hash[cache_key]
|
@@ -169,8 +171,35 @@ module Facebooker
|
|
169
171
|
session.get_photos(nil, nil, profile_pic_album_id)
|
170
172
|
end
|
171
173
|
|
172
|
-
|
173
|
-
|
174
|
+
# Upload a photo to the user's profile.
|
175
|
+
#
|
176
|
+
# In your view, create a multipart form that posts directly to your application (not through canvas):
|
177
|
+
#
|
178
|
+
# <% form_tag photos_url(:canvas => false), :html => {:multipart => true, :promptpermission => 'photo_upload'} do %>
|
179
|
+
# Photo: <%= file_field_tag 'photo' %>
|
180
|
+
# Caption: <%= text_area_tag 'caption' %>
|
181
|
+
# <%= submit_tag 'Upload Photo', :class => 'inputsubmit' %>
|
182
|
+
# <% end %>
|
183
|
+
#
|
184
|
+
# And in your controller:
|
185
|
+
#
|
186
|
+
# class PhotosController < ApplicationController
|
187
|
+
# def create
|
188
|
+
# file = Net::HTTP::MultipartPostFile.new(
|
189
|
+
# params[:photo].original_filename,
|
190
|
+
# params[:photo].content_type,
|
191
|
+
# params[:photo].read
|
192
|
+
# )
|
193
|
+
#
|
194
|
+
# @photo = facebook_session.user.upload_photo(file, :caption => params[:caption])
|
195
|
+
# redirect_to photos_url(:canvas => true)
|
196
|
+
# end
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# Options correspond to http://wiki.developers.facebook.com/index.php/Photos.upload
|
200
|
+
def upload_photo(multipart_post_file, options = {})
|
201
|
+
Photo.from_hash(session.post_file('facebook.photos.upload',
|
202
|
+
options.merge(nil => multipart_post_file)))
|
174
203
|
end
|
175
204
|
|
176
205
|
def profile_fbml
|
@@ -73,9 +73,12 @@ module Facebooker
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def clear_fb_cookies!
|
76
|
-
|
76
|
+
domain_cookie_tag = "base_domain_#{Facebooker.api_key}"
|
77
|
+
cookie_domain = ".#{cookies[domain_cookie_tag]}" if cookies[domain_cookie_tag]
|
78
|
+
fb_cookie_names.each {|name| cookies.delete(name, :domain=>cookie_domain)}
|
79
|
+
cookies.delete Facebooker.api_key
|
77
80
|
end
|
78
|
-
|
81
|
+
|
79
82
|
def fb_cookie_prefix
|
80
83
|
Facebooker.api_key+"_"
|
81
84
|
end
|
@@ -190,7 +193,11 @@ module Facebooker
|
|
190
193
|
end
|
191
194
|
|
192
195
|
def request_comes_from_facebook?
|
193
|
-
request_is_for_a_facebook_canvas? || request_is_facebook_ajax?
|
196
|
+
request_is_for_a_facebook_canvas? || request_is_facebook_ajax? || request_is_fb_ping?
|
197
|
+
end
|
198
|
+
|
199
|
+
def request_is_fb_ping?
|
200
|
+
!params['fb_sig'].blank?
|
194
201
|
end
|
195
202
|
|
196
203
|
def request_is_for_a_facebook_canvas?
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# Extends the ActionView::Helpers::UrlHelper module. See it for details on
|
2
|
+
# the usual url helper methods: url_for, link_to, button_to, etc.
|
3
|
+
#
|
4
|
+
# Mostly, the changes sanitize javascript into facebook javascript.
|
5
|
+
# It sanitizes link_to solely by altering the private methods:
|
6
|
+
# convert_options_to_javascript!, confirm_javascript_function, and
|
7
|
+
# method_javascript_function. For button_to, it alters button_to
|
8
|
+
# itself, as well as confirm_javascript_function. No other methods
|
9
|
+
# need to be changed because of Facebook javascript.
|
10
|
+
#
|
11
|
+
# For button_to and link_to, adds alternate confirm options for facebook.
|
12
|
+
# ==== Options
|
13
|
+
# * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
|
14
|
+
# prompt with the question specified.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# # Generates: <a href="http://rubyforge.org/projects/facebooker" onclick="
|
18
|
+
# # var dlg = new Dialog().showChoice('Please Confirm', 'Go to Facebooker?').setStyle();
|
19
|
+
# # var a=this;dlg.onconfirm = function() {
|
20
|
+
# # document.setLocation(a.getHref());
|
21
|
+
# # }; return false;">Facebooker</a>
|
22
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>"Go to Facebooker?")
|
23
|
+
#
|
24
|
+
# Alternatively, options[:confirm] may be specified.
|
25
|
+
# See the Facebook page http://wiki.developers.facebook.com/index.php/FBJS.
|
26
|
+
# These options are:
|
27
|
+
# <tt>:title</tt>:: Specifies the title of the Facebook dialog. Default is "Please Confirm".
|
28
|
+
# <tt>:content</tt>:: Specifies the title of the Facebook dialog. Default is "Are you sure?".
|
29
|
+
#
|
30
|
+
# Example:
|
31
|
+
# # Generates: <a href="http://rubyforge.org/projects/facebooker" onclick="
|
32
|
+
# # var dlg = new Dialog().showChoice('the page says:', 'Go to Facebooker?').setStyle();
|
33
|
+
# # var a=this;dlg.onconfirm = function() {
|
34
|
+
# # document.setLocation(a.getHref());
|
35
|
+
# # }; return false;">Facebooker</a>
|
36
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>{:title=>"the page says:", :content=>"Go to Facebooker?"})
|
37
|
+
#
|
38
|
+
# Any other options passed are assumed to be css styles.
|
39
|
+
# Again, see the Facebook page http://wiki.developers.facebook.com/index.php/FBJS.
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# # Generates: <a href="http://rubyforge.org/projects/facebooker" onclick="
|
43
|
+
# # var dlg = new Dialog().showChoice('the page says:', 'Are you sure?').setStyle({color: 'pink', width: '200px'});
|
44
|
+
# # var a=this;dlg.onconfirm = function() {
|
45
|
+
# # document.setLocation(a.getHref());
|
46
|
+
# # }; return false;">Facebooker</a>
|
47
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>{:title=>"the page says:, :color=>"pink", :width=>"200px"})
|
48
|
+
module ActionView
|
49
|
+
module Helpers
|
50
|
+
module UrlHelper
|
51
|
+
# Alters one and only one line of the Rails button_to. See below.
|
52
|
+
def button_to_with_facebooker(name, options={}, html_options = {})
|
53
|
+
if !request_comes_from_facebook?
|
54
|
+
button_to_without_facebooker(name,options,html_options)
|
55
|
+
else
|
56
|
+
html_options = html_options.stringify_keys
|
57
|
+
convert_boolean_attributes!(html_options, %w( disabled ))
|
58
|
+
|
59
|
+
method_tag = ''
|
60
|
+
if (method = html_options.delete('method')) && %w{put delete}.include?(method.to_s)
|
61
|
+
method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
form_method = method.to_s == 'get' ? 'get' : 'post'
|
65
|
+
|
66
|
+
request_token_tag = ''
|
67
|
+
if form_method == 'post' && protect_against_forgery?
|
68
|
+
request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
|
69
|
+
end
|
70
|
+
|
71
|
+
if confirm = html_options.delete("confirm")
|
72
|
+
# this line is the only change => html_options["onclick"] = "return #{confirm_javascript_function(confirm)}"
|
73
|
+
html_options["onclick"] = "#{confirm_javascript_function(confirm, 'a.getForm().submit();')}return false;"
|
74
|
+
end
|
75
|
+
|
76
|
+
url = options.is_a?(String) ? options : self.url_for(options)
|
77
|
+
name ||= url
|
78
|
+
|
79
|
+
html_options.merge!("type" => "submit", "value" => name)
|
80
|
+
|
81
|
+
"<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
|
82
|
+
method_tag + tag("input", html_options) + request_token_tag + "</div></form>"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
alias_method_chain :button_to, :facebooker
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Altered to throw an error on :popup and sanitize the javascript
|
91
|
+
# for Facebook.
|
92
|
+
def convert_options_to_javascript_with_facebooker!(html_options, url ='')
|
93
|
+
if !request_comes_from_facebook?
|
94
|
+
convert_options_to_javascript_without_facebooker!(html_options,url)
|
95
|
+
else
|
96
|
+
confirm, popup = html_options.delete("confirm"), html_options.delete("popup")
|
97
|
+
|
98
|
+
method, href = html_options.delete("method"), html_options['href']
|
99
|
+
|
100
|
+
html_options["onclick"] = case
|
101
|
+
when popup
|
102
|
+
raise ActionView::ActionViewError, "You can't use :popup"
|
103
|
+
when method # or maybe (confirm and method)
|
104
|
+
"#{method_javascript_function(method, url, href, confirm)}return false;"
|
105
|
+
when confirm # and only confirm
|
106
|
+
"#{confirm_javascript_function(confirm)}return false;"
|
107
|
+
else
|
108
|
+
html_options["onclick"]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
alias_method_chain :convert_options_to_javascript!, :facebooker
|
114
|
+
|
115
|
+
|
116
|
+
# Overrides a private method that link_to calls via convert_options_to_javascript! and
|
117
|
+
# also, button_to calls directly. For Facebook, confirm can be a hash of options to
|
118
|
+
# stylize the Facebook dialog. Takes :title, :content, :style options. See
|
119
|
+
# the Facebook page http://wiki.developers.facebook.com/index.php/FBJS for valid
|
120
|
+
# style formats like "color: 'black', background: 'white'" or like "'color','black'".
|
121
|
+
#
|
122
|
+
# == Examples ==
|
123
|
+
#
|
124
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>"Go to Facebooker?")
|
125
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>{:title=>"the page says:, :content=>"Go to Facebooker?"})
|
126
|
+
# link_to("Facebooker", "http://rubyforge.org/projects/facebooker", :confirm=>{:title=>"the page says:, :content=>"Go to Facebooker?", :color=>"pink"})
|
127
|
+
def confirm_javascript_function_with_facebooker(confirm, fun = nil)
|
128
|
+
if !request_comes_from_facebook?
|
129
|
+
confirm_javascript_function_without_facebooker(confirm)
|
130
|
+
else
|
131
|
+
if(confirm.is_a?(Hash))
|
132
|
+
confirm_options = confirm.stringify_keys
|
133
|
+
title = confirm_options.delete("title") || "Please Confirm"
|
134
|
+
content = confirm_options.delete("content") || "Are you sure?"
|
135
|
+
style = confirm_options.empty? ? "" : convert_options_to_css(confirm_options)
|
136
|
+
else
|
137
|
+
title,content,style = 'Please Confirm', confirm, ""
|
138
|
+
end
|
139
|
+
|
140
|
+
"var dlg = new Dialog().showChoice('#{escape_javascript(title.to_s)}','#{escape_javascript(content.to_s)}').setStyle(#{style});"+
|
141
|
+
"var a=this;dlg.onconfirm = function() { #{fun ? fun : 'document.setLocation(a.getHref());'} };"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
alias_method_chain :confirm_javascript_function, :facebooker
|
146
|
+
|
147
|
+
def convert_options_to_css(options)
|
148
|
+
key_pair = options.shift
|
149
|
+
style = "{#{key_pair[0]}: '#{key_pair[1]}'"
|
150
|
+
for key in options.keys
|
151
|
+
style << ", #{key}: '#{options[key]}'"
|
152
|
+
end
|
153
|
+
style << "}"
|
154
|
+
end
|
155
|
+
|
156
|
+
# Dynamically creates a form for link_to with method. Calls confirm_javascript_function if and
|
157
|
+
# only if (confirm && method) for link_to
|
158
|
+
def method_javascript_function_with_facebooker(method, url = '', href = nil, confirm = nil)
|
159
|
+
if !request_comes_from_facebook?
|
160
|
+
method_javascript_function_without_facebooker(method,url,href)
|
161
|
+
else
|
162
|
+
action = (href && url.size > 0) ? "'#{url}'" : 'a.getHref()'
|
163
|
+
submit_function =
|
164
|
+
"var f = document.createElement('form'); f.setStyle('display','none'); " +
|
165
|
+
"a.getParentNode().appendChild(f); f.setMethod('POST'); f.setAction(#{action});"
|
166
|
+
|
167
|
+
unless method == :post
|
168
|
+
submit_function << "var m = document.createElement('input'); m.setType('hidden'); "
|
169
|
+
submit_function << "m.setName('_method'); m.setValue('#{method}'); f.appendChild(m);"
|
170
|
+
end
|
171
|
+
|
172
|
+
if protect_against_forgery?
|
173
|
+
submit_function << "var s = document.createElement('input'); s.setType('hidden'); "
|
174
|
+
submit_function << "s.setName('#{request_forgery_protection_token}'); s.setValue('#{escape_javascript form_authenticity_token}'); f.appendChild(s);"
|
175
|
+
end
|
176
|
+
submit_function << "f.submit();"
|
177
|
+
|
178
|
+
if(confirm)
|
179
|
+
confirm_javascript_function(confirm, submit_function)
|
180
|
+
else
|
181
|
+
"var a=this;" + submit_function
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
alias_method_chain :method_javascript_function, :facebooker
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
@@ -524,20 +524,52 @@ module Facebooker
|
|
524
524
|
|
525
525
|
#
|
526
526
|
# Embed a discussion board named xid on the current page
|
527
|
-
#
|
527
|
+
# <em>See</em http://wiki.developers.facebook.com/index.php/Fb:board for more details
|
528
|
+
# Options are:
|
529
|
+
# * canpost
|
530
|
+
# * candelete
|
531
|
+
# * canmark
|
532
|
+
# * cancreatet
|
533
|
+
# * numtopics
|
534
|
+
# * callbackurl
|
535
|
+
# * returnurl
|
536
|
+
#
|
528
537
|
def fb_board(xid,options={})
|
529
538
|
options = options.dup
|
530
|
-
|
539
|
+
title = (title = options.delete(:title)) ? fb_title(title) : nil
|
540
|
+
content_tag("fb:board", title, stringify_vals(options.merge(:xid=>xid)))
|
531
541
|
end
|
532
542
|
|
543
|
+
# Renders an 'Add to Profile' button
|
544
|
+
# The button allows a user to add condensed profile box to the main profile
|
533
545
|
def fb_add_profile_section
|
534
546
|
tag "fb:add-section-button",:section=>"profile"
|
535
547
|
end
|
536
548
|
|
549
|
+
# Renders an 'Add to Info' button
|
550
|
+
# The button allows a user to add an application info section to her Info tab
|
537
551
|
def fb_add_info_section
|
538
552
|
tag "fb:add-section-button",:section=>"info"
|
539
553
|
end
|
540
554
|
|
555
|
+
# Renders a link that, when clicked, initiates a dialog requesting the specified extended permission from the user.
|
556
|
+
#
|
557
|
+
# You can prompt a user with the following permissions:
|
558
|
+
# * email
|
559
|
+
# * offline_access
|
560
|
+
# * status_update
|
561
|
+
# * photo_upload
|
562
|
+
# * create_listing
|
563
|
+
# * create_event
|
564
|
+
# * rsvp_event
|
565
|
+
# * sms
|
566
|
+
#
|
567
|
+
# Example:
|
568
|
+
# <%= fb_prompt_permission('email', "Would you like to receive email from our application?" ) %>
|
569
|
+
#
|
570
|
+
# See http://wiki.developers.facebook.com/index.php/Fb:prompt-permission for
|
571
|
+
# more details
|
572
|
+
#
|
541
573
|
def fb_prompt_permission(permission,message,callback=nil)
|
542
574
|
raise(ArgumentError, "Unknown value for permission: #{permission}") unless VALID_PERMISSIONS.include?(permission.to_sym)
|
543
575
|
args={:perms=>permission}
|
@@ -545,22 +577,29 @@ module Facebooker
|
|
545
577
|
content_tag("fb:prompt-permission",message,args)
|
546
578
|
end
|
547
579
|
|
580
|
+
# Renders an <fb:eventlink /> tag that displays the event name and links to the event's page.
|
548
581
|
def fb_eventlink(eid)
|
549
582
|
content_tag "fb:eventlink",nil,:eid=>eid
|
550
583
|
end
|
551
584
|
|
585
|
+
# Renders an <fb:grouplink /> tag that displays the group name and links to the group's page.
|
552
586
|
def fb_grouplink(gid)
|
553
587
|
content_tag "fb:grouplink",nil,:gid=>gid
|
554
588
|
end
|
555
589
|
|
590
|
+
# Returns the status of the user
|
556
591
|
def fb_user_status(user,linked=true)
|
557
592
|
content_tag "fb:user-status",nil,stringify_vals(:uid=>cast_to_facebook_id(user), :linked=>linked)
|
558
593
|
end
|
559
594
|
|
595
|
+
# Renders a standard 'Share' button for the specified URL.
|
560
596
|
def fb_share_button(url)
|
561
597
|
content_tag "fb:share-button",nil,:class=>"url",:href=>url
|
562
598
|
end
|
563
599
|
|
600
|
+
# Renders the FBML on a Facebook server inside an iframe.
|
601
|
+
#
|
602
|
+
# Meant to be used for a Facebook Connect site or an iframe application
|
564
603
|
def fb_serverfbml(options={},&proc)
|
565
604
|
inner = capture(&proc)
|
566
605
|
concat(content_tag("fb:serverfbml",inner,options),&proc.binding)
|
@@ -174,10 +174,13 @@ module Facebooker
|
|
174
174
|
|
175
175
|
def hashed_content(klass, method)
|
176
176
|
publisher = setup_publisher(klass,method)
|
177
|
-
|
177
|
+
# sort the Hash elements (in the short_story and full_story) before generating MD5
|
178
|
+
Digest::MD5.hexdigest [publisher.one_line_story_templates,
|
179
|
+
(publisher.short_story_templates and publisher.short_story_templates.collect{|ss| ss.to_a.sort_by{|e| e[0]}}),
|
180
|
+
(publisher.full_story_template and publisher.full_story_template.to_a.sort_by{|e| e[0]})
|
181
|
+
].to_json
|
178
182
|
end
|
179
183
|
|
180
|
-
|
181
184
|
def template_name(klass,method)
|
182
185
|
"#{klass.name}::#{method}"
|
183
186
|
end
|
data/lib/facebooker/service.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'curb'
|
3
|
+
Facebooker.use_curl = true
|
4
|
+
rescue Exception=>e
|
5
|
+
puts e
|
6
|
+
require 'net/http'
|
7
|
+
end
|
2
8
|
require 'facebooker/parser'
|
3
9
|
module Facebooker
|
4
10
|
class Service
|
@@ -11,7 +17,7 @@ module Facebooker
|
|
11
17
|
# TODO: support ssl
|
12
18
|
def post(params)
|
13
19
|
attempt = 0
|
14
|
-
Parser.parse(params[:method],
|
20
|
+
Parser.parse(params[:method], post_form(url,params) )
|
15
21
|
rescue Errno::ECONNRESET, EOFError
|
16
22
|
if attempt == 0
|
17
23
|
attempt += 1
|
@@ -19,13 +25,68 @@ module Facebooker
|
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
28
|
+
def post_form(url,params)
|
29
|
+
if Facebooker.use_curl?
|
30
|
+
post_form_with_curl(url,params)
|
31
|
+
else
|
32
|
+
post_form_with_net_http(url,params)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def post_form_with_net_http(url,params)
|
37
|
+
Net::HTTP.post_form(url, params)
|
38
|
+
end
|
39
|
+
|
40
|
+
def post_form_with_curl(url,params,multipart=false)
|
41
|
+
response = Curl::Easy.http_post(url.to_s, *to_curb_params(params)) do |c|
|
42
|
+
c.multipart_form_post = multipart
|
43
|
+
c.timeout = Facebooker.timeout
|
44
|
+
end
|
45
|
+
response.body_str
|
46
|
+
end
|
47
|
+
|
48
|
+
def post_multipart_form(url,params)
|
49
|
+
if Facebooker.use_curl?
|
50
|
+
post_form_with_curl(url,params,true)
|
51
|
+
else
|
52
|
+
post_multipart_form_with_net_http(url,params)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def post_multipart_form_with_net_http(url,params)
|
57
|
+
Net::HTTP.post_multipart_form(url, params)
|
58
|
+
end
|
59
|
+
|
22
60
|
def post_file(params)
|
23
|
-
Parser.parse(params[:method],
|
61
|
+
Parser.parse(params[:method], post_multipart_form(url, params))
|
24
62
|
end
|
25
63
|
|
26
64
|
private
|
27
65
|
def url
|
28
66
|
URI.parse('http://'+ @api_base + @api_path)
|
29
67
|
end
|
68
|
+
|
69
|
+
# Net::HTTP::MultipartPostFile
|
70
|
+
def multipart_post_file?(object)
|
71
|
+
object.respond_to?(:content_type) &&
|
72
|
+
object.respond_to?(:data) &&
|
73
|
+
object.respond_to?(:filename)
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_curb_params(params)
|
77
|
+
parray = []
|
78
|
+
params.each_pair do |k,v|
|
79
|
+
if multipart_post_file?(v)
|
80
|
+
# Curl doesn't like blank field names
|
81
|
+
field = Curl::PostField.file((k.blank? ? 'xxx' : k.to_s), nil, File.basename(v.filename))
|
82
|
+
field.content_type = v.content_type
|
83
|
+
field.content = v.data
|
84
|
+
parray << field
|
85
|
+
else
|
86
|
+
parray << Curl::PostField.content(k.to_s, v.to_s)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
parray
|
90
|
+
end
|
30
91
|
end
|
31
92
|
end
|
data/lib/facebooker/session.rb
CHANGED
@@ -178,8 +178,10 @@ module Facebooker
|
|
178
178
|
Photo.from_hash(hash)
|
179
179
|
when 'event_member'
|
180
180
|
Event::Attendance.from_hash(hash)
|
181
|
+
else
|
182
|
+
hash
|
181
183
|
end
|
182
|
-
end
|
184
|
+
end
|
183
185
|
end
|
184
186
|
end
|
185
187
|
|
@@ -211,13 +213,13 @@ module Facebooker
|
|
211
213
|
end
|
212
214
|
|
213
215
|
def users_standard(user_ids, fields=[])
|
214
|
-
post("facebook.users.getStandardInfo",:uids=>user_ids.join(","),:fields=>User.
|
216
|
+
post("facebook.users.getStandardInfo",:uids=>user_ids.join(","),:fields=>User.standard_fields(fields)) do |users|
|
215
217
|
users.map { |u| User.new(u)}
|
216
218
|
end
|
217
219
|
end
|
218
220
|
|
219
221
|
def users(user_ids, fields=[])
|
220
|
-
post("facebook.users.getInfo",:uids=>user_ids.join(","),:fields=>User.
|
222
|
+
post("facebook.users.getInfo",:uids=>user_ids.join(","),:fields=>User.user_fields(fields)) do |users|
|
221
223
|
users.map { |u| User.new(u)}
|
222
224
|
end
|
223
225
|
end
|
data/test/facebook_admin_test.rb
CHANGED
data/test/facebook_cache_test.rb
CHANGED
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/test_helper.rb'
|
|
3
3
|
class FacebookCacheTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
5
|
@session = Facebooker::Session.create('apikey', 'secretkey')
|
6
|
+
Facebooker.use_curl=false
|
6
7
|
end
|
7
8
|
|
8
9
|
def test_can_ask_facebook_to_store_fbml_in_a_named_reference
|
data/test/facebook_data_test.rb
CHANGED
@@ -3,6 +3,8 @@ require File.dirname(__FILE__) + '/test_helper.rb'
|
|
3
3
|
class FacebookDataTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
5
|
@session = Facebooker::Session.create('apikey', 'secretkey')
|
6
|
+
#make sure we use net::http since that's what the tests expect
|
7
|
+
Facebooker.use_curl=false
|
6
8
|
end
|
7
9
|
|
8
10
|
def test_can_ask_facebook_to_set_a_cookies
|
@@ -894,7 +894,10 @@ class RailsHelperTest < Test::Unit::TestCase
|
|
894
894
|
assert_equal "<fb:comments candelete=\"false\" canpost=\"true\" numposts=\"4\" optional=\"false\" xid=\"xxx\"><fb:title>TITLE</fb:title></fb:comments>", @h.fb_comments("xxx",true,false,4,:optional=>false, :title => "TITLE")
|
895
895
|
end
|
896
896
|
def test_fb_board
|
897
|
-
assert_equal "<fb:board optional=\"false\" xid=\"xxx\"
|
897
|
+
assert_equal "<fb:board optional=\"false\" xid=\"xxx\"></fb:board>", @h.fb_board("xxx",:optional => false)
|
898
|
+
end
|
899
|
+
def test_fb_board_with_title
|
900
|
+
assert_equal "<fb:board optional=\"false\" xid=\"xxx\"><fb:title>TITLE</fb:title></fb:board>", @h.fb_board("xxx",:optional=>false, :title => "TITLE")
|
898
901
|
end
|
899
902
|
|
900
903
|
def test_fb_dashboard
|
data/test/session_test.rb
CHANGED
@@ -8,6 +8,7 @@ class SessionTest < Test::Unit::TestCase
|
|
8
8
|
ENV['FACEBOOK_SECRET_KEY'] = '7654321'
|
9
9
|
Facebooker.current_adapter = nil
|
10
10
|
@session = Facebooker::Session.create('whatever', 'doesnotmatterintest')
|
11
|
+
Facebooker.use_curl=false
|
11
12
|
end
|
12
13
|
|
13
14
|
def teardown
|
@@ -574,6 +575,31 @@ class SessionTest < Test::Unit::TestCase
|
|
574
575
|
end
|
575
576
|
end
|
576
577
|
|
578
|
+
class PostMethodTest < Test::Unit::TestCase
|
579
|
+
|
580
|
+
def setup
|
581
|
+
Facebooker.use_curl = true
|
582
|
+
Facebooker::Parser.stubs(:parse)
|
583
|
+
@uri = URI.parse("http://api.facebook.com/api")
|
584
|
+
@service = Facebooker::Service.new("a","b","c")
|
585
|
+
@service.stubs("url").returns(@uri)
|
586
|
+
end
|
587
|
+
|
588
|
+
def teardown
|
589
|
+
Facebooker.use_curl = false
|
590
|
+
end
|
591
|
+
|
592
|
+
def test_use_curl_makes_post_with_curl
|
593
|
+
@service.expects(:post_form_with_curl).with(@uri,{:method=>"a"})
|
594
|
+
@service.post(:method=>"a")
|
595
|
+
end
|
596
|
+
|
597
|
+
def test_use_curl_makes_post_file_use_curl_with_multipart
|
598
|
+
@service.expects(:post_form_with_curl).with(@uri,{:method=>"a"},true)
|
599
|
+
@service.post_file(:method=>"a")
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
577
603
|
class CanvasSessionTest < Test::Unit::TestCase
|
578
604
|
def setup
|
579
605
|
ENV['FACEBOOK_API_KEY'] = '1234567'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djanowski-facebooker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chad Fowler
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- lib/facebooker/rails/facebook_pretty_errors.rb
|
118
118
|
- lib/facebooker/rails/facebook_request_fix.rb
|
119
119
|
- lib/facebooker/rails/facebook_session_handling.rb
|
120
|
+
- lib/facebooker/rails/facebook_url_helper.rb
|
120
121
|
- lib/facebooker/rails/facebook_url_rewriting.rb
|
121
122
|
- lib/facebooker/rails/helpers.rb
|
122
123
|
- lib/facebooker/rails/helpers/fb_connect.rb
|