Class: Mogli::Client

Inherits:
Object
  • Object
show all
Includes:
HTTMultiParty, Event, User
Defined in:
lib/mogli/client.rb,
lib/mogli/client/user.rb,
lib/mogli/client/event.rb

Direct Known Subclasses

AppClient

Defined Under Namespace

Modules: Event, User Classes: ClientException, FeedActionRequestLimitExceeded, HTTPException, OAuthAccessTokenException, OAuthException, OAuthUnauthorizedClientException, QueryParseException, SessionInvalidatedDueToPasswordChange, UnrecognizeableClassError

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from User

#user

Methods included from Event

#event

Constructor Details

- (Client) initialize(access_token = nil, expiration = nil)

Returns a new instance of Client



39
40
41
42
43
44
45
# File 'lib/mogli/client.rb', line 39

def initialize(access_token = nil,expiration=nil)
  @access_token = access_token
  # nil expiration means extended access
  expiration = Time.now.to_i + 10*365*24*60*60 if expiration.nil? or expiration == 0
  @expiration = Time.at(expiration)
  @default_params = @access_token ? {:access_token=>access_token} : {}
end

Instance Attribute Details

- (Object) access_token (readonly)

Returns the value of attribute access_token



6
7
8
# File 'lib/mogli/client.rb', line 6

def access_token
  @access_token
end

- (Object) default_params (readonly)

Returns the value of attribute default_params



7
8
9
# File 'lib/mogli/client.rb', line 7

def default_params
  @default_params
end

- (Object) expiration (readonly)

Returns the value of attribute expiration



8
9
10
# File 'lib/mogli/client.rb', line 8

def expiration
  @expiration
end

Class Method Details

+ (Object) access_token_from_access_data(access_data)



98
99
100
101
# File 'lib/mogli/client.rb', line 98

def self.access_token_from_access_data(access_data)
  return nil if access_data.nil?
  access_data['access_token']
end

+ (Object) create_and_authenticate_as_application(client_id, secret)



108
109
110
111
112
113
114
# File 'lib/mogli/client.rb', line 108

def self.create_and_authenticate_as_application(client_id, secret)
  authenticator = Mogli::Authenticator.new(client_id, secret, nil)
  access_data = authenticator.get_access_token_for_application
  client = AppClient.new(access_data)
  client.application_id = client_id
  client
end

+ (Object) create_from_code_and_authenticator(code, authenticator)



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/mogli/client.rb', line 51

def self.create_from_code_and_authenticator(code,authenticator)
  post_data = get(authenticator.access_token_url(code)).parsed_response
  if (response_is_error?(post_data))
    raise_client_exception(post_data)
  end
  parts = post_data.split("&")
  hash = {}
  parts.each do |p| (k,v) = p.split("=")
    hash[k]=CGI.unescape(v)
  end

  if hash["expires"]
    expires = Time.now.to_i + hash["expires"].to_i
  else
    expires = nil
  end

  new(hash["access_token"],expires)
end

+ (Object) create_from_session_key(session_key, client_id, secret)



92
93
94
95
96
# File 'lib/mogli/client.rb', line 92

def self.create_from_session_key(session_key, client_id, secret)
  authenticator = Mogli::Authenticator.new(client_id, secret, nil)
  access_data = authenticator.get_access_token_for_session_key(session_key)
  new(access_token_from_access_data(access_data),expiration_from_access_data(access_data))
end

+ (Object) expiration_from_access_data(access_data)



103
104
105
106
# File 'lib/mogli/client.rb', line 103

def self.expiration_from_access_data(access_data)
  return nil if access_data.nil? or access_data['expires'].nil?
  Time.now.to_i + access_data['expires'].to_i
end

+ (Object) raise_client_exception(post_data)



71
72
73
# File 'lib/mogli/client.rb', line 71

def self.raise_client_exception(post_data)
  raise_error_by_type_and_message(post_data["error"]["type"], post_data["error"]["message"])
end

+ (Object) raise_error_by_type_and_message(type, message)



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/mogli/client.rb', line 75

def self.raise_error_by_type_and_message(type, message)
  if type == 'OAuthException' && message =~ /Feed action request limit reached/
    raise FeedActionRequestLimitExceeded.new(message)
  elsif type == 'OAuthException' && message =~ /The session has been invalidated because the user has changed the password/
    raise SessionInvalidatedDueToPasswordChange.new(message)
  elsif Mogli::Client.const_defined?(type)
    raise Mogli::Client.const_get(type).new(message)
  else
    raise ClientException.new("#{type}: #{message}")
  end
end

