facebook_client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/auth.rb +62 -0
- data/lib/ext.rb +58 -0
- data/lib/facebook_client.rb +47 -0
- data/lib/graph.rb +36 -0
- data/lib/rest_api.rb +42 -0
- metadata +107 -0
data/lib/auth.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module FacebookClient
|
5
|
+
|
6
|
+
class ResponseError < StandardError; end
|
7
|
+
|
8
|
+
class Auth
|
9
|
+
|
10
|
+
def initialize(fb)
|
11
|
+
@fb=fb
|
12
|
+
end
|
13
|
+
|
14
|
+
def url(params={})
|
15
|
+
# params
|
16
|
+
# - scope
|
17
|
+
# - redirect_uri
|
18
|
+
params = params.stringify_keys
|
19
|
+
params['client_id'] = @fb.app_id
|
20
|
+
params.require_keys('redirect_uri', 'client_id')
|
21
|
+
params.assert_valid_keys('redirect_uri', 'client_id', 'scope')
|
22
|
+
connection.build_url('/oauth/authorize', params).to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def request_access(params={})
|
26
|
+
# required params
|
27
|
+
# - code
|
28
|
+
# - redirect_uri
|
29
|
+
response = connection.get(access_token_url(params))
|
30
|
+
data = Rack::Utils.parse_query(response.body)
|
31
|
+
validate_access_token_response(data)
|
32
|
+
@fb.graph(data['access_token'], data['expires'])
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_access_token_response(data)
|
36
|
+
if !data.is_a?(Hash)
|
37
|
+
raise ResponseError, "response must be a hash"
|
38
|
+
end
|
39
|
+
data = data.stringify_keys
|
40
|
+
missing_keys = ['access_token']-data.keys
|
41
|
+
if missing_keys.size>0
|
42
|
+
raise ResponseError, "response missing key(s) #{missing_keys.join(', ')}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def access_token_url(params={})
|
47
|
+
params = params.stringify_keys
|
48
|
+
params['client_id'] = @fb.app_id
|
49
|
+
params['client_secret'] = @fb.secret
|
50
|
+
params.require_keys('redirect_uri', 'client_id', 'client_secret', 'code')
|
51
|
+
params.assert_valid_keys('redirect_uri', 'client_id', 'client_secret', 'code')
|
52
|
+
connection.build_url('/oauth/access_token', params).to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def connection
|
56
|
+
@connection ||= Faraday::Connection.new(:url => Base::GRAPH_URL) do |builder|
|
57
|
+
builder.adapter :net_http
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/ext.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
def reverse_merge(other_hash)
|
4
|
+
other_hash.merge(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Return a new hash with all keys converted to strings.
|
8
|
+
def stringify_keys
|
9
|
+
dup.stringify_keys!
|
10
|
+
end
|
11
|
+
|
12
|
+
# Destructively convert all keys to strings.
|
13
|
+
def stringify_keys!
|
14
|
+
keys.each do |key|
|
15
|
+
self[key.to_s] = delete(key)
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return a new hash with all keys converted to symbols, as long as
|
21
|
+
# they respond to +to_sym+.
|
22
|
+
def symbolize_keys
|
23
|
+
dup.symbolize_keys!
|
24
|
+
end
|
25
|
+
|
26
|
+
# Destructively convert all keys to symbols, as long as they respond
|
27
|
+
# to +to_sym+.
|
28
|
+
def symbolize_keys!
|
29
|
+
keys.each do |key|
|
30
|
+
self[(key.to_sym rescue key)] = delete(key) if key.respond_to?(:to_sym) && !key.is_a?(Fixnum)
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :to_options, :symbolize_keys
|
36
|
+
alias_method :to_options!, :symbolize_keys!
|
37
|
+
|
38
|
+
# Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
|
39
|
+
# Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
|
40
|
+
# as keys, this will fail.
|
41
|
+
#
|
42
|
+
# ==== Examples
|
43
|
+
# { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
|
44
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
|
45
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
46
|
+
def assert_valid_keys(*valid_keys)
|
47
|
+
unknown_keys = keys - [valid_keys].flatten
|
48
|
+
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
def require_keys(*required_keys)
|
52
|
+
missing_keys = [required_keys].flatten - keys
|
53
|
+
if missing_keys.size>0
|
54
|
+
raise(ArgumentError, "Missing key(s): #{missing_keys.join(', ')}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/ext'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__)+'/graph'
|
4
|
+
require File.dirname(__FILE__)+'/auth'
|
5
|
+
require File.dirname(__FILE__)+'/rest_api'
|
6
|
+
|
7
|
+
module FacebookClient
|
8
|
+
|
9
|
+
class Base
|
10
|
+
|
11
|
+
GRAPH_URL = 'https://graph.facebook.com'
|
12
|
+
|
13
|
+
attr_reader :params
|
14
|
+
|
15
|
+
def initialize(default_params={})
|
16
|
+
@params = default_params.reverse_merge({
|
17
|
+
:app_id => ENV['FB_APP_ID'],
|
18
|
+
:api_key => ENV['FB_API_KEY'],
|
19
|
+
:secret => ENV['FB_SECRET'],
|
20
|
+
:canvas => ENV['FB_CANVAS'],
|
21
|
+
:callback_url => ENV['FB_CALLBACK_URL']
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth
|
26
|
+
@auth ||= Auth.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def graph(token, expires=nil)
|
30
|
+
Graph.new(self,token,expires)
|
31
|
+
end
|
32
|
+
|
33
|
+
def rest_api
|
34
|
+
@rest_api ||= RestApi.new(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(name, *args)
|
38
|
+
if @params.has_key?(name)
|
39
|
+
return @params[name]
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/graph.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module FacebookClient
|
4
|
+
|
5
|
+
class Graph
|
6
|
+
|
7
|
+
attr_reader :access_token
|
8
|
+
|
9
|
+
def initialize(fb, access_token, expires=nil)
|
10
|
+
@fb=fb
|
11
|
+
@access_token=access_token
|
12
|
+
if expires.nil?
|
13
|
+
expires=0
|
14
|
+
end
|
15
|
+
expires=expires.to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(path, params={})
|
19
|
+
params = params.stringify_keys
|
20
|
+
params['access_token'] = @access_token
|
21
|
+
resp = connection.run_request(:get, path, nil, {}) do |request|
|
22
|
+
request.params.update(params)
|
23
|
+
end
|
24
|
+
resp.body
|
25
|
+
end
|
26
|
+
|
27
|
+
def connection
|
28
|
+
@connection ||= Faraday::Connection.new(:url => Base::GRAPH_URL) do |builder|
|
29
|
+
builder.adapter :net_http
|
30
|
+
builder.response :yajl
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/rest_api.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module FacebookClient
|
2
|
+
|
3
|
+
class ResponseError < StandardError; end
|
4
|
+
|
5
|
+
require 'digest'
|
6
|
+
require 'faraday'
|
7
|
+
|
8
|
+
class RestApi
|
9
|
+
|
10
|
+
def initialize(fb)
|
11
|
+
@fb = fb
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(method, params={})
|
15
|
+
params[:format] = 'JSON'
|
16
|
+
params[:v] = '1.0'
|
17
|
+
params[:method] = 'facebook.' + method
|
18
|
+
params[:call_id] = Time.now.to_f.to_s
|
19
|
+
params[:timeout] ||= 8 # seconds
|
20
|
+
params[:api_key] = @fb.api_key
|
21
|
+
|
22
|
+
timeout = params.delete(:timeout)
|
23
|
+
|
24
|
+
raw_string = params.inject([]) { |args, pair| args << pair.join('=') }.sort.join
|
25
|
+
params[:sig] = Digest::MD5.hexdigest(raw_string + @fb.secret)
|
26
|
+
|
27
|
+
response = connection.post do |request|
|
28
|
+
request.body = params
|
29
|
+
end
|
30
|
+
response.body
|
31
|
+
end
|
32
|
+
|
33
|
+
def connection
|
34
|
+
@connection ||= Faraday::Connection.new(:url => 'http://api.facebook.com/restserver.php') do |builder|
|
35
|
+
builder.adapter :net_http
|
36
|
+
builder.response :yajl
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: facebook_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- David Crockett
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-13 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: faraday
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 4
|
30
|
+
- 5
|
31
|
+
version: 0.4.5
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: yajl-ruby
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 7
|
44
|
+
- 6
|
45
|
+
version: 0.7.6
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 1
|
57
|
+
- 0
|
58
|
+
- 1
|
59
|
+
version: 1.0.1
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Facebook Client
|
63
|
+
email: davy@davcro.com
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files: []
|
69
|
+
|
70
|
+
files:
|
71
|
+
- lib/auth.rb
|
72
|
+
- lib/ext.rb
|
73
|
+
- lib/facebook_client.rb
|
74
|
+
- lib/graph.rb
|
75
|
+
- lib/rest_api.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage:
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
requirements: []
|
100
|
+
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.3.6
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Facebook Client
|
106
|
+
test_files: []
|
107
|
+
|