mirror of
https://github.com/onyx-and-iris/obsws-ruby.git
synced 2026-04-18 21:43:32 +00:00
initial commit
This commit is contained in:
117
lib/obsws/base.rb
Normal file
117
lib/obsws/base.rb
Normal file
@@ -0,0 +1,117 @@
|
||||
require "socket"
|
||||
require "websocket/driver"
|
||||
require "digest/sha2"
|
||||
require "json"
|
||||
require "observer"
|
||||
require "waitutil"
|
||||
|
||||
require_relative "mixin"
|
||||
require_relative "error"
|
||||
|
||||
module OBSWS
|
||||
class Socket
|
||||
attr_reader :url
|
||||
|
||||
def initialize(url, socket)
|
||||
@url = url
|
||||
@socket = socket
|
||||
end
|
||||
|
||||
def write(s)
|
||||
@socket.write(s)
|
||||
end
|
||||
end
|
||||
|
||||
class Base
|
||||
include Observable
|
||||
include Mixin::OPCodes
|
||||
|
||||
attr_reader :id, :driver, :closed
|
||||
|
||||
def initialize(**kwargs)
|
||||
host = kwargs[:host] || "localhost"
|
||||
port = kwargs[:port] || 4455
|
||||
@password = kwargs[:password] || ""
|
||||
@subs = kwargs[:subs] || 0
|
||||
|
||||
@socket = TCPSocket.new(host, port)
|
||||
@driver =
|
||||
WebSocket::Driver.client(Socket.new("ws://#{host}:#{port}", @socket))
|
||||
@ready = false
|
||||
@closed = false
|
||||
@driver.on :open do |msg|
|
||||
LOGGER.debug("driver socket open")
|
||||
@ready = true
|
||||
end
|
||||
@driver.on :close do |msg|
|
||||
LOGGER.debug("driver socket closed")
|
||||
@closed = true
|
||||
end
|
||||
@driver.on :message do |msg|
|
||||
LOGGER.debug("received [#{msg}] passing to handler")
|
||||
msg_handler(JSON.parse(msg.data, symbolize_names: true))
|
||||
end
|
||||
Thread.new { start_driver }
|
||||
WaitUtil.wait_for_condition(
|
||||
"driver socket ready",
|
||||
delay_sec: 0.01,
|
||||
timeout_sec: 0.5
|
||||
) { @ready }
|
||||
end
|
||||
|
||||
def start_driver
|
||||
@driver.start
|
||||
|
||||
loop do
|
||||
@driver.parse(@socket.readpartial(4096))
|
||||
rescue EOFError
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
def auth_token(salt:, challenge:)
|
||||
Digest::SHA256.base64digest(
|
||||
Digest::SHA256.base64digest(@password + salt) + challenge
|
||||
)
|
||||
end
|
||||
|
||||
def authenticate(auth)
|
||||
token = auth_token(**auth)
|
||||
payload = {
|
||||
op: Mixin::OPCodes::IDENTIFY,
|
||||
d: {
|
||||
rpcVersion: 1,
|
||||
authentication: token,
|
||||
eventSubscriptions: @subs
|
||||
}
|
||||
}
|
||||
@driver.text(JSON.generate(payload))
|
||||
end
|
||||
|
||||
def msg_handler(data)
|
||||
op_code = data[:op]
|
||||
case op_code
|
||||
when Mixin::OPCodes::HELLO
|
||||
authenticate(data[:d][:authentication])
|
||||
when Mixin::OPCodes::IDENTIFIED
|
||||
LOGGER.debug("Authentication successful")
|
||||
when Mixin::OPCodes::EVENT, Mixin::OPCodes::REQUESTRESPONSE
|
||||
changed
|
||||
notify_observers(op_code, data[:d])
|
||||
end
|
||||
end
|
||||
|
||||
def req(id, type_, data = nil)
|
||||
payload = {
|
||||
op: Mixin::OPCodes::REQUEST,
|
||||
d: {
|
||||
requestType: type_,
|
||||
requestId: id
|
||||
}
|
||||
}
|
||||
payload[:d][:requestData] = data if data
|
||||
queued = @driver.text(JSON.generate(payload))
|
||||
LOGGER.debug("request with id #{id} queued? #{queued}")
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user