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