+ (Boolean) response_is_error?(post_data)

Returns:

  • (Boolean)


87
88
89
90
# File 'lib/mogli/client.rb', line 87

def self.response_is_error?(post_data)
   post_data.kind_of?(Hash) and
   !post_data["error"].empty?
end

Instance Method Details

- (Object) api_path(path)



27
28
29
# File 'lib/mogli/client.rb', line 27

def api_path(path)
  "https://graph.facebook.com/#{path}"
end

- (Object) capitalize_if_required(string)



223
224
225
# File 'lib/mogli/client.rb', line 223

def capitalize_if_required(string)
  string.downcase == string ? string.capitalize : string
end

- (Object) constantize_string(klass)



227
228
229
# File 'lib/mogli/client.rb', line 227

def constantize_string(klass)
  klass.is_a?(String) ? Mogli.const_get(capitalize_if_required(klass)) : klass
end

- (Object) create_instance(klass, data)



215
216
217
218
219
220
221
# File 'lib/mogli/client.rb', line 215

def create_instance(klass,data)
  klass_to_create =  determine_class(klass,data)
  if klass_to_create.nil?
    raise UnrecognizeableClassError.new("unable to recognize klass for #{klass.inspect} => #{data.inspect}")
  end
  klass_to_create.new(data,self)
end

- (Object) delete(path)



132
133
134
# File 'lib/mogli/client.rb', line 132

def delete(path)
  self.class.delete(api_path(path),:query=>default_params)
end

- (Object) determine_class(klass_or_klasses, data)



231
232
233
234
235
236
237
238
# File 'lib/mogli/client.rb', line 231

def determine_class(klass_or_klasses,data)
  if data.respond_to?(:has_key?) && data.has_key?('type') &&
                                     klass_or_klasses == Mogli::Model
    return constantize_string(data['type'])
  end
  klasses = Array(klass_or_klasses).map { |k| constantize_string(k)}
  klasses.detect {|klass| klass.recognize?(data)} || klasses.first
end

- (Object) exchange_access_token(client_id, secret)



121
122
123
124
125
# File 'lib/mogli/client.rb', line 121

def exchange_access_token(client_id, secret)
  authenticator = Mogli::Authenticator.new(client_id, secret, nil)
  results = authenticator.extend_access_token(@access_token)
  self.class.new(results["access_token"],Time.now.to_i+results["expires"].to_i)
end

- (Boolean) expired?

Returns:

  • (Boolean)


47
48
49
# File 'lib/mogli/client.rb', line 47

def expired?
  expiration and expiration < Time.now
end

- (Boolean) extended?

Returns:

  • (Boolean)


116
117
118
119
# File 'lib/mogli/client.rb', line 116

def extended?
  (expiration.to_i - Time.now.to_i) > 24*60*60

end

- (Object) extract_fetching_array(hash, klass)



193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/mogli/client.rb', line 193

def extract_fetching_array(hash,klass)
  f = Mogli::FetchingArray.new
  f.concat(hash["data"])
  f.client = self
  f.classes = Array(klass)
  f.total_count = hash["count"]
  if paging=hash["paging"]
    f.next_url = URI.encode paging["next"] unless paging["next"].nil?
    f.previous_url = URI.encode paging["previous"] unless paging["previous"].nil?
  end
  f
end

- (Object) extract_hash_or_array(hash_or_array, klass)

protected



177
178
179
180
181
182
183
184
185
186
# File 'lib/mogli/client.rb', line 177

def extract_hash_or_array(hash_or_array,klass)
  hash_or_array = hash_or_array.parsed_response if hash_or_array.respond_to?(:parsed_response)
  return nil if hash_or_array == false
  return []  if hash_or_array == {"count" => 0}
  return hash_or_array if hash_or_array.nil? or hash_or_array.kind_of?(Array)
  return extract_fetching_array(hash_or_array,klass) if is_fetching_array?(hash_or_array)
  # Facebook doesn't return numbers or booleans in an object or list
  # container; this will catch the number, "true" and "false" response case
  return hash_or_array
end

- (Object) fields_to_serialize



249
250
251
# File 'lib/mogli/client.rb', line 249

def fields_to_serialize
  [:access_token,:default_params,:expiration]
end

- (Object) fql_multiquery(queries)



147
148
149
150
# File 'lib/mogli/client.rb', line 147

def fql_multiquery(queries)
  data = self.class.post(fql_multiquery_path,:body=>default_params.merge({:queries=>queries.to_json,:format=>"json"}))
  map_data(data)
end

- (Object) fql_multiquery_path



35
36
37
# File 'lib/mogli/client.rb', line 35

