diff options
author | Joe Rayhawk <jrayhawk+git@omgwallhack.org> | 2022-10-25 01:11:19 -0700 |
---|---|---|
committer | Joe Rayhawk <jrayhawk+git@omgwallhack.org> | 2022-10-25 01:11:19 -0700 |
commit | 07adc920bbf28d0047a73fca3260d5eabce510d9 (patch) | |
tree | 007ba6ced201119550d18dff9cbae297a5591b26 | |
parent | 89431aa34a8c01099dda72ca1f46b8c7ebcbb74d (diff) | |
download | twitchtools-07adc920bbf28d0047a73fca3260d5eabce510d9.tar.gz twitchtools-07adc920bbf28d0047a73fca3260d5eabce510d9.zip |
crystal/bungmobott: partial migration to OBS-WebSocket protocol 5
-rwxr-xr-x | crystal/bungmobott.cr | 330 |
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 |