mirror of
https://github.com/onyx-and-iris/obsws-ruby.git
synced 2025-04-03 20:03:46 +01:00
Compare commits
13 Commits
72ee539b96
...
155cbe019a
Author | SHA1 | Date | |
---|---|---|---|
155cbe019a | |||
6293ae7b8c | |||
57fca646b5 | |||
d12a1a5954 | |||
438f3b1659 | |||
d15418a660 | |||
2883fd42cc | |||
88b2eabc0c | |||
e15e17cc9f | |||
72e09d5278 | |||
11d991b039 | |||
3d3d8f3020 | |||
82c6ced760 |
@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
obsws (0.2.1)
|
||||
obsws (0.3.3)
|
||||
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.5)
|
||||
websocket-driver (0.7.6)
|
||||
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)
|
||||
|
||||
# A Ruby wrapper around OBS Studio WebSocket v5.0
|
||||
# Ruby Clients for OBS Studio WebSocket v5.0
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -114,15 +114,12 @@ For a full list of status codes refer to [Codes](https://github.com/obsproject/o
|
||||
|
||||
### Logging
|
||||
|
||||
To see the raw messages set log level to debug
|
||||
To enable logs set an environmental variable `OBSWS_LOG_LEVEL` to the appropriate level.
|
||||
|
||||
example:
|
||||
example in powershell:
|
||||
|
||||
```ruby
|
||||
require "obsws"
|
||||
|
||||
OBSWS::LOGGER.debug!
|
||||
...
|
||||
```powershell
|
||||
$env:OBSWS_LOG_LEVEL="DEBUG"
|
||||
```
|
||||
|
||||
### Tests
|
||||
|
@ -1,7 +1,6 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
class Main
|
||||
attr_reader :running
|
||||
|
@ -1,7 +1,6 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
module LevelTypes
|
||||
VU = 0
|
||||
|
@ -1,7 +1,6 @@
|
||||
require_relative "../../lib/obsws"
|
||||
require "yaml"
|
||||
|
||||
OBSWS::LOGGER.info!
|
||||
|
||||
class Main
|
||||
def conn_from_yaml
|
||||
|
@ -1,11 +1,5 @@
|
||||
require "logger"
|
||||
|
||||
require_relative "obsws/req"
|
||||
require_relative "obsws/event"
|
||||
|
||||
module OBSWS
|
||||
include Logger::Severity
|
||||
|
||||
LOGGER = Logger.new(STDOUT)
|
||||
LOGGER.level = WARN
|
||||
end
|
||||
|
@ -1,27 +1,16 @@
|
||||
require "socket"
|
||||
require "websocket/driver"
|
||||
require "digest/sha2"
|
||||
require "json"
|
||||
require "waitutil"
|
||||
|
||||
require_relative "mixin"
|
||||
require_relative "driver"
|
||||
require_relative "error"
|
||||
require_relative "logger"
|
||||
require_relative "mixin"
|
||||
|
||||
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
|
||||
@ -32,21 +21,7 @@ module OBSWS
|
||||
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))
|
||||
@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
|
||||
setup_driver(host, port)
|
||||
start_driver
|
||||
WaitUtil.wait_for_condition(
|
||||
"successful identification",
|
||||
@ -55,22 +30,6 @@ 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:)
|
||||
@ -91,7 +50,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))
|
||||
@ -117,7 +76,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
|
||||
|
53
lib/obsws/driver.rb
Normal file
53
lib/obsws/driver.rb
Normal file
@ -0,0 +1,53 @@
|
||||
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,6 +2,7 @@ require "json"
|
||||
|
||||
require_relative "util"
|
||||
require_relative "mixin"
|
||||
require_relative "logger"
|
||||
|
||||
module OBSWS
|
||||
module Events
|
||||
@ -34,27 +35,28 @@ module OBSWS
|
||||
end
|
||||
|
||||
module Callbacks
|
||||
include Util
|
||||
include Util::String
|
||||
|
||||
def observers
|
||||
@observers ||= []
|
||||
end
|
||||
|
||||
def add_observer(observer)
|
||||
@observers = [] unless defined?(@observers)
|
||||
observer = [observer] if !observer.respond_to? :each
|
||||
observer.each { |o| @observers.append(o) }
|
||||
observer.each { |o| observers << o }
|
||||
end
|
||||
|
||||
def remove_observer(observer)
|
||||
@observers.delete(observer)
|
||||
observers.delete(observer)
|
||||
end
|
||||
|
||||
def notify_observers(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
|
||||
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)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -62,6 +64,7 @@ module OBSWS
|
||||
end
|
||||
|
||||
class Client
|
||||
include Logging
|
||||
include Callbacks
|
||||
include Mixin::TearDown
|
||||
include Mixin::OPCodes
|
||||
@ -69,9 +72,10 @@ module OBSWS
|
||||
def initialize(**kwargs)
|
||||
kwargs[:subs] ||= SUBS::LOW_VOLUME
|
||||
@base_client = Base.new(**kwargs)
|
||||
LOGGER.info("#{self} succesfully identified with server")
|
||||
logger.info("#{self} successfully 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))
|
||||
|
11
lib/obsws/logger.rb
Normal file
11
lib/obsws/logger.rb
Normal file
@ -0,0 +1,11 @@
|
||||
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
|
||||
include Util::String
|
||||
|
||||
def make_field_methods(*params)
|
||||
params.each do |param|
|
||||
define_singleton_method(param.to_s.to_snake) { @resp[param] }
|
||||
define_singleton_method(snakecase(param.to_s)) { @resp[param] }
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -23,7 +23,7 @@ module OBSWS
|
||||
|
||||
def empty? = @fields.empty?
|
||||
|
||||
def attrs = @fields.map { |f| f.to_s.to_snake }
|
||||
def attrs = @fields.map { |f| snakecase(f.to_s) }
|
||||
end
|
||||
|
||||
class Response < MetaObject
|
||||
|
@ -4,18 +4,21 @@ 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} succesfully identified with server")
|
||||
logger.info("#{self} successfully 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}
|
||||
@ -56,7 +59,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
|
||||
class ::String
|
||||
def to_camel
|
||||
self.split(/_/).map(&:capitalize).join
|
||||
module String
|
||||
def camelcase(s)
|
||||
s.split("_").map(&:capitalize).join
|
||||
end
|
||||
|
||||
def to_snake
|
||||
self
|
||||
def snakecase(s)
|
||||
s
|
||||
.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
|
||||
2
|
||||
3
|
||||
end
|
||||
|
||||
def patch
|
||||
1
|
||||
3
|
||||
end
|
||||
|
||||
def to_a
|
||||
|
Loading…
x
Reference in New Issue
Block a user