Class: A4Tools::AcresClient

Inherits:
Object
  • Object
show all
Includes:
EventGenerator
Defined in:
lib/acres_client.rb

Direct Known Subclasses

CachingClient, UsherClient

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from EventGenerator

#on, #passthrough, #signal

Constructor Details

#initialize(destination, username = nil, password = nil) ⇒ AcresClient

Returns a new instance of AcresClient.



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
191
192
193
194
195
# File 'lib/acres_client.rb', line 162

def initialize(destination, username=nil, password=nil)
  if destination.is_a? String then
    @uri = URI(destination)
  else
    @uri = URI(destination[:url] + destination[:ctx] + "/json?wrap")
  end

  @username = username
  @password = password
  @history = []

  case @uri.scheme
  when 'http', 'https'
    @transport = HTTPTransporter.new(@uri)
  when 'ws', 'wss'
    @transport = WebSocketTransporter.new(@uri)
  end

  passthrough(@transport)
  @transport.on(:message) { |trigger, message| snoop_token(message) }
  @transport.on(:message) { |trigger, message| add_message_to_history(:server, message) }
  @transport.on(:sent) { |trigger, message| add_message_to_history(:client, message) }
  @transport.on(:connect) { |trigger, message| @ready = true }
  @transport.on(:disconnect) do |trigger, message|
    @ready = false
    @start_time = nil
  end

  @connected = false
  @connect_time = nil
  @start_time = nil
  @authenticated = false
  @token = nil
end

Instance Attribute Details

#connect_timeObject (readonly)

Returns the value of attribute connect_time.



159
160
161
# File 'lib/acres_client.rb', line 159

def connect_time
  @connect_time
end

#connectedObject (readonly)

Returns the value of attribute connected.



159
160
161
# File 'lib/acres_client.rb', line 159

def connected
  @connected
end

#historyObject (readonly)

Returns the value of attribute history.



159
160
161
# File 'lib/acres_client.rb', line 159

def history
  @history
end

#passwordObject

Returns the value of attribute password.



160
161
162
# File 'lib/acres_client.rb', line 160

def password
  @password
end

#readyObject (readonly)

Returns the value of attribute ready.



159
160
161
# File 'lib/acres_client.rb', line 159

def ready
  @ready
end

#server_infoObject (readonly)

Returns the value of attribute server_info.



159
160
161
# File 'lib/acres_client.rb', line 159

def server_info
  @server_info
end

#start_timeObject (readonly)

Returns the value of attribute start_time.



159
160
161
# File 'lib/acres_client.rb', line 159

def start_time
  @start_time
end

#tokenObject (readonly)

Returns the value of attribute token.



159
160
161
# File 'lib/acres_client.rb', line 159

def token
  @token
end

#uriObject (readonly)

Returns the value of attribute uri.



159
160
161
# File 'lib/acres_client.rb', line 159

def uri
  @uri
end

#usernameObject

Returns the value of attribute username.



160
161
162
# File 'lib/acres_client.rb', line 160

def username
  @username
end

#versionObject

Returns the value of attribute version.



160
161
162
# File 'lib/acres_client.rb', line 160

def version
  @version
end

Instance Method Details

#add_message_to_history(sender, message, timestamp = nil) ⇒ Object



197
198
199
200
201
# File 'lib/acres_client.rb', line 197

def add_message_to_history(sender, message, timestamp=nil)
  timestamp ||= Time.now
  @start_time ||= timestamp
  history.push({ time: timestamp, sender: sender, message: (symbolify(JSON.parse(message)) rescue nil), raw:message })
end

#app_infoObject



360
361
362
363
364
# File 'lib/acres_client.rb', line 360

def app_info
  info = ObjectBuilder[:app_info_for_script].value
  info[:currentTalkVersion] = @version unless @version.nil?
  info
end

#attempt_snoop(result) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/acres_client.rb', line 214

def attempt_snoop(result)
  if not(result.nil?) and result.has_key? :tok and result.has_key? :serverInfo then
    # this is a connection token
    @connected = true
    @token = result[:tok] if result.has_key? :tok
    @server_info = result[:serverInfo] if result.has_key? :serverInfo
    signal(:connect)
    true
  else
    false
  end
end

#authenticate(username = nil, password = nil) ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/acres_client.rb', line 256

def authenticate(username=nil, password=nil)
  return nil unless connect_if_needed

  request = {
    tok: @token,
    username: username || @username,
    password: make_password(password || @password),
    automaticReconnect: false
  }

  result = send_message(wrapped_message("login", "com.acres4.common.info.ClientLoginRequest", request))
  response = response_body(result)
  @authenticated = not(response.nil?)
  response
