class OBS::WebSocket::Client

OBS-websocket client.

Public Class Methods

new(websocket, executor: :io) click to toggle source

Creates an OBS-websocket client.

websocket object must respond to the following methods:

  • text(str): send a text frame

  • on(event, &block): add an event handler

  • close(): close the connection

@param websocket [Object] the websocket object @param executor the executor on which the callbacks are invoked

# File lib/obs/websocket.rb, line 34
def initialize(websocket, executor: :io)
  @websocket = websocket
  @response_dispatcher = ResponseDispatcher.new
  @event_dispatcher = EventDispatcher.new
  @executor = executor
  @on_open = Concurrent::Promises.resolvable_event
  @on_close = Concurrent::Promises.resolvable_future

  websocket.on(:open) do
    @on_open.resolve
  end

  websocket.on(:close) do |event|
    @on_close.resolve(true, [event.code, event.reason])
  end

  websocket.on(:message) do |event|
    handle_message(JSON.parse(event.data))
  end

  websocket.on(:error) do |event|
    $stderr.puts "Error: #{event.code} #{event.reason}"
  end
end

Public Instance Methods

authenticate!(password) click to toggle source

Authenticates the client to the server using the password.

@param password [String] the password @return [Future<:ok>]

# File lib/obs/websocket.rb, line 63
def authenticate!(password)
  get_auth_required.then do |h|
    if h.auth_required
      token = auth_token(
        password: password,
        salt: h.salt,
        challenge: h.challenge,
      )
      authenticate(auth: token).then { :ok }
    else
      :ok
    end
  end.flat
end
close() click to toggle source

Close the connection.

@return [void]

# File lib/obs/websocket.rb, line 119
def close
  @websocket.close
end
on(type, executor: @executor, &listener) click to toggle source

Adds an event handler for obs-websocket event.

@param type [String] type of obs-websocket event to listen for @param executor the executor on which the callback is invoked @yield Called when the specified type of obs-websocket event is received. @yieldparam event [Event] the event object @return [void]

# File lib/obs/websocket.rb, line 111
def on(type, executor: @executor, &listener)
  @event_dispatcher.register(executor, type, listener)
  nil
end
on_close(executor: @executor, &listener) click to toggle source

Adds an event handler for connection termination.

@param executor the executor on which the callback is invoked @yield Called when obs-websocket connection is terminated. @return [Future]

# File lib/obs/websocket.rb, line 96
def on_close(executor: @executor, &listener)
  if listener
    @on_close.then_on(executor, &listener)
  else
    @on_close.with_default_executor(executor)
  end
end
on_open(executor: @executor, &listener) click to toggle source

Adds an event handler for connection establishment.

@param executor the executor on which the callback is invoked @yield Called when obs-websocket connection is established. @return [Event]

# File lib/obs/websocket.rb, line 83
def on_open(executor: @executor, &listener)
  if listener
    @on_open.chain_on(executor, &listener)
  else
    @on_open.with_default_executor(executor)
  end
end

Private Instance Methods

auth_token(password:, salt:, challenge:) click to toggle source
# File lib/obs/websocket.rb, line 125
def auth_token(password:, salt:, challenge:)
  Digest::SHA256.base64digest(Digest::SHA256.base64digest(password + salt) + challenge)
end
handle_message(payload) click to toggle source
# File lib/obs/websocket.rb, line 135
 def handle_message(payload)
   if message_id = payload['message-id']
     @response_dispatcher.dispatch(message_id, payload)
   elsif update_type = payload['update-type']
     @event_dispatcher.dispatch(update_type, payload)
   else
     fail 'Unknown message'
   end
end
send_request(request) click to toggle source
# File lib/obs/websocket.rb, line 129
def send_request(request)
  message_id, future = @response_dispatcher.register(@executor, request)
  @websocket.text(JSON.dump({**request.to_h, 'message-id' => message_id}))
  future
end