Class: Facebook::GraphClient

Inherits:
Object
  • Object
show all
Defined in:
lib/facebook-graphclient.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(facebook_settings = {}) ⇒ GraphClient

Returns a new instance of GraphClient.



19
20
21
22
23
24
25
26
27
# File 'lib/facebook-graphclient.rb', line 19

def initialize facebook_settings = {}
  @app_id       = facebook_settings[:app_id]
  @api_key      = facebook_settings[:api_key]
  @secret       = facebook_settings[:secret]

  @cookie = get_user_cookie facebook_settings[:cookies]
  @access_token = facebook_settings[:access_token] || @cookie['access_token']
  @session = Patron::Session.new
end

Instance Attribute Details

#access_tokenObject

Returns the value of attribute access_token.



17
18
19
# File 'lib/facebook-graphclient.rb', line 17

def access_token
  @access_token
end

#api_keyObject (readonly)

Returns the value of attribute api_key.



16
17
18
# File 'lib/facebook-graphclient.rb', line 16

def api_key
  @api_key
end

#app_idObject (readonly)

Returns the value of attribute app_id.



16
17
18
# File 'lib/facebook-graphclient.rb', line 16

def app_id
  @app_id
end

#secretObject (readonly)

Returns the value of attribute secret.



16
17
18
# File 'lib/facebook-graphclient.rb', line 16

def secret
  @secret
end

Instance Method Details

#[](k) ⇒ Object



124
125
126
# File 'lib/facebook-graphclient.rb', line 124

def [] k
  params[k]
end

#api(action, method, query_params = {}) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/facebook-graphclient.rb', line 46

def api action, method, query_params = {}
  query_params[:access_token] ||= @access_token
  query_string = '?' + query_params.map { |k,v| "#{k}=#{v}" }.join("&") unless query_params.empty?
  query_string ||= ''

  tries = 0
  begin
    raw_response = @session.send(action, GRAPH_URL + method + query_string)
  rescue Patron::HostResolutionError, Patron::ConnectionFailed
    retry if tries < 5
    tries += 1
  end

  # TODO: Handle photo requests, which return photo data and not JSON

  if raw_response.headers['Content-Type'] =~ /text\/javascript/
    # We have JSON
    json = ["false", '', nil].include?(raw_response.body) ? '{}' : raw_response.body
    response = Yajl::Parser.parse(json)

    if e = response['error']
      error = FacebookError.new(e['message'])
      error.data = e
      raise error
    else
      response
    end
  end
end

#fql(query) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/facebook-graphclient.rb', line 76

def fql query
  query_params = {
    :access_token => @access_token,
    :format => 'json',
    :query => Rack::Utils.escape(query)
  }

  query_string = '?' + query_params.map { |k,v| "#{k}=#{v}" }.join("&") unless query_params.empty?

  tries = 0
  begin
    raw_response = @session.get("https://api.facebook.com/method/fql.query" + query_string)
  rescue Patron::HostResolutionError, Patron::ConnectionFailed
    retry if tries < 5
    tries += 1
  end

  json = ["false", '', nil].include?(raw_response.body) ? '{}' : raw_response.body
  response = Yajl::Parser.parse(json)

  if e = response.first['error']
    error = FacebookError.new(e['message'])
    error.data = e
    raise error
  else
    response
  end
end


29
30
31
32
33
34
35
36
# File 'lib/facebook-graphclient.rb', line 29

def get_user_cookie cookies
  if cookies and cookie = cookies["fbs_#{@app_id}"]
    cookie = cookie[1..-2] if cookie[0..0] == '"'
    Rack::Utils.parse_nested_query(cookie)
  else
    {}
  end
end

#paramsObject



128
129
130
# File 'lib/facebook-graphclient.rb', line 128

def params
  valid? ? @params : {}
end

#rest(method, opts = {}) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/facebook-graphclient.rb', line 132

def rest(method, opts = {})
  if method == 'photos.upload'
    image = opts.delete :image
  end

  opts = { :api_key => self.api_key,
           :call_id => Time.now.to_f,
           :format => 'JSON',
           :v => '1.0',
           :access_token => @access_token,
           :session_key => %w[ photos.upload ].include?(method) ? nil : params[:session_key],
           :method => method }.merge(opts)

  args = opts.map{ |k,v|
                   next nil unless v

                   "#{k}=" + case v
                             when Hash
                               Yajl::Encoder.encode(v)
                             when Array
                               if k == :tags
                                 Yajl::Encoder.encode(v)
                               else
                                 v.join(',')
                               end
                             else
                               v.to_s
                             end
                 }.compact.sort

  sig = Digest::MD5.hexdigest(args.join+self.secret)

  if method == 'photos.upload'
    data = MimeBoundary
    data += opts.merge(:sig => sig).inject('') do |buf, (key, val)|
      if val
        buf << (MimePart % [key, val])
      else
        buf
      end
    end
    data += MimeImage % ['upload.jpg', 'jpg', image.respond_to?(:read) ? image.read : image]
  else
    data = Array["sig=#{sig}", *args.map{|a| a.gsub('&','%26').gsub('+','%2B') }].join('&')
  end

  raw_response = @session.post(API_URL + method, data)

  json = ["false", '', nil].include?(raw_response.body) ? '{}' : raw_response.body
  response = Yajl::Parser.parse(json)

  if response.is_a?(Hash) and response.has_key?('error_code')
    error = FacebookError.new(response['error_msg'])
    error.data = response
    raise error
  else
    response
  end
end

#valid?Boolean

Returns:

  • (Boolean)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/facebook-graphclient.rb', line 105

def valid?
  return false if @cookie.nil?

  if @is_valid.nil?
    vars = @cookie.dup

    good_sig = vars.delete 'sig'
    sig = Digest::MD5.hexdigest(vars.sort.map { |k,v| "#{k}=#{v}" }.compact.join + @secret)

    if @is_valid = (sig == good_sig)
      @params = vars
    else
      @params = {}
    end
  end

  @is_valid
end