mirror of
https://github.com/onyx-and-iris/obsws-ruby.git
synced 2025-04-11 07:23:45 +01:00
Compare commits
No commits in common. "155cbe019acea9c4684f92063676556c0c550ef5" and "72ee539b96b5bf2c89c580a468331067493c3086" have entirely different histories.
155cbe019a
...
72ee539b96
@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
obsws (0.3.3)
|
||||
obsws (0.2.1)
|
||||
waitutil (~> 0.2.1)
|
||||
websocket-driver (~> 0.7.5)
|
||||
|
||||
@ -52,7 +52,7 @@ GEM
|
||||
rubocop-performance (~> 1.18.0)
|
||||
unicode-display_width (2.4.2)
|
||||
waitutil (0.2.1)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
|
||||
|
13
README.md
13
README.md
@ -2,7 +2,7 @@
|
||||
[](https://github.com/onyx-and-iris/obsws-ruby/blob/dev/LICENSE)
|
||||
[](https://github.com/standardrb/standard)
|
||||
|
||||
# Ruby Clients for OBS Studio WebSocket v5.0
|
||||
# A Ruby wrapper around OBS Studio WebSocket v5.0
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -114,12 +114,15 @@ For a full list of status codes refer to [Codes](https://github.com/obsproject/o
|
||||
|
||||
### Logging
|
||||
|
||||
To enable logs set an environmental variable `OBSWS_LOG_LEVEL` to the appropriate level.
|
||||
To see the raw messages set log level to debug
|
||||
|
||||
example in powershell:
|
||||
example:
|
||||
|
||||
```powershell
|
||||
$env:OBSWS_LOG_LEVEL="DEBUG"
|
||||
```ruby
|
||||
require "obsws"
|
||||
|
||||
OBSWS::LOGGER.debug!
|
||||
...
|
||||
```
|
||||
|
||||
### Tests
|
||||
|
@ -1,6 +1,7 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
class Main
|
||||
attr_reader :running
|
||||
|
@ -1,6 +1,7 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
module LevelTypes
|
||||
VU = 0
|
||||
|
@ -1,6 +1,7 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
class Main
|
||||
def conn_from_yaml
|
||||
|
@ -1,5 +1,11 @@
|
||||
require "logger"
|
||||
|
||||
require_relative "obsws/req"
|
||||
require_relative "obsws/event"
|
||||
|
||||
module OBSWS
|
||||
include Logger::Severity
|
||||
|
||||
LOGGER = Logger.new(STDOUT)
|
||||
LOGGER.level = WARN
|
||||
end
|
||||
|
@ -1,16 +1,27 @@
|
||||
require "socket"
|
||||
require "websocket/driver"
|
||||
require "digest/sha2"
|
||||
require "json"
|
||||
require "waitutil"
|
||||
|
||||
require_relative "driver"
|
||||
require_relative "error"
|
||||
require_relative "logger"
|
||||
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 Logging
|
||||
include Driver::Director
|
||||
include Mixin::OPCodes
|
||||
|
||||
attr_reader :closed
|
||||
@ -21,7 +32,21 @@ module OBSWS
|
||||
port = kwargs[:port] || 4455
|
||||
@password = kwargs[:password] || ""
|
||||
@subs = kwargs[:subs] || 0
|
||||
setup_driver(host, port)
|
||||
|
||||
@socket = TCPSocket.new(host, port)
|
||||
@driver =
|
||||
WebSocket::Driver.client(Socket.new("ws://#{host}:#{port}", @socket))
|
||||
@driver.on :open do |msg|
|
||||
LOGGER.debug("driver socket open")
|
||||
end
|
||||
@driver.on :close do |msg|
|
||||
LOGGER.debug("driver socket closed")
|
||||
@closed = true
|
||||
end
|
||||
@driver.on :message do |msg|
|
||||
LOGGER.debug("received: #{msg.data}")
|
||||
msg_handler(JSON.parse(msg.data, symbolize_names: true))
|
||||
end
|
||||
start_driver
|
||||
WaitUtil.wait_for_condition(
|
||||
"successful identification",
|
||||
@ -30,6 +55,22 @@ module OBSWS
|
||||
) { @identified }
|
||||
end
|
||||
|
||||
private def start_driver
|
||||
Thread.new do
|
||||
@driver.start
|
||||
|
||||
loop do
|
||||
@driver.parse(@socket.readpartial(4096))
|
||||
rescue EOFError
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
public def stop_driver
|
||||
@driver.close
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def auth_token(salt:, challenge:)
|
||||
@ -50,7 +91,7 @@ module OBSWS
|
||||
if @password.empty?
|
||||
raise OBSWSError("auth enabled but no password provided")
|
||||
end
|
||||
logger.info("initiating authentication")
|
||||
LOGGER.info("initiating authentication")
|
||||
payload[:d][:authentication] = auth_token(**auth)
|
||||
end
|
||||
@driver.text(JSON.generate(payload))
|
||||
@ -76,7 +117,7 @@ module OBSWS
|
||||
}
|
||||
}
|
||||
payload[:d][:requestData] = data if data
|
||||
logger.debug("sending request: #{payload}")
|
||||
LOGGER.debug("sending request: #{payload}")
|
||||
@driver.text(JSON.generate(payload))
|
||||
end
|
||||
end
|
||||
|
@ -1,53 +0,0 @@
|
||||
require "socket"
|
||||
require "websocket/driver"
|
||||
|
||||
module OBSWS
|
||||
module Driver
|
||||
class Socket
|
||||
attr_reader :url
|
||||
|
||||
def initialize(url, socket)
|
||||
@url = url
|
||||
@socket = socket
|
||||
end
|
||||
|
||||
def write(s)
|
||||
@socket.write(s)
|
||||
end
|
||||
end
|
||||
|
||||
module Director
|
||||
def setup_driver(host, port)
|
||||
@socket = TCPSocket.new(host, port)
|
||||
@driver =
|
||||
WebSocket::Driver.client(Socket.new("ws://#{host}:#{port}", @socket))
|
||||
@driver.on :open do |msg|
|
||||
logger.debug("driver socket open")
|
||||
end
|
||||
@driver.on :close do |msg|
|
||||
logger.debug("driver socket closed")
|
||||
@closed = true
|
||||
end
|
||||
@driver.on :message do |msg|
|
||||
msg_handler(JSON.parse(msg.data, symbolize_names: true))
|
||||
end
|
||||
end
|
||||
|
||||
private def start_driver
|
||||
Thread.new do
|
||||
@driver.start
|
||||
|
||||
loop do
|
||||
@driver.parse(@socket.readpartial(4096))
|
||||
rescue EOFError
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
public def stop_driver
|
||||
@driver.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -2,7 +2,6 @@ require "json"
|
||||
|
||||
require_relative "util"
|
||||
require_relative "mixin"
|
||||
require_relative "logger"
|
||||
|
||||
module OBSWS
|
||||
module Events
|
||||
@ -35,28 +34,27 @@ module OBSWS
|
||||
end
|
||||
|
||||
module Callbacks
|
||||
include Util::String
|
||||
|
||||
def observers
|
||||
@observers ||= []
|
||||
end
|
||||
include Util
|
||||
|
||||
def add_observer(observer)
|
||||
@observers = [] unless defined?(@observers)
|
||||
observer = [observer] if !observer.respond_to? :each
|
||||
observer.each { |o| observers << o }
|
||||
observer.each { |o| @observers.append(o) }
|
||||
end
|
||||
|
||||
def remove_observer(observer)
|
||||
observers.delete(observer)
|
||||
@observers.delete(observer)
|
||||
end
|
||||
|
||||
def notify_observers(event, data)
|
||||
observers.each do |o|
|
||||
if o.respond_to? "on_#{snakecase(event)}"
|
||||
if data.empty?
|
||||
o.send("on_#{snakecase(event)}")
|
||||
else
|
||||
o.send("on_#{snakecase(event)}", data)
|
||||
if defined?(@observers)
|
||||
@observers.each do |o|
|
||||
if o.respond_to? "on_#{event.to_snake}"
|
||||
if data.empty?
|
||||
o.send("on_#{event.to_snake}")
|
||||
else
|
||||
o.send("on_#{event.to_snake}", data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -64,7 +62,6 @@ module OBSWS
|
||||
end
|
||||
|
||||
class Client
|
||||
include Logging
|
||||
include Callbacks
|
||||
include Mixin::TearDown
|
||||
include Mixin::OPCodes
|
||||
@ -72,10 +69,9 @@ module OBSWS
|
||||
def initialize(**kwargs)
|
||||
kwargs[:subs] ||= SUBS::LOW_VOLUME
|
||||
@base_client = Base.new(**kwargs)
|
||||
logger.info("#{self} successfully identified with server")
|
||||
LOGGER.info("#{self} succesfully identified with server")
|
||||
@base_client.updater = ->(op_code, data) {
|
||||
if op_code == Mixin::OPCodes::EVENT
|
||||
logger.debug("received: #{data}")
|
||||
event = data[:eventType]
|
||||
data = data.fetch(:eventData, {})
|
||||
notify_observers(event, Mixin::Data.new(data, data.keys))
|
||||
|
@ -1,11 +0,0 @@
|
||||
require "logger"
|
||||
|
||||
module OBSWS
|
||||
module Logging
|
||||
def logger
|
||||
@logger = Logger.new($stdout, level: ENV.fetch("OBSWS_LOG_LEVEL", "WARN"))
|
||||
@logger.progname = instance_of?(::Module) ? name : self.class.name
|
||||
@logger
|
||||
end
|
||||
end
|
||||
end
|
@ -3,11 +3,11 @@ require_relative "util"
|
||||
module OBSWS
|
||||
module Mixin
|
||||
module Meta
|
||||
include Util::String
|
||||
include Util
|
||||
|
||||
def make_field_methods(*params)
|
||||
params.each do |param|
|
||||
define_singleton_method(snakecase(param.to_s)) { @resp[param] }
|
||||
define_singleton_method(param.to_s.to_snake) { @resp[param] }
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -23,7 +23,7 @@ module OBSWS
|
||||
|
||||
def empty? = @fields.empty?
|
||||
|
||||
def attrs = @fields.map { |f| snakecase(f.to_s) }
|
||||
def attrs = @fields.map { |f| f.to_s.to_snake }
|
||||
end
|
||||
|
||||
class Response < MetaObject
|
||||
|
@ -4,21 +4,18 @@ require_relative "base"
|
||||
require_relative "error"
|
||||
require_relative "util"
|
||||
require_relative "mixin"
|
||||
require_relative "logger"
|
||||
|
||||
module OBSWS
|
||||
module Requests
|
||||
class Client
|
||||
include Logging
|
||||
include Error
|
||||
include Mixin::TearDown
|
||||
include Mixin::OPCodes
|
||||
|
||||
def initialize(**kwargs)
|
||||
@base_client = Base.new(**kwargs)
|
||||
logger.info("#{self} successfully identified with server")
|
||||
LOGGER.info("#{self} succesfully identified with server")
|
||||
@base_client.updater = ->(op_code, data) {
|
||||
logger.debug("response received: #{data}")
|
||||
@response = data if op_code == Mixin::OPCodes::REQUESTRESPONSE
|
||||
}
|
||||
@response = {requestId: 0}
|
||||
@ -59,7 +56,7 @@ module OBSWS
|
||||
@response[:responseData]
|
||||
rescue WaitUtil::TimeoutError
|
||||
msg = "no response with matching id received"
|
||||
logger.error(msg)
|
||||
LOGGER.error(msg)
|
||||
raise OBSWSError.new(msg)
|
||||
end
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
module OBSWS
|
||||
module Util
|
||||
module String
|
||||
def camelcase(s)
|
||||
s.split("_").map(&:capitalize).join
|
||||
class ::String
|
||||
def to_camel
|
||||
self.split(/_/).map(&:capitalize).join
|
||||
end
|
||||
|
||||
def snakecase(s)
|
||||
s
|
||||
def to_snake
|
||||
self
|
||||
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
||||
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
||||
.downcase
|
||||
|
@ -7,11 +7,11 @@ module OBSWS
|
||||
end
|
||||
|
||||
def minor
|
||||
3
|
||||
2
|
||||
end
|
||||
|
||||
def patch
|
||||
3
|
||||
1
|
||||
end
|
||||
|
||||
def to_a
|
||||
|
Loading…
x
Reference in New Issue
Block a user