class Eventflit::Client

Attributes

app_id[RW]
connect_timeout[W]
host[RW]
http_proxy[R]
keep_alive_timeout[W]
key[RW]
notification_host[RW]
notification_scheme[RW]
port[RW]
proxy[R]
receive_timeout[W]
scheme[RW]
secret[RW]
send_timeout[W]

Public Class Methods

from_env(key = 'EVENTFLIT_URL') click to toggle source

Loads the configuration from an url in the environment

# File lib/eventflit/client.rb, line 13
def self.from_env(key = 'EVENTFLIT_URL')
  url = ENV[key] || raise(ConfigurationError, key)
  from_url(url)
end
from_url(url) click to toggle source

Loads the configuration from a url

# File lib/eventflit/client.rb, line 19
def self.from_url(url)
  client = new
  client.url = url
  client
end
new(options = {}) click to toggle source
# File lib/eventflit/client.rb, line 25
def initialize(options = {})
  default_options = {
    :scheme => 'http',
    :port => 80,
  }
  merged_options = default_options.merge(options)

  if options.has_key?(:host)
    merged_options[:host] = options[:host]
  elsif options.has_key?(:cluster)
    merged_options[:host] = "api-#{options[:cluster]}.eventflit.com"
  else
    merged_options[:host] = "service.eventflit.com"
  end

  # TODO: Change host name when finalized
  merged_options[:notification_host] =
    options.fetch(:notification_host, "push.eventflit.com")

  merged_options[:notification_scheme] =
    options.fetch(:notification_scheme, "https")

  @scheme, @host, @port, @app_id, @key, @secret, @notification_host, @notification_scheme =
    merged_options.values_at(
      :scheme, :host, :port, :app_id, :key, :secret, :notification_host, :notification_scheme
    )

  @http_proxy = nil
  self.http_proxy = options[:http_proxy] if options[:http_proxy]

  # Default timeouts
  @connect_timeout = 5
  @send_timeout = 5
  @receive_timeout = 5
  @keep_alive_timeout = 30
end

Public Instance Methods

[](channel_name)
Alias for: channel
authenticate(channel_name, socket_id, custom_data = nil) click to toggle source

Generate the expected response for an authentication endpoint. See docs.eventflit.com/authenticating_users for details.

@example Private channels

render :json => Eventflit.authenticate('private-my_channel', params[:socket_id])

@example Presence channels

render :json => Eventflit.authenticate('presence-my_channel', params[:socket_id], {
  :user_id => current_user.id, # => required
  :user_info => { # => optional - for example
    :name => current_user.name,
    :email => current_user.email
  }
})

@param socket_id [String] @param custom_data [Hash] used for example by private channels

@return [Hash]

@raise [Eventflit::Error] if channel_name or socket_id are invalid

@private Custom data is sent to server as JSON-encoded string

# File lib/eventflit/client.rb, line 357
def authenticate(channel_name, socket_id, custom_data = nil)
  channel_instance = channel(channel_name)
  channel_instance.authenticate(socket_id, custom_data)
end
authentication_token() click to toggle source

@private Returns the authentication token for the client

# File lib/eventflit/client.rb, line 63
def authentication_token
  raise ConfigurationError, :key unless @key
  raise ConfigurationError, :secret unless @secret
  Pusher::Signature::Token.new(@key, @secret)
end
channel(channel_name) click to toggle source

Return a convenience channel object by name that delegates operations on a channel. No API request is made.

@example

Eventflit['my-channel']

@return [Channel] @raise [Eventflit::Error] if the channel name is invalid.

Channel names should be less than 200 characters, and
should not contain anything other than letters, numbers, or the
characters "_\-=@,.;"
# File lib/eventflit/client.rb, line 213
def channel(channel_name)
  Channel.new(nil, channel_name, self)
end
Also aliased as: []
channel_info(channel_name, params = {}) click to toggle source

Request info for a specific channel

GET /apps//channels/

@param channel_name [String] Channel name (max 200 characters) @param params [Hash] Hash of parameters for the API - see REST API docs

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 246
def channel_info(channel_name, params = {})
  get("/channels/#{channel_name}", params)
end
channel_users(channel_name, params = {}) click to toggle source

Request info for users of a presence channel

GET /apps//channels//users

@param channel_name [String] Channel name (max 200 characters) @param params [Hash] Hash of parameters for the API - see REST API docs

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 262
def channel_users(channel_name, params = {})
  get("/channels/#{channel_name}/users", params)
