doesopengraph 0.1.1 → 0.2.0
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/lib/doesopengraph/graph_api.rb +49 -70
- data/lib/doesopengraph/graph_request.rb +59 -0
- data/lib/doesopengraph/graph_response.rb +122 -8
- data/lib/doesopengraph.rb +8 -1
- metadata +4 -4
- data/lib/doesopengraph/graph_node.rb +0 -42
@@ -6,6 +6,14 @@
|
|
6
6
|
#
|
7
7
|
|
8
8
|
module DoesOpenGraph
|
9
|
+
|
10
|
+
class OpenGraphException < Exception; end
|
11
|
+
class IncapableOfUpdateMethods < OpenGraphException; end
|
12
|
+
class InvalidRequestMethod < OpenGraphException; end
|
13
|
+
class InvalidResponseFromFacebook < OpenGraphException; end
|
14
|
+
|
15
|
+
|
16
|
+
|
9
17
|
class GraphAPI
|
10
18
|
|
11
19
|
require "typhoeus"
|
@@ -15,99 +23,70 @@ module DoesOpenGraph
|
|
15
23
|
HTTP_GRAPH_ENDPOINT = "http://graph.facebook.com/"
|
16
24
|
HTTPS_GRAPH_ENDPOINT = "https://graph.facebook.com/"
|
17
25
|
|
18
|
-
attr_reader :access_token
|
26
|
+
attr_reader :access_token, :history
|
19
27
|
|
20
28
|
def initialize(acctok=nil)
|
21
29
|
@access_token = acctok
|
30
|
+
@history = Array.new
|
22
31
|
end
|
23
|
-
|
24
|
-
|
32
|
+
|
33
|
+
def renew(acctok)
|
34
|
+
@access_token = acctok
|
35
|
+
end
|
36
|
+
|
37
|
+
|
25
38
|
def node(id, connection=nil, params={})
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# Stringify tokens:
|
30
|
-
id = id.to_s
|
31
|
-
connection = connection.to_s unless connection.nil?
|
32
|
-
|
33
|
-
# Smoosh the URL components together:
|
34
|
-
base = @access_token.nil? ? HTTP_GRAPH_ENDPOINT : HTTPS_GRAPH_ENDPOINT
|
35
|
-
path = connection.nil? ? id : File.join(id, connection)
|
36
|
-
href = File.join(base, path)
|
37
|
-
|
38
|
-
# Make a request and parse JSON result:
|
39
|
-
begin
|
40
|
-
response = Typhoeus::Request.get(href, :params=>params)
|
41
|
-
data = JSON.parse(response.body)
|
42
|
-
return GraphNode.new(data, self)
|
43
|
-
rescue JSON::ParserError => jsone
|
44
|
-
raise "Invalid JSON or poorly formed JSON returned for #{path}" and return nil
|
45
|
-
end
|
39
|
+
path = connection.nil? ? id.to_s : File.join(id.to_s, connection.to_s)
|
40
|
+
return request(:get, path, params)
|
46
41
|
end
|
47
42
|
alias_method :get, :node
|
48
43
|
|
49
44
|
|
50
45
|
def update(id, connection, params={})
|
51
|
-
# Inject the access token if we have it and err if we don't
|
52
46
|
return nil unless @access_token
|
53
|
-
|
54
|
-
|
55
|
-
# Smoosh the URL components together:
|
56
|
-
base = HTTPS_GRAPH_ENDPOINT
|
57
|
-
path = File.join(id, connection)
|
58
|
-
href = File.join(base, path)
|
59
|
-
|
60
|
-
# Make our POST request and check the results:
|
61
|
-
begin
|
62
|
-
response = Typhoeus::Request.post(href, :params=>params)
|
63
|
-
data = JSON.parse(response.body)
|
64
|
-
return GraphResponse.new(data)
|
65
|
-
rescue JSON::ParserError => jsone
|
66
|
-
# A JSON.parse on "true" triggers an error, so let's build it straight from body:
|
67
|
-
return GraphResponse.new(response.body)
|
68
|
-
end
|
47
|
+
path = connection.nil? ? id.to_s : File.join(id.to_s, connection.to_s)
|
48
|
+
return request(:post, path, params)
|
69
49
|
end
|
70
50
|
alias_method :post, :update
|
71
51
|
|
72
52
|
|
73
53
|
def delete(id, connection=nil)
|
74
|
-
# Inject the access token if we have it and err if we don't
|
75
54
|
return nil unless @access_token
|
76
|
-
|
77
|
-
|
78
|
-
# Smoosh the URL components together:
|
79
|
-
base = HTTPS_GRAPH_ENDPOINT
|
80
|
-
path = connection.nil? ? id : File.join(id, connection)
|
81
|
-
href = File.join(base, path)
|
82
|
-
|
83
|
-
# Make our DELETE request and return the results:
|
84
|
-
begin
|
85
|
-
response = Typhoeus::Request.delete(href, :params=>params)
|
86
|
-
data = JSON.parse(response.body)
|
87
|
-
return GraphResponse.new(data)
|
88
|
-
rescue JSON::ParserError => jsone
|
89
|
-
# A JSON.parse on "true" triggers an error, so let's build it straight from body:
|
90
|
-
return GraphResponse.new(response.body)
|
91
|
-
end
|
55
|
+
path = connection.nil? ? id.to_s : File.join(id.to_s, connection.to_s)
|
56
|
+
return request(:delete, path)
|
92
57
|
end
|
93
58
|
|
94
|
-
|
59
|
+
|
95
60
|
def search(query, type, params={})
|
96
|
-
# Inject the access token if we have it and err if we don't
|
97
61
|
return nil unless @access_token
|
98
|
-
params[:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
response = Typhoeus::Request.get(href, :params=>params)
|
107
|
-
data = JSON.parse(response.body)
|
108
|
-
return GraphResponse.new(data)
|
62
|
+
params[:q] = query.to_s
|
63
|
+
params[:type] = type.to_s
|
64
|
+
request(:get, "search", params)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def num_requests
|
69
|
+
@history.length
|
109
70
|
end
|
110
71
|
|
72
|
+
def previous_request
|
73
|
+
@history.last
|
74
|
+
end
|
75
|
+
|
76
|
+
def repeat
|
77
|
+
previous_request.request()
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
|
85
|
+
def request(method, path, params={})
|
86
|
+
api_request = GraphRequest.new(self, method, path, params)
|
87
|
+
@history << api_request
|
88
|
+
return api_request.request()
|
89
|
+
end
|
111
90
|
|
112
91
|
|
113
92
|
end # GraphAPI
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# AWEXOME LABS
|
2
|
+
# DoesOpenGraph
|
3
|
+
#
|
4
|
+
# GraphRequest - A request to the OpenGraph API.
|
5
|
+
#
|
6
|
+
|
7
|
+
module DoesOpenGraph
|
8
|
+
class GraphRequest
|
9
|
+
|
10
|
+
attr_reader :api, :method, :path, :params, :href
|
11
|
+
|
12
|
+
# Build a Request object from its component parts
|
13
|
+
def initialize(api, method, path, params={})
|
14
|
+
@api = api
|
15
|
+
@method = method
|
16
|
+
@path = path
|
17
|
+
@params = params
|
18
|
+
@href = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Perform the request
|
23
|
+
def request
|
24
|
+
base = @api.access_token ? GraphAPI::HTTPS_GRAPH_ENDPOINT : GraphAPI::HTTP_GRAPH_ENDPOINT
|
25
|
+
@href = File.join(base, @path)
|
26
|
+
|
27
|
+
if !%w(get post delete).include?(@method.to_s)
|
28
|
+
raise InvalidRequestMethod.new("Invalid HTTP method #{@method} passed to request") and return nil
|
29
|
+
end
|
30
|
+
|
31
|
+
params[:access_token] = @api.access_token if @api.access_token
|
32
|
+
|
33
|
+
begin
|
34
|
+
response = Typhoeus::Request.send(@method, @href, :params=>@params)
|
35
|
+
puts "RESPONSE RECEIVED FROM FACEBOOK ON REQUEST TO PATH #{@path}:\n#{response.body}\n\n"
|
36
|
+
|
37
|
+
return GraphResponse.new(response.body, self)
|
38
|
+
|
39
|
+
# TODO: Parse known error responses from Facebook, such as:
|
40
|
+
# TODO: {"error":{"message":"Unknown path components: \/status","type":"OAuthException"}}
|
41
|
+
|
42
|
+
rescue Exception => e
|
43
|
+
raise OpenGraphException.new("Error in OpenGraph response: #{e}") and return nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# Repeat the same request with optionally different parameters
|
49
|
+
def repeat(params={})
|
50
|
+
@params.merge(params)
|
51
|
+
request()
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end # GraphRequest
|
56
|
+
end # DoesOpenGraph
|
57
|
+
|
58
|
+
|
59
|
+
|
@@ -7,17 +7,131 @@
|
|
7
7
|
module DoesOpenGraph
|
8
8
|
class GraphResponse
|
9
9
|
|
10
|
-
attr_reader :content, :
|
10
|
+
attr_reader :content, :object, :request
|
11
11
|
|
12
|
-
# Build a Response object from
|
13
|
-
def initialize(
|
14
|
-
@
|
15
|
-
|
12
|
+
# Build a Response object from raw JSON HTTP response
|
13
|
+
def initialize(raw_content, request=nil)
|
14
|
+
@request = request
|
15
|
+
self.update(raw_content)
|
16
16
|
end
|
17
|
-
|
18
|
-
#
|
17
|
+
|
18
|
+
# Update the stored content of this node and parse
|
19
|
+
def update (raw_content)
|
20
|
+
@content = raw_content
|
21
|
+
self.parse
|
22
|
+
end
|
23
|
+
|
24
|
+
# Parse the stored raw content and translate into a usable object
|
25
|
+
def parse
|
26
|
+
begin
|
27
|
+
parsed_content = JSON.parse(@content)
|
28
|
+
@object = parsed_content.is_a?(Hash) ? Hashie::Mash.new(parsed_content) : parsed_content
|
29
|
+
|
30
|
+
rescue JSON::ParserError => parse_error
|
31
|
+
@object = nil
|
32
|
+
if parse_error.message.match("unexpected token")
|
33
|
+
@object = true if @content == "true"
|
34
|
+
@object = false if @content == "false"
|
35
|
+
end
|
36
|
+
if @object.nil?
|
37
|
+
raise InvalidResponseFromFacebook.new("Invalid JSON returned from Facebook: #{parse_error.message}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Update this node from theFetch an updated view of this node
|
44
|
+
def reload
|
45
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
46
|
+
up = request.request()
|
47
|
+
@content = up.content
|
48
|
+
@object = up.object
|
49
|
+
return self
|
50
|
+
end
|
51
|
+
|
52
|
+
# Is this response an error?
|
53
|
+
def error?
|
54
|
+
keys.include?(:error)
|
55
|
+
end
|
56
|
+
|
57
|
+
# What is the error return from Facebook in this response?
|
58
|
+
def error_message
|
59
|
+
@object.error ? @object.error.message : nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Introspect on the connections available to this node
|
63
|
+
def introspect
|
64
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
65
|
+
request.repeat(:metadata=>1)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get a connection of this node
|
69
|
+
def get(connection, params={})
|
70
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
71
|
+
request.api.get(object.id, connection, params)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Post to a connection of this node
|
75
|
+
def post(connection, params={})
|
76
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
77
|
+
request.api.post(object.id, connection, params)
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Load the next page of the response if paging is available
|
82
|
+
def next_page; page("next"); end
|
83
|
+
def previous_page; page("previous"); end
|
84
|
+
|
85
|
+
# Load a specific page of results if available:
|
86
|
+
def page(pg, pp=25)
|
87
|
+
if pg.is_a?(String)
|
88
|
+
if object.paging
|
89
|
+
if page_url = object.paging[pg]
|
90
|
+
data = page_url.match(/\?(\S+)/)[1].split("&").collect{|pair| pair.split("=")}.select{|k,v| k!="access_token"}
|
91
|
+
params = Hash.new
|
92
|
+
data.each {|k,v| params[k.to_sym] = v}
|
93
|
+
return request.repeat(params)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
else
|
97
|
+
return request.repeat(:limit=>pp, :offset=>(pg-1)*pp)
|
98
|
+
end
|
99
|
+
return nil
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# Delete this node from the graph
|
104
|
+
def delete
|
105
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
106
|
+
request.api.delete(object.id)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Like this node, if supported
|
110
|
+
def like
|
111
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
112
|
+
request.api.post(object.id, "likes")
|
113
|
+
end
|
114
|
+
|
115
|
+
# Unlike this node, if supported
|
116
|
+
def unlike
|
117
|
+
raise IncapableOfUpdateMethods.new("Cannot update content without stored request") if request.nil?
|
118
|
+
request.api.delete(object.id, "likes")
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# What keys are available on this OpenGraph node?
|
123
|
+
def keys
|
124
|
+
object.is_a?(Hash) ? object.keys.collect{|k|k.to_sym} : Array.new
|
125
|
+
end
|
126
|
+
|
127
|
+
# Include our return top-level keys in the methods list:
|
128
|
+
def methods()
|
129
|
+
keys + super()
|
130
|
+
end
|
131
|
+
|
132
|
+
# Use method-missing to provide top-level keys of response Hash as methods
|
19
133
|
def method_missing(m, *args, &block)
|
20
|
-
|
134
|
+
object.include?(m.to_s) ? object.send(m.to_s) : super(m, args)
|
21
135
|
end
|
22
136
|
|
23
137
|
end # GraphResponse
|
data/lib/doesopengraph.rb
CHANGED
@@ -3,10 +3,17 @@
|
|
3
3
|
#
|
4
4
|
# DoesOpenGraph - Module definition and loader
|
5
5
|
|
6
|
+
require 'hashie'
|
7
|
+
|
6
8
|
require "doesopengraph"
|
7
9
|
require "doesopengraph/graph_api"
|
10
|
+
require "doesopengraph/graph_request"
|
8
11
|
require "doesopengraph/graph_response"
|
9
|
-
require "doesopengraph/graph_node"
|
10
12
|
|
11
13
|
module DoesOpenGraph
|
14
|
+
|
15
|
+
def self.version
|
16
|
+
Gem.loaded_specs["doesopengraph"].version.to_s
|
17
|
+
end
|
18
|
+
|
12
19
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: doesopengraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- mccolin
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-09-23 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: *id004
|
60
|
-
description:
|
60
|
+
description: Content-type-agnostic library for accessing and manipulating the Facebook OpenGraph with all major methods and search
|
61
61
|
email: info@awexomelabs.com
|
62
62
|
executables: []
|
63
63
|
|
@@ -69,7 +69,7 @@ extra_rdoc_files:
|
|
69
69
|
files:
|
70
70
|
- lib/doesopengraph.rb
|
71
71
|
- lib/doesopengraph/graph_api.rb
|
72
|
-
- lib/doesopengraph/
|
72
|
+
- lib/doesopengraph/graph_request.rb
|
73
73
|
- lib/doesopengraph/graph_response.rb
|
74
74
|
- LICENSE
|
75
75
|
- README.rdoc
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# AWEXOME LABS
|
2
|
-
# DoesOpenGraph
|
3
|
-
#
|
4
|
-
# GraphNode - An instance of an item on the open graph
|
5
|
-
#
|
6
|
-
|
7
|
-
module DoesOpenGraph
|
8
|
-
class GraphNode < GraphResponse
|
9
|
-
|
10
|
-
# Fetch an updated view of this node
|
11
|
-
def reload
|
12
|
-
up = api.node(self.id)
|
13
|
-
@content = up.content
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
# Introspect on the connections available to this node
|
18
|
-
def introspect
|
19
|
-
api.node(self.id, nil, :metadata=>1)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Delete this node from the graph
|
23
|
-
def delete
|
24
|
-
api.delete(self.id)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Like this node, if supported
|
28
|
-
def like
|
29
|
-
api.post(self.id, "likes")
|
30
|
-
end
|
31
|
-
|
32
|
-
# Unlike this node, if supported
|
33
|
-
def unlike
|
34
|
-
api.delete(self.id, "likes")
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
end # GraphNode
|
39
|
-
end # DoesOpenGraph
|
40
|
-
|
41
|
-
|
42
|
-
|