def fql_multiquery_path
  "https://api.facebook.com/method/fql.multiquery"
end

- (Object) fql_path



31
32
33
# File 'lib/mogli/client.rb', line 31

def fql_path
  "https://graph.facebook.com/fql"
end

- (Object) fql_query(query, klass = nil, format = "json")



141
142
143
144
145
# File 'lib/mogli/client.rb', line 141

def fql_query(query,klass=nil,format="json")
  data = self.class.get(fql_path,:query=>default_params.merge({:q=>query,:format=>format})).parsed_response
  return data unless format=="json"
  map_data(data["data"],klass)
end

- (Object) get_and_map(path, klass = nil, body_args = {})



152
153
154
155
156
# File 'lib/mogli/client.rb', line 152

def get_and_map(path,klass=nil,body_args = {})
  data = self.class.get(api_path(path),:query=>default_params.merge(body_args))
  data = data.values if body_args.key?(:ids) && !data.key?('error')
  map_data(data,klass)
end

- (Object) get_and_map_url(url, klass = nil, body_args = {})



158
159
160
161
# File 'lib/mogli/client.rb', line 158

def get_and_map_url(url,klass=nil,body_args = {})
  data = self.class.get(url,:query=>default_params.merge(body_args))
  map_data(data,klass)
end

- (Boolean) is_fetching_array?(hash)

Returns:

  • (Boolean)


188
189
190
191
# File 'lib/mogli/client.rb', line 188

def is_fetching_array?(hash)
  return false unless hash.respond_to? :has_key?
  hash.has_key?("data") and hash["data"].instance_of?(Array)
end

- (Object) map_data(data, klass = nil)



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/mogli/client.rb', line 163

def map_data(data,klass=nil)
  raise_error_if_necessary(data)
  hash_or_array = extract_hash_or_array(data,klass)
  if hash_or_array.is_a?(Array) && hash_or_array.size == 2 && hash_or_array[1].is_a?(Hash) && hash_or_array[1]['body']
      # responses from batch queries are buried inside a
      # completely different data structure
      hash_or_array = JSON.parse(hash_or_array[1]['body'].first).values
  end
  hash_or_array = map_to_class(hash_or_array,klass) if klass
  hash_or_array
end

- (Object) map_to_class(hash_or_array, klass)



206
207
208
209
210
211
212
213
# File 'lib/mogli/client.rb', line 206

def map_to_class(hash_or_array,klass)
  return nil if !hash_or_array
  if hash_or_array.kind_of?(Array)
    hash_or_array.map! {|i| create_instance(klass,i)}
  else
    hash_or_array = create_instance(klass,hash_or_array)
  end
end

- (Object) marshal_dump

Only serialize the bare minimum to recreate the session.



259
260
261
# File 'lib/mogli/client.rb', line 259

def marshal_dump#:nodoc:
  fields_to_serialize.map{|field| send(field)}
end

- (Object) marshal_load(variables)

Only serialize the bare minimum to recreate the session.



254
255
256
# File 'lib/mogli/client.rb', line 254

def marshal_load(variables)#:nodoc:
  fields_to_serialize.each_with_index{|field, index| instance_variable_set("@#{field}", variables[index])}
end

- (Object) post(path, klass, body_args)



127
128
129
130
# File 'lib/mogli/client.rb', line 127

def post(path,klass,body_args)
  data = self.class.post(api_path(path),:body=>default_params.merge(body_args))
  map_data(data,klass)
end

- (Object) raise_error_if_necessary(data)

Raises:



240
241
242
243
244
245
246
247
# File 'lib/mogli/client.rb', line 240

def raise_error_if_necessary(data)
  if data.kind_of?(Hash)
    if data.keys.size == 1 and data["error"]
      self.class.raise_error_by_type_and_message(data["error"]["type"], data["error"]["message"])
    end
  end
  raise HTTPException if data.respond_to?(:code) and data.code != 200 and data.code != 400
end

- (Object) subscribe_to_model(model, options)



136
137
138
139
# File 'lib/mogli/client.rb', line 136

def subscribe_to_model(model,options)
  options_to_send=options.dup
  self.class.post("http://")
end

- (Object) to_yaml(opts = {})

Only serialize the bare minimum to recreate the session.



264
265
266
267
268
269
270
271
272
# File 'lib/mogli/client.rb', line 264

def to_yaml( opts = {} )#nodoc
  YAML::quick_emit(self.object_id, opts) do |out|
    out.map(taguri) do |map|
      fields_to_serialize.each do |field|
        map.add(field, send(field))
      end
    end
  end
end