end
channels(params = {}) click to toggle source

Request a list of occupied channels from the API

GET /apps//channels

@param params [Hash] Hash of parameters for the API - see REST API docs

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 230
def channels(params = {})
  get('/channels', params)
end
cluster=(cluster) click to toggle source
# File lib/eventflit/client.rb, line 125
def cluster=(cluster)
  @host = "api-#{cluster}.eventflit.com"
end
em_http_client(uri) click to toggle source

@private Construct an em-http-request http client

# File lib/eventflit/client.rb, line 377
def em_http_client(uri)
  begin
    unless defined?(EventMachine) && EventMachine.reactor_running?
      raise Error, "In order to use async calling you must be running inside an eventmachine loop"
    end
    require 'em-http' unless defined?(EventMachine::HttpRequest)

    connection_opts = {
      :connect_timeout => @connect_timeout,
      :inactivity_timeout => @receive_timeout,
    }

    if defined?(@proxy)
      proxy_opts = {
        :host => @proxy[:host],
        :port => @proxy[:port]
      }
      if @proxy[:user]
        proxy_opts[:authorization] = [@proxy[:user], @proxy[:password]]
      end
      connection_opts[:proxy] = proxy_opts
    end

    EventMachine::HttpRequest.new(uri, connection_opts)
  end
end
encrypted=(boolean) click to toggle source

Configure whether Eventflit API calls should be made over SSL (default false)

@example

Eventflit.encrypted = true
# File lib/eventflit/client.rb, line 115
def encrypted=(boolean)
  @scheme = boolean ? 'https' : 'http'
  # Configure port if it hasn't already been configured
  @port = boolean ? 443 : 80
end
encrypted?() click to toggle source
# File lib/eventflit/client.rb, line 121
def encrypted?
  @scheme == 'https'
end
get(path, params = {}) click to toggle source

GET arbitrary REST API resource using a synchronous http client. All request signing is handled automatically.

@example

begin
  Eventflit.get('/channels', filter_by_prefix: 'private-')
rescue Eventflit::Error => e
  # Handle error
end

@param path [String] Path excluding /apps/APP_ID @param params [Hash] API params (see docs.eventflit.com/rest_api)

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 159
def get(path, params = {})
  resource(path).get(params)
end
get_async(path, params = {}) click to toggle source

GET arbitrary REST API resource using an asynchronous http client. All request signing is handled automatically.

When the eventmachine reactor is running, the em-http-request gem is used; otherwise an async request is made using httpclient. See README for details and examples.

@param path [String] Path excluding /apps/APP_ID @param params [Hash] API params (see docs.eventflit.com/rest_api)

@return Either an EM::DefaultDeferrable or a HTTPClient::Connection

# File lib/eventflit/client.rb, line 175
def get_async(path, params = {})
  resource(path).get_async(params)
end
http_proxy=(http_proxy) click to toggle source
# File lib/eventflit/client.rb, line 96
def http_proxy=(http_proxy)
  @http_proxy = http_proxy
  uri = URI.parse(http_proxy)
  @proxy = {
    :scheme => uri.scheme,
    :host => uri.host,
    :port => uri.port,
    :user => uri.user,
    :password => uri.password
  }
  @http_proxy
end
notification_client() click to toggle source
# File lib/eventflit/client.rb, line 314
def notification_client
  @notification_client ||=
    NativeNotification::Client.new(@app_id, @notification_host, @notification_scheme, self)
end
notify(interests, data = {}) click to toggle source

Send a push notification

POST /apps//notifications

@param interests [Array] An array of interests @param message [String] Message to send @param options [Hash] Additional platform specific options

@return [Hash]

# File lib/eventflit/client.rb, line 329
def notify(interests, data = {})
  notification_client.notify(interests, data)
end
post(path, params = {}) click to toggle source

POST arbitrary REST API resource using a synchronous http client. Works identially to get method, but posts params as JSON in post body.

# File lib/eventflit/client.rb, line 181
def post(path, params = {})
  resource(path).post(params)
end
post_async(path, params = {}) click to toggle source

POST arbitrary REST API resource using an asynchronous http client. Works identially to get_async method, but posts params as JSON in post body.

# File lib/eventflit/client.rb, line 188
def post_async(path, params = {})
  resource(path).post_async(params)
end
resource(path) click to toggle source

INTERACT WITH THE API ##

# File lib/eventflit/client.rb, line 137
def resource(path)
  Resource.new(self, path)
