fb_util 0.0.7

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.
Files changed (2) hide show
  1. data/lib/fb_util.rb +199 -0
  2. metadata +62 -0
data/lib/fb_util.rb ADDED
@@ -0,0 +1,199 @@
1
+ require 'mechanize'
2
+
3
+ class FBUtil
4
+ @graph_url = nil
5
+ @access_token = nil
6
+ @feed = nil
7
+ @account_info = nil
8
+ @debug = nil
9
+
10
+ def initialize(access_token, debug = false)
11
+ @debug = debug
12
+ @graph_url = 'https://graph.facebook.com'
13
+ @access_token = access_token
14
+ if @access_token.blank? && !Rails.nil?
15
+ Rails.logger.info 'An access token is required for this class to work'
16
+ end
17
+ end
18
+
19
+ # Get the basic account information from facebook
20
+ def get_account_info
21
+ @account_info ||= get_request('/me')
22
+ end
23
+
24
+ # Get the users feed
25
+ def get_feed
26
+ @feed ||= get_request('/me/feed')
27
+ # I have no idea why sometimes it uses the data index and sometimes it doesn't....
28
+ begin
29
+ return @feed['data']
30
+ rescue
31
+ return @feed
32
+ end
33
+ end
34
+
35
+ # Post a message to the users wall
36
+ # message: text of the message to be posted. Links will not be converted to click able links. Use post_link to post a clickable link (including video)
37
+ def post_status(message)
38
+ post_request('/me/feed', {message: message})
39
+ end
40
+
41
+ # Post a picture to the users wall
42
+ # picture_path: the actual file path to the image (no urls)
43
+ # message: the message to be attached to the image if any. Can be null or empty.
44
+ # post_to_feed: true (by default) if you want the picture to be posted to the users wall, false if you want it hidden. This isn't 100% tested.
45
+ def post_picture(picture_path, message, post_to_feed=true)
46
+ File.open(picture_path.to_s.gsub('%20', '\ ').gsub('(', '\(').gsub(')', '\)'), 'rb') do |binary_image|
47
+ if post_to_feed
48
+ post_request('/me/photos', {source: binary_image, message: message})
49
+ else
50
+ post_request('/me/photos', {source: binary_image, message: message, no_story: 'true'})
51
+ end
52
+ end
53
+ end
54
+
55
+ # Set an already existing image to be the users cover image
56
+ # picture_id: the facebook id of the image to use as the users cover image. This currently doesn't allow for an offset, but this will be available in the next version.
57
+ def set_as_cover_image(picture_id)
58
+ post_request('/me', {cover: picture_id, no_feed_story: 'true'})
59
+ end
60
+
61
+ # Post a clickable link to a users feed (works for youtube videos as well)
62
+ # link: the link (beginning with http:// or https://) that will be displayed in the users feed
63
+ # message: the message to be posted with the link on the feed page
64
+ def post_link(link, message)
65
+ post_request('/me/feed', {link: link, message: message})
66
+ end
67
+
68
+ # Post a reply to a status that is already existing on facebook
69
+ # status_id: the facebook id of the status to reply to
70
+ # message: the message to use in the reply
71
+ def reply_to_status(status_id, message)
72
+ post_request('/' + status_id + '/comments', {message: message})
73
+ end
74
+
75
+ # Delete a status
76
+ # status_id: the facebook id of the status to delete
77
+ def delete_status(status_id)
78
+ delete_request('/' + status_id)
79
+ end
80
+
81
+ # Get statuses from facebook page/account
82
+ def get_statuses
83
+ @statuses ||= get_request('/me/statuses')
84
+ # I have no idea why sometimes it uses the data index and sometimes it doesn't....
85
+ begin
86
+ return @statuses['data']
87
+ rescue
88
+ return @statuses
89
+ end
90
+ end
91
+
92
+ # Get the insights of a page (**this doesn't work for profiles**)
93
+ def get_insights
94
+ @insights ||= get_request('/me/insights')
95
+ begin
96
+ return @insights['data']
97
+ rescue
98
+ return @insights
99
+ end
100
+ end
101
+
102
+ # Get any fql request
103
+ # Fql cannot be cached since it might be used more than once to gather different data without creating a new facebook api class
104
+ def get_fql(fql)
105
+ get_request('/fql?q=' + CGI.escape(fql))['data']
106
+ end
107
+
108
+ # Get pages associated with the account
109
+ def get_pages
110
+ @page ||= get_request('/me/accounts')['data']
111
+ end
112
+
113
+ private
114
+ # Execute a get request against the facebook endpoint requested
115
+ # end_point: anything in the url after the graph.facebook.com i.e. /me/accounts
116
+ def get_request(end_point)
117
+ execute_request(end_point, 'get')
118
+ end
119
+
120
+ # Send data to the facebook endpoint requested
121
+ # end_point: anything in the url after the graph.facebook.com i.e. /me/accounts
122
+ # parameters: the information to be sent to facebook in a hash
123
+ def post_request(end_point, parameters)
124
+ execute_request(end_point, 'post', parameters)
125
+ end
126
+
127
+ # Delete end point from facebook
128
+ def delete_request(end_point)
129
+ execute_request(end_point, 'delete')
130
+ end
131
+
132
+ # The actual request send to facebook
133
+ # end_point: anything in the url after the graph.facebook.com i.e. /me/accounts
134
+ # method: the HTTP method used to send or receive information from facebook
135
+ # parameters: the information to be send to facebook in a hash
136
+ def execute_request(end_point, method, parameters = {})
137
+ agent = Mechanize.new
138
+ response = nil
139
+ begin
140
+ if end_point.include? '?'
141
+ url = @graph_url + end_point + '&access_token=' + @access_token
142
+ else
143
+ url = @graph_url + end_point + '?access_token=' + @access_token
144
+ end
145
+ if method == 'get'
146
+ response = agent.get(url)
147
+ elsif method == 'delete'
148
+ response = agent.get(url + '&method=delete')
149
+ elsif method == 'post'
150
+ response = agent.post(url, parameters)
151
+ end
152
+ if @debug && !Rails.nil?
153
+ # Echo the response if we are in development mode
154
+ if Rails.env.development?
155
+ Rails.logger.info 'FB: ' + method.capitalize + end_point
156
+ # Rails.logger.info 'FB Response: ' + response.body
157
+ end
158
+ end
159
+ return (JSON.parse response.body)
160
+ rescue Exception => e
161
+ if !Rails.nil?
162
+ Rails.logger.info e.page.body
163
+ Rails.logger.info 'Raw exception: ' + e.message
164
+ if @debug
165
+ if !(method == 'post')
166
+ Rails.logger.info 'FB: Error executing ' + method + ' request for "' + end_point + '"'
167
+ else
168
+ Rails.logger.info 'FB: Error executing ' + method + ' request for "' + end_point + '" with parameters: ' + parameters.inspect
169
+ end
170
+ end
171
+ end
172
+ return []
173
+ end
174
+ end
175
+
176
+ # These are the methods that don't need to be called with an instanciated class because they don't need an access token
177
+ class << self
178
+ def base64_url_decode(encoded_url)
179
+ encoded_url += '=' * (4 - encoded_url.length.modulo(4))
180
+ Base64.decode64(encoded_url.gsub('-', '+').gsub('_', '/'))
181
+ end
182
+
183
+ def parse_signed_request(signed_request, application_secret, max_age = 3600)
184
+ encoded_signature, encoded_json = signed_request.split('.', 2)
185
+ json = JSON.parse(base64_url_decode(encoded_json))
186
+ encryption_algorithm = json['algorithm']
187
+
188
+ if encryption_algorithm != 'HMAC-SHA256'
189
+ raise 'Unsupported encryption algorithm.'
190
+ elsif json['issued_at'] < Time.now.to_i - max_age
191
+ raise 'Signed request too old.'
192
+ elsif base64_url_decode(encoded_signature) != OpenSSL::HMAC.hexdigest('sha256', application_secret, encoded_json).split.pack('H*')
193
+ raise 'Invalid signature.'
194
+ end
195
+
196
+ return json
197
+ end
198
+ end
199
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fb_util
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brennon Loveless
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mechanize
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.3'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.3'
30
+ description: A quick utility class to work with the facebook graph api and misc facebook
31
+ functions
32
+ email: brennon@fritzandandre.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/fb_util.rb
38
+ homepage: http://rubygems.org/gems/fb_util
39
+ licenses: []
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 1.8.24
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: Oh my simple facebook util
62
+ test_files: []