summaryrefslogtreecommitdiff
path: root/crystal/bungmobott.cr
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-10-25 01:11:19 -0700
committerJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-10-25 01:11:19 -0700
commit07adc920bbf28d0047a73fca3260d5eabce510d9 (patch)
tree007ba6ced201119550d18dff9cbae297a5591b26 /crystal/bungmobott.cr
parent89431aa34a8c01099dda72ca1f46b8c7ebcbb74d (diff)
downloadtwitchtools-07adc920bbf28d0047a73fca3260d5eabce510d9.tar.gz
twitchtools-07adc920bbf28d0047a73fca3260d5eabce510d9.zip
crystal/bungmobott: partial migration to OBS-WebSocket protocol 5
Diffstat (limited to 'crystal/bungmobott.cr')
-rwxr-xr-xcrystal/bungmobott.cr330
1 files changed, 268 insertions, 62 deletions
diff --git a/crystal/bungmobott.cr b/crystal/bungmobott.cr
index 124d983..1d91bf7 100755
--- a/crystal/bungmobott.cr
+++ b/crystal/bungmobott.cr
@@ -105,7 +105,8 @@ else
settings["chat_user"] = settings["channel"]
end
-obsipc = Channel( String ).new
+obs4ipc = Channel( String ).new
+obs5ipc = Channel( String ).new
ircipc = Channel( Tuple( String, String ) ).new
t2sipc = Channel( Tuple( String, String ) ).new
twitchipc = Channel( Tuple( String, Union( String, UInt64 ) ) ).new
@@ -143,12 +144,15 @@ snifflast = Int64.new(0)
def urbandef( term : String )
+ ssl_context = OpenSSL::SSL::Context::Client.new
+ {% if flag?(:windows) %}
+ ssl_context.verify_mode = OpenSSL::SSL::VerifyMode::NONE
+ {% end %}
#http://api.urbandictionary.com/v0/define?term=waifu
- client = HTTP::Client.new( "api.urbandictionary.com" )
- response = client.exec( "GET", "/v0/define?term=pawg" + URI.encode_www_form( term ) )
+ response = HTTP::Client.exec( "GET", "https://api.urbandictionary.com/v0/define?term=#{term}", tls: ssl_context )
puts response.status_code
json = JSON.parse( response.body )
- return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /\n/, "" )
+ return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /(\r|\n)/, " " )
end
# Currently only used in flag?(:unix)
@@ -303,7 +307,7 @@ def reversesource( scenes : Hash( String, Hash( String, Hash( String, Int64 | Fl
scenes[currentscene].each do | source, sourcedata |
# maybe make this recurse later
sourcemap[source.to_s] = currentscene
- if sourcedata["type"] == "scene"
+ if ( ( ! sourcedata.has_key?("type") ) || ( sourcedata["type"] == "scene" ) )
scenes[source.to_s].each do | metasource, metasourcedata |
sourcemap[metasource.to_s] = source.to_s
end
@@ -405,6 +409,7 @@ lastvoice = Array(String).new
#streamstatus = Hash(String, Union( Bool, Float64, Int64, UInt64, String ) ).new
streamstatus = Hash(String, JSON::Any).new
+outputstatus = Hash(String, JSON::Any).new
# Put tts stuff into the same thread so each playback blocks the next
spawn do
@@ -480,12 +485,216 @@ spawn do
end
end
-# obs-websocket thread
+def obsrequest( type : String, id : String, data : ( String | Nil | JSON::Any ) = nil )
+ request = JSON.build do |json|
+ json.object do
+ json.field "op", 6
+ json.field "d" do
+ json.object do
+ json.field "requestType", type
+ json.field "requestId", id
+ if data
+ json.field "requestData", data
+ end
+ end
+ end
+ end
+ end
+ return request.to_s
+end
+
+# obs-websocket-5 thread
spawn do
loop do
begin
- obs_pubsub = HTTP::WebSocket.new( URI.parse( "ws://127.0.0.1:4444/" ), HTTP::Headers{"Cookie" => "SESSIONID=1234"} )
+ obs5_pubsub = HTTP::WebSocket.new( URI.parse( "ws://127.0.0.1:4455/" ), HTTP::Headers{"Cookie" => "SESSIONID=1235", "Sec-WebSocket-Protocol" => "obswebsocket.json"} )
+ # Outgoing
+ # state
+ currentscene = "unknown"
+ canvas = { 1280, 720 }
+
+ # inputname => { property => value }
+ inputs = Hash( String, Hash( String, String | Int64 | Float64 | Bool ) )
+ # GetInputList
+ # GetInputSettings
+
+ # scenename => { sceneitemid => { property => value }
+ scenes = Hash( String, Hash( String, Hash( String, Int64 | Float64 | Bool | String ) ) ).new
+ # GetSceneList
+ # GetSceneItemList
+ # GetSceneItemTransform
+
+ spawn do
+ while msg = obs5ipc.receive
+ pp msg
+ if ( match = msg.match( /^\x10source(-notransition|) ([a-z0-9-_]+)/ ) )
+ transition = ( match[1] != "-notransition" )
+ source = match[2]
+ sources = reversesource( scenes, currentscene )
+ pp sources
+ unless ( scene = sources[source]? )
+ ircipc.send( { "#" + settings["channel"], "| obs5: source not found: #{source}" } )
+ next
+ end
+ obs5_pubsub.send( obsrequest( "GetSceneItemEnabled", "GetSceneItemTransform", JSON.parse( { "sceneName" => scene, "sceneItemId" => scenes[scene][source]["id"] }.to_json ) ) )
+ if ( match = msg.match( /^\x10source[-a-zA-Z0-9_]* ([a-z0-9-_]+) (true|false)/ ) )
+ obs5_pubsub.send( obsrequest( "SetSceneItemEnabled", "SetSceneItemEnabled", JSON.parse( { "sceneName" => scene, "sceneItemId" => scenes[scene][source]["id"], "sceneItemEnabled" => ( match[2] == "true" ) }.to_json ) ) )
+ elsif ( match = msg.match( /^\x10source[-a-zA-Z0-9_]* ([a-z0-9-_]+)/ ) )
+ obs5_pubsub.send( obsrequest( "SetSceneItemEnabled", "SetSceneItemEnabled", JSON.parse( { "sceneName" => scene, "sceneItemId" => scenes[scene][source]["id"], "sceneItemEnabled" => ! scenes[scene][source]["render"] }.to_json ) ) )
+ end
+# if transition
+# request = Hash( String, String | Bool ).new
+# request["request-type"] = "SetPreviewScene"
+# request["message-id"] = "SetPreviewScene"
+# request["scene-name"] = currentscene
+# obs4_pubsub.send( request.to_json )
+# sleep 0.1 # somehow these get out-of-order otherwise? >:(
+# request = Hash( String, String ).new
+# request["request-type"] = "TransitionToProgram"
+# request["message-id"] = "TransitionToProgram"
+# obs4_pubsub.send( request.to_json )
+# end
+ elsif ( match = msg.match( /^\x10source/ ) )
+ pp scenes
+ pp currentscene
+ sources = reversesource( scenes, currentscene )
+ #ircipc.send( { "#" + settings["channel"], "| obs: " + sources.keys.join(", ") } )
+ obs5_pubsub.send( obsrequest( "GetSceneItemList", "GetSceneItemList", JSON.parse( { "sceneName" => currentscene }.to_json ) ) )
+ else
+ obs5_pubsub.send( msg )
+ end
+ end
+ end
+ # Incoming
+ obs5_pubsub.on_message do | message |
+ json = JSON.parse( message )
+ if json["error"]?
+ puts json["error"]
+ ircipc.send( { "#" + settings["channel"], "| obs5: #{json["error"]}" } )
+ next
+ end
+ case json["op"].as_i
+ when 0 # hello
+ json_text = %({"op":1,"d":{"rpcVersion":1}})
+ obs5_pubsub.send( json_text )
+ when 5 # event
+ edata = json["d"]["eventData"]
+ case json["d"]["eventType"].as_s
+ when "CurrentProgramSceneChanged"
+ ircipc.send( { "#" + settings["channel"], "| obs5: switched scene to " + ( edata["sceneName"]?.as_s? || "unknown" ) } )
+ puts "SwitchScenes: currentscene is " + currentscene
+ currentscene = edata["sceneName"].as_s
+ puts "SwitchScenes: currentscene is " + currentscene
+ when "SceneItemEnableStateChanged"
+ # FIXME: No sceneItemName? need to convert scenes/sceneitems into a proper object interface or build a new index so we can lookup name by id
+ edata["sceneItemEnabled"].as_bool
+ edata["sceneItemId"].as_i
+ edata["sceneName"].as_s
+ end
+ when 7 # requestResponse
+ case json["d"]["requestType"].as_s
+ when "GetStats" # FIXME: RequestBatch this with GetOutputStatus?
+ streamstatus = json["d"]["responseData"].as_h
+
+ obs5_pubsub.send( obsrequest( "GetOutputList", "GetOutputList" ))
+ when "GetOutputList"
+ output_name = String.new
+ json["d"]["responseData"]["outputs"].as_a.each do | output |
+ if output["outputKind"].as_s == "rtmp_output"
+ output_name = output["outputName"].as_s
+ end
+ end
+ unless output_name.empty?
+ obs5_pubsub.send( obsrequest( "GetOutputStatus", "GetOutputStatus", JSON.parse( { "outputName" => output_name }.to_json ) ))
+ end
+ when "GetOutputStatus"
+ streamstatus = streamstatus.merge( json["d"]["responseData"].as_h )
+ ircipc.send( { "##{settings["channel"]}", "| #{streamstatus["outputTimecode"].as_s[0..7]} #{streamstatus["activeFps"].as_f.to_s[0,2]}fps Usage: #{streamstatus["cpuUsage"].as_f.to_i64}% #{streamstatus["memoryUsage"].as_f.to_i64}MiB Frame losses: #{streamstatus["outputSkippedFrames"].as_i64} #{streamstatus["outputSkippedFrames"].as_i64}" } )
+ when /^GetSceneItemList/
+ pp json
+ rdata = json["d"]["responseData"]
+ ( match = json["d"]["requestId"].as_s.match( /^GetSceneItemList-([A-Za-z0-9-_\/]+)/ ) ) || next
+ # scenename => { sourcename => { property => value }
+ # scenes = Hash( String, Hash( String, Hash( String, Int64 | Float64 | Bool | String ) ) ).new
+ rdata["sceneItems"].as_a.each do | source |
+
+ scenes[match[1]][source["sourceName"]]? || ( scenes[match[1]][source["sourceName"].as_s] = Hash( String, Int64 | Float64 | Bool | String ).new )
+ source["sceneItemEnabled"].as_bool != Nil && ( scenes[match[1]][source["sourceName"].as_s]["render"] = source["sceneItemEnabled"].as_bool )
+ source["sceneItemId"].as_i64? && ( scenes[match[1]][source["sourceName"].as_s]["id"] = source["sceneItemId"].as_i64 )
+ source["inputKind"].as_s? && ( scenes[match[1]][source["sourceName"].as_s]["type"] = source["inputKind"].as_s )
+ source["sceneItemTransform"]["positionX"].as_f? && ( scenes[match[1]][source["sourceName"].as_s]["x"] = source["sceneItemTransform"]["positionX"].as_f )
+ source["sceneItemTransform"]["positionY"].as_f? && ( scenes[match[1]][source["sourceName"].as_s]["y"] = source["sceneItemTransform"]["positionY"].as_f )
+ source["sceneItemTransform"]["sourceWidth"].as_f? && ( scenes[match[1]][source["sourceName"].as_s]["source_cx"] = source["sceneItemTransform"]["sourceWidth"].as_f )
+ source["sceneItemTransform"]["sourceHeight"].as_f? && ( scenes[match[1]][source["sourceName"].as_s]["source_cy"] = source["sceneItemTransform"]["sourceHeight"].as_f )
+ if source["sceneItemTransform"]["width"].as_i64?
+ scenes[match[1]][source["sourceName"].as_s]["cx"] = source["sceneItemTransform"]["cx"].as_i64
+ else
+ scenes[match[1]][source["sourceName"].as_s]["cx"] = 0.to_i64
+ end
+ if source["sceneItemTransform"]["height"].as_i64?
+ scenes[match[1]][source["sourceName"].as_s]["cy"] = source["sceneItemTransform"]["cy"].as_i64
+ else
+ scenes[match[1]][source["sourceName"].as_s]["cy"] = 0.to_i64
+ end
+ end
+ when "GetSceneList"
+ rdata = json["d"]["responseData"]
+ currentscene = rdata["currentProgramSceneName"].as_s
+ pp rdata["scenes"]
+ rdata["scenes"].as_a.each do |scene|
+ scenes[scene["sceneName"].as_s] = Hash( String, Hash( String, Int64 | Float64 | Bool | String ) ).new
+ end
+ if json["d"]["requestId"].as_s =~ /Quietly/ # We need to populate the scenes table once at startup
+ scenes.keys.each do |scene|
+ obs5_pubsub.send( obsrequest( "GetSceneItemList", "GetSceneItemList-#{scene}", JSON.parse( { "sceneName" => scene }.to_json ) ))
+ end
+ else # Loudly
+ ircipc.send( { "#" + settings["channel"], "| obs5: " + rdata["scenes"].as_a.map{ |scene| scene["sceneName"] }.join(", ") } )
+ end
+ when "GetVideoSettings"
+ rdata = json["d"]["responseData"]
+ canvas = { rdata["baseWidth"].as_i.to_u64 , rdata["baseHeight"].as_i.to_u64 }
+ pp canvas
+ end
+ end
+ print( "5 RECEIVED: ")
+ print( json.to_pretty_json )
+ print( "\n")
+ end
+ spawn do
+ # authentication
+ sleep 1
+ obs5_pubsub.send( obsrequest( "GetVideoSettings", "GetVideoSettings" ))
+ obs5_pubsub.send( obsrequest( "GetStats", "GetStats" ))
+ sleep 1
+ obs5_pubsub.send( obsrequest( "GetSceneList", "GetSceneList Quietly" ))
+ end
+ obs5_pubsub.run
+ rescue ex : Socket::ConnectError
+ # these are a bit noisy
+ #pp ex
+ obs5_pubsub && obs5_pubsub.close
+ rescue ex : IO::Error
+ pp ex
+ ircipc.send( { "#" + settings["channel"], "obs.cr:obs: " + ex.to_s.gsub(/\r|\n/, ' ') + ": Maybe try again in 10 seconds?" } )
+ rescue ex
+ pp ex
+ pp ex.backtrace?
+ ircipc.send( { "#" + settings["channel"], "irc.cr:obs: " + ex.to_s.gsub(/\r|\n/, ' ') } )
+ obs5_pubsub && obs5_pubsub.close
+ end
+ sleep 10
+ next
+ end
+end
+
+# obs-websocket-4 thread
+spawn do
+ loop do
+ begin
+
+ obs4_pubsub = HTTP::WebSocket.new( URI.parse( "ws://127.0.0.1:4444/" ), HTTP::Headers{"Cookie" => "SESSIONID=1234"} )
# Outgoing
# state
currentscene = "unknown"
@@ -493,7 +702,7 @@ spawn do
# scenename => { sourcename => { property => value }
scenes = Hash( String, Hash( String, Hash( String, Int64 | Float64 | Bool | String ) ) ).new
spawn do
- while msg = obsipc.receive
+ while msg = obs4ipc.receive
pp msg
if ( match = msg.match( /^\x10source(-notransition|) ([a-z0-9-_]+)/ ) )
transition = ( match[1] != "-notransition" )
@@ -504,7 +713,7 @@ spawn do
request["request-type"] = "SetSceneItemProperties"
request["message-id"] = "SetSceneItemProperties"
unless ( scene = sources[source]? )
- ircipc.send( { "#" + settings["channel"], "| obs: source not found: #{source}" } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: source not found: #{source}" } )
next
end
request["scene-name"] = scene
@@ -526,19 +735,19 @@ spawn do
end
end
end
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
puts "x10source: currentscene is " + currentscene
if transition
request = Hash( String, String | Bool ).new
request["request-type"] = "SetPreviewScene"
request["message-id"] = "SetPreviewScene"
request["scene-name"] = currentscene
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
sleep 0.1 # somehow these get out-of-order otherwise? >:(
request = Hash( String, String ).new
request["request-type"] = "TransitionToProgram"
request["message-id"] = "TransitionToProgram"
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
end
elsif ( match = msg.match( /^\x10sceneitem ([a-z0-9-_]+)/ ) )
source = match[1]
@@ -548,18 +757,18 @@ spawn do
request["request-type"] = "GetSceneItemProperties"
request["message-id"] = "GetSceneItemProperties"
unless ( scene = sources[source]? )
- ircipc.send( { "#" + settings["channel"], "| obs: source not found: #{source}" } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: source not found: #{source}" } )
next
end
request["scene-name"] = scene
request["item"] = source
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
elsif ( match = msg.match( /^\x10source/ ) )
request = Hash( String, String ){
"request-type" => "GetCurrentScene",
"message-id" => "GetCurrentScene",
}
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
elsif ( match = msg.match( /^\x10newsource(-temporary|) ([a-zA-Z0-9-_]+)/ ) )
temporary = ( match[1]? )
@@ -581,26 +790,26 @@ spawn do
},
}
ircipc.send( { "##{settings["channel"]}", "Creating #{sourcename}" } )
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
else
- obs_pubsub.send( msg )
+ obs4_pubsub.send( msg )
end
end
end
# Incoming
- obs_pubsub.on_message do | message |
+ obs4_pubsub.on_message do | message |
json = JSON.parse( message )
if json["error"]?
puts json["error"]
- ircipc.send( { "#" + settings["channel"], "| obs: #{json["error"]}" } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: #{json["error"]}" } )
next
end
case json["update-type"]?
when "StreamStatus" # these are a bit noisy,
- streamstatus = json
+ streamstatus = json.as_h
next # so skip them
when "SwitchScenes"
- ircipc.send( { "#" + settings["channel"], "| obs: switched scene to " + ( json["scene-name"]?.as_s? || "unknown" ) } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: switched scene to " + ( json["scene-name"]?.as_s? || "unknown" ) } )
puts "SwitchScenes: currentscene is " + currentscene
currentscene = json["scene-name"].as_s
puts "SwitchScenes: currentscene is " + currentscene
@@ -617,8 +826,8 @@ spawn do
"item" => source,
"visible" => false
}
- ircipc.send( { "##{settings["channel"]}", "| obs: Media ended; disabling #{source}" } )
- obsipc.send( request.to_json )
+ ircipc.send( { "##{settings["channel"]}", "| obs4: Media ended; disabling #{source}" } )
+ obs4ipc.send( request.to_json )
end
end
if ( source =~ /^media-temporary-/ )
@@ -629,21 +838,21 @@ spawn do
"item" => { "name" => json["sourceName"].as_s },
}
ircipc.send( { "##{settings["channel"]}", "Deleting #{source}" } )
- obsipc.send( request.to_json )
+ obs4ipc.send( request.to_json )
end
when "SourceFilterVisibilityChanged"
- ircipc.send( { "##{settings["channel"]}", "| obs: source #{json["sourceName"]} filter #{json["filterName"]} visibility is currently #{json["filterEnabled"]}" } )
+ ircipc.send( { "##{settings["channel"]}", "| obs4: source #{json["sourceName"]} filter #{json["filterName"]} visibility is currently #{json["filterEnabled"]}" } )
when "SceneItemAdded"
request = Hash( String, String ){
"request-type" => "GetCurrentScene",
"message-id" => "GetCurrentScene Quietly",
}
- obsipc.send( request.to_json)
+ obs4ipc.send( request.to_json)
request = Hash( String, String ){
"request-type" => "GetSceneList",
"message-id" => "GetSceneList Quietly",
}
- obsipc.send( request.to_json )
+ obs4ipc.send( request.to_json )
if json["item-name"].as_s =~ /media-temporary/
request = Hash( String, String | Bool ).new
@@ -651,7 +860,7 @@ spawn do
request["message-id"] = "GetSceneItemProperties"
request["scene-name"] = json["scene-name"].as_s
request["item"] = json["item-name"].as_s
- obs_pubsub.send( request.to_json )
+ obs4_pubsub.send( request.to_json )
end
#scenes[json["scene-name"].as_s][json["item-name"].as_s]
when "SourceRenamed"
@@ -669,10 +878,10 @@ spawn do
print( json.to_pretty_json )
if json["item-name"].as_s !~ /media-temporary/
scenes[json["scene-name"].as_s][json["item-name"].as_s]["render"] = json["item-visible"].as_bool
- ircipc.send( { "##{settings["channel"]}", "| obs: source #{json["item-name"]} visibility is now #{json["item-visible"].as_bool}" } )
+ ircipc.send( { "##{settings["channel"]}", "| obs4: source #{json["item-name"]} visibility is now #{json["item-visible"].as_bool}" } )
end
end
- print( "RECEIVED: ")
+ print( "4 RECEIVED: ")
print( json.to_pretty_json )
print( "\n")
case json["message-id"]?.as_s?
@@ -688,11 +897,11 @@ spawn do
# We should probably just preprocess these values into explosionslist :/
# ffprobe -show_entries stream=width,height big_explosion_1.webm
request["position"] = {
- "x" => (rand(canvas[0]) - ( size[0] / 2 ) ).to_f ,
+ "x" => (rand(canvas[0]) - ( size[0] / 2 ) ).to_f,
"y" => (rand(canvas[1]) - ( size[1] / 2 ) ).to_f,
}
- obsipc.send( request.to_json )
- #ircipc.send( { "##{settings["channel"]}", "| obs: #{request.to_json}" } )
+ obs4ipc.send( request.to_json )
+ #ircipc.send( { "##{settings["channel"]}", "| obs4: #{request.to_json}" } )
end
when /^GetVideoInfo/
@@ -703,13 +912,13 @@ spawn do
puts "GetCurrentScene: currentscene is " + currentscene
if json["message-id"].as_s? !~ /Quietly/
sources = reversesource( scenes, currentscene )
- ircipc.send( { "#" + settings["channel"], "| obs: " + sources.keys.join(", ") } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: " + sources.keys.join(", ") } )
end
when "GetSourceFilters"
- ircipc.send( { "#" + settings["channel"], "| obs: " + json["filters"].as_a.map{ |filter| "#{filter["name"].as_s}: #{filter["enabled"].as_bool}" }.join(", ") } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: " + json["filters"].as_a.map{ |filter| "#{filter["name"].as_s}: #{filter["enabled"].as_bool}" }.join(", ") } )
when /^GetSceneList/
if json["message-id"].as_s? !~ /Quietly/
- ircipc.send( { "#" + settings["channel"], "| obs: " + json["scenes"].as_a.map{ |scene| scene["name"] }.join(", ") } )
+ ircipc.send( { "#" + settings["channel"], "| obs4: " + json["scenes"].as_a.map{ |scene| scene["name"] }.join(", ") } )
end
json["scenes"].as_a.each{ |scene|
scenes[scene["name"].as_s]? || ( scenes[scene["name"].as_s] = Hash( String, Hash( String, Int64 | Float64 | Bool | String ) ).new )
@@ -743,32 +952,32 @@ spawn do
"request-type" => "GetCurrentScene",
"message-id" => "GetCurrentScene Quietly",
}
- obsipc.send( request.to_json )
+ obs4ipc.send( request.to_json )
request = Hash( String, String ){
"request-type" => "GetSceneList",
"message-id" => "GetSceneList Quietly",
}
- obsipc.send( request.to_json)
+ obs4ipc.send( request.to_json)
sleep 1
request = Hash( String, String ){
"request-type" => "GetVideoInfo",
"message-id" => "GetVideoInfo Quietly",
}
- obsipc.send( request.to_json)
+ obs4ipc.send( request.to_json)
end
- obs_pubsub.run
+ obs4_pubsub.run
rescue ex : Socket::ConnectError
# these are a bit noisy
#pp ex
- obs_pubsub && obs_pubsub.close
+ obs4_pubsub && obs4_pubsub.close
rescue ex : IO::Error
pp ex
- ircipc.send( { "#" + settings["channel"], "obs.cr:obs: " + ex.to_s.gsub(/\r|\n/, ' ') + ": Maybe try again in 10 seconds?" } )
+ ircipc.send( { "#" + settings["channel"], "obs.cr:obs4: " + ex.to_s.gsub(/\r|\n/, ' ') + ": Maybe try again in 10 seconds?" } )
rescue ex
pp ex
pp ex.backtrace?
- ircipc.send( { "#" + settings["channel"], "irc.cr:obs: " + ex.to_s.gsub(/\r|\n/, ' ') } )
- obs_pubsub && obs_pubsub.close
+ ircipc.send( { "#" + settings["channel"], "irc.cr:obs4: " + ex.to_s.gsub(/\r|\n/, ' ') } )
+ obs4_pubsub && obs4_pubsub.close
end
sleep 10
next
@@ -899,33 +1108,30 @@ loop do
else
end
elsif ( cmd =~ /^uptime$/ )
- ircipc.send( { "##{settings["channel"]}", "| #{streamstatus["stream-timecode"].as_s[0..7]} Usage: #{streamstatus["cpu-usage"].as_f.to_i64}% #{streamstatus["memory-usage"].as_f.to_i64}MiB #{streamstatus["kbits-per-sec"].as_i64}kbps Frame losses: #{streamstatus["render-missed-frames"].as_i64} #{streamstatus["num-dropped-frames"].as_i64} #{streamstatus["output-skipped-frames"].as_i64}" } )
+ obs5ipc.send( obsrequest( "GetStats", "GetStats" ))
# !newimage [name] [url] (random|top|bottom|left|right|center)
# download url, verify mimetype with libmagic, duplicate existing medialoop source, change "file" SourceSetting
elsif ( ( cmd =~ /^sourcesettings$/ ) && ( mod || own || vip ) )
if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
- obsipc.send( "{ \"request-type\": \"GetSourceSettings\", \"message-id\": \"GetSourceSettings\", \"sourceName\": \"#{match[2]}\" }" )
+
+ obs5ipc.send( obsrequest( "GetInputSettings", "GetInputSettings", JSON.parse( { "inputName" => match[2] }.to_json ) ))
end
+ elsif ( ( cmd =~ /^inputlist$/ ) && ( mod || own || vip ) )
+ obs5ipc.send( obsrequest( "GetInputList", "GetInputList" ) )
elsif ( ( cmd =~ /^scene$/ ) && ( mod || own || vip ) )
if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
- obsipc.send( "{ \"request-type\": \"SetCurrentScene\", \"message-id\": \"SetCurrentScene\", \"scene-name\": \"" + match[2] + "\" }" )
- else
- obsipc.send( "{ \"request-type\": \"GetSceneList\", \"message-id\": \"GetSceneList\" }" )
- end
- elsif ( ( cmd =~ /^sceneitem$/ ) && ( mod || own || vip ) )
- if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
- obsipc.send( "\x10sceneitem #{match[2]}" )
+ obs5ipc.send( obsrequest( "SetCurrentProgramScene", "SetCurrentProgramScene", JSON.parse( { "sceneName" => match[2] }.to_json ) ))
else
- ircipc.send( { "##{settings["channel"]}", "Must provide provide a scene name as argument." } )
+ obs5ipc.send( obsrequest( "GetSceneList", "GetSceneList" ) )
end
elsif ( ( cmd =~ /^source$/ ) && ( mod || own || vip ) )
request = Hash( String, String | Bool ).new
if ( match[2]? ) && ( sourceargs = match[2].match( /^([a-zA-Z0-9-_]+) +(true|false)$/ ) )
- obsipc.send( "\x10source #{match[2]}" )
+ obs5ipc.send( "\x10source #{match[2]}" )
elsif ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
- obsipc.send( "\x10source #{match[2]}" )
+ obs5ipc.send( "\x10source #{match[2]}" )
else
- obsipc.send( "\x10source" )
+ obs5ipc.send( "\x10source" )
end
elsif ( ( cmd =~ /^filter$/ ) && ( mod || own ) )
request = Hash( String, String | Bool ){
@@ -939,29 +1145,29 @@ loop do
#request["filterEnabled"] = filterargs[3]
filterargs[3] == "true" && ( request["filterEnabled"] = true )
filterargs[3] == "false" && ( request["filterEnabled"] = false )
- obsipc.send( request.to_json )
+ obs4ipc.send( request.to_json )
elsif ( match[2]? ) && ( filterargs = match[2].match( /^([a-zA-Z0-9-_]+) +([a-zA-Z0-9-_]+)/ ) )
ircipc.send( { "##{settings["channel"]}", "Must provide provide a value of true or false as the third argument." } )
elsif ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
request["sourceName"] = match[2]
request["message-id"] = "GetSourceFilters"
- obsipc.send( request.to_json )
+ obs4ipc.send( request.to_json )
else
ircipc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument, and optionally one filter name and a value of true or false." } )
end
elsif ( cmd == "create" && ( mod || own || vip ) )
if ( match[2]? ) && ( match[2] =~ /^([a-zA-Z0-9-_]+)/ )
- obsipc.send( "\x10newsource-temporary #{match[2]}" )
+ obs4ipc.send( "\x10newsource-temporary #{match[2]}" )
else
ircipc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument." } )
end
elsif ( cmd =~ /^(metaminute|youdied)$/ )
- obsipc.send( "\x10source-notransition media-#{cmd}" )
+ obs4ipc.send( "\x10source-notransition media-#{cmd}" )
elsif ( cmd =~ /^explosion$/ )
if explosions
explosion = explosions.sample( 1 )[0][1]
puts explosion
- obsipc.send( "\x10newsource-temporary #{explosion}" )
+ obs4ipc.send( "\x10newsource-temporary #{explosion}" )
else
puts "explosions undefined"
end