end
sync_http_client() click to toggle source

@private Construct a net/http http client

# File lib/eventflit/client.rb, line 363
def sync_http_client
  @client ||= begin
    require 'httpclient'

    HTTPClient.new(@http_proxy).tap do |c|
      c.connect_timeout = @connect_timeout
      c.send_timeout = @send_timeout
      c.receive_timeout = @receive_timeout
      c.keep_alive_timeout = @keep_alive_timeout
    end
  end
end
timeout=(value) click to toggle source

Convenience method to set all timeouts to the same value (in seconds). For more control, use the individual writers.

# File lib/eventflit/client.rb, line 131
def timeout=(value)
  @connect_timeout, @send_timeout, @receive_timeout = value, value, value
end
trigger(channels, event_name, data, params = {}) click to toggle source

Trigger an event on one or more channels

POST /apps//events

@param channels [String or Array] 1-10 channel names @param event_name [String] @param data [Object] Event data to be triggered in javascript.

Objects other than strings will be converted to JSON

@param params [Hash] Additional parameters to send to api, e.g socket_id

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 281
def trigger(channels, event_name, data, params = {})
  post('/events', trigger_params(channels, event_name, data, params))
end
trigger_async(channels, event_name, data, params = {}) click to toggle source

Trigger an event on one or more channels asynchronously. For parameters see trigger

# File lib/eventflit/client.rb, line 303
def trigger_async(channels, event_name, data, params = {})
  post_async('/events', trigger_params(channels, event_name, data, params))
end
trigger_batch(*events) click to toggle source

Trigger multiple events at the same time

POST /apps//batch_events

@param events [Array] List of events to publish

@return [Hash] See Eventflit API docs

@raise [Eventflit::Error] Unsuccessful response - see the error message @raise [Eventflit::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error

# File lib/eventflit/client.rb, line 296
def trigger_batch(*events)
  post('/batch_events', trigger_batch_params(events.flatten))
end
trigger_batch_async(*events) click to toggle source

Trigger multiple events asynchronously. For parameters see trigger_batch

# File lib/eventflit/client.rb, line 310
def trigger_batch_async(*events)
  post_async('/batch_events', trigger_batch_params(events.flatten))
end
url(path = nil) click to toggle source

@private Builds a url for this app, optionally appending a path

# File lib/eventflit/client.rb, line 70
def url(path = nil)
  raise ConfigurationError, :app_id unless @app_id
  URI::Generic.build({
    :scheme => @scheme,
    :host => @host,
    :port => @port,
    :path => "/apps/#{@app_id}#{path}"
  })
end
url=(url) click to toggle source

Configure Eventflit connection by providing a url rather than specifying scheme, key, secret, and app_id separately.

@example

Eventflit.url = http://KEY:SECRET@service.eventflit.com/apps/APP_ID
# File lib/eventflit/client.rb, line 86
def url=(url)
  uri = URI.parse(url)
  @scheme = uri.scheme
  @app_id = uri.path.split('/').last
  @key    = uri.user
  @secret = uri.password
  @host   = uri.host
  @port   = uri.port
end
webhook(request) click to toggle source

Convenience method for creating a new WebHook instance for validating and extracting info from a received WebHook

@param request [Rack::Request] Either a Rack::Request or a Hash containing :key, :signature, :body, and optionally :content_type.

# File lib/eventflit/client.rb, line 199
def webhook(request)
  WebHook.new(request, self)
end

Private Instance Methods

configured?() click to toggle source
# File lib/eventflit/client.rb, line 433
def configured?
  host && scheme && key && secret && app_id
end
encode_data(data) click to toggle source

JSON-encode the data if it's not a string

# File lib/eventflit/client.rb, line 428
def encode_data(data)
  return data if data.is_a? String
  MultiJson.encode(data)
end
trigger_batch_params(events) click to toggle source
# File lib/eventflit/client.rb, line 417
def trigger_batch_params(events)
  {
    batch: events.map do |event|
      event.dup.tap do |e|
        e[:data] = encode_data(e[:data])
      end
    end
  }
end
trigger_params(channels, event_name, data, params) click to toggle source
# File lib/eventflit/client.rb, line 406
def trigger_params(channels, event_name, data, params)
  channels = Array(channels).map(&:to_s)
  raise Eventflit::Error, "Too many channels (#{channels.length}), max 10" if channels.length > 10

  params.merge({
    name: event_name,
    channels: channels,
    data: encode_data(data),
  })
end