end

#authenticate_if_needed(username = nil, password = nil) ⇒ Object



272
273
274
275
276
# File 'lib/acres_client.rb', line 272

def authenticate_if_needed(username=nil, password=nil)
  return true if @authenticated
  return true unless authenticate(username, password).nil?
  return false
end

#connectObject



235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/acres_client.rb', line 235

def connect
  return nil unless transport_connect

  request = {
    appInfo: app_info,
    deviceInfo: device_info
  }

  result = send_message(wrapped_message("connect", "com.acres4.common.info.ConnectionRequest", request))
  response = response_body(result)
  return nil unless response

  response
end

#connect_if_neededObject



250
251
252
253
254
# File 'lib/acres_client.rb', line 250

def connect_if_needed
  return true if @connected
  return true unless connect.nil?
  return false
end

#device_infoObject



366
367
368
# File 'lib/acres_client.rb', line 366

def device_info
  ObjectBuilder[:device_info_for_system].value
end

#disconnectObject



231
232
233
# File 'lib/acres_client.rb', line 231

def disconnect
  @transport.disconnect
end

#empty_query(method, interface = nil) ⇒ Object



338
339
340
# File 'lib/acres_client.rb', line 338

def empty_query(method, interface=nil)
  jsonrpc_message(method, interface)
end

#inject_token(message, force = false, type = nil) ⇒ Object



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/acres_client.rb', line 306

def inject_token(message, force=false, type=nil)
  return nil if message.nil?
  return message unless force or message[:tok].nil?
  type ||= talk.guess_class(message)
  unless type.nil? then
    cls = talk.class_named(type)
    has_tok = (cls[:field].select do |f|
      is_token_class = talk.name_matches?("com.acres4.common.info.ConnectionToken", f[:type].first)
      f[:name] == "tok" and is_token_class
    end).length >= 1

    message[:tok] = @token if has_tok
  end

  message
end

#jsonrpc_message(method, interface = nil, cls = nil, body = {}) ⇒ Object



323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/acres_client.rb', line 323

def jsonrpc_message(method, interface=nil, cls=nil, body={})
  body[:__class] = (cls || talk.guess_class(body)) unless body.nil?

  json = {
    __class:"com.acres4.common.info.JSONRPCRequest",
    method:method,
    params:body,
    id:next_msg_id,
    jsonrpc:"2.0"
  }

  json[:intf] = interface unless interface.nil? # don't even include it if we didn't specify it
  json
end

#make_password(password) ⇒ Object



278
279
280
281
282
283
284
# File 'lib/acres_client.rb', line 278

def make_password(password)
  {
    algorithm:"CLEARTEXT",
    contents:password,
    parameters:[]
  }
end

#next_msg_idObject



286
287
288
# File 'lib/acres_client.rb', line 286

def next_msg_id
  @msg_id = @msg_id.nil? ? 0 : @msg_id + 1
end

#response_body(result) ⇒ Object



347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/acres_client.rb', line 347

def response_body(result)
  return nil unless result.code.to_i >= 200 and result.code.to_i < 300

  jsonrpc = JSON.parse(result.body)
  return nil unless jsonrpc["jsonrpc"] == "2.0"
  return nil unless jsonrpc["error"].nil?
  return nil if jsonrpc["result"].nil?

  return symbolify jsonrpc["result"]["body"] unless jsonrpc["result"]["body"].nil?

  return symbolify jsonrpc["result"]
end

#send_message(message) ⇒ Object



342
343
344
345
# File 'lib/acres_client.rb', line 342

def send_message(message)
  message = message.to_json unless message.is_a? String
  @transport.send_message(message)
end

#snoop_token(message) ⇒ Object



203
204
205
206
207
208
209
210
211
212
# File 'lib/acres_client.rb', line 203

def snoop_token(message)
  begin
    response = symbolify JSON.parse(message)
    result = response[:result]
    return if attempt_snoop(result)
    attempt_snoop(result[:body]) unless result.nil? or result[:body].nil?
  rescue
    ""
  end
end

#transport_connectObject



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

def transport_connect
  @transport.connect
end

#wrapped_message(method, cls, body) ⇒ Object



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/acres_client.rb', line 290

def wrapped_message(method, cls, body)
  cls ||= talk.guess_class(body)
  body[:__class] = cls.to_s;
  body[:tok] = @token unless @token.nil?

  wrapper = {
    className:cls,
    body:body,
    namedObjectEncodingType:0,
    serializedEncoding:nil,
    __class:"com.acres4.common.info.NamedObjectWrapper"
  }

  jsonrpc_message(method, nil, "com.acres4.common.info.NamedObjectWrapper", wrapper)
end