From 47adaa9a252f82688eabbf6f18d9ddd786e1cb70 Mon Sep 17 00:00:00 2001 From: Joe Rayhawk Date: Mon, 21 Nov 2022 22:57:17 -0800 Subject: crystal: crystal-obs-websocket API updates --- crystal/bungmobott.cr | 35 +++++++++++++++++++-------- crystal/eventsub.cr | 65 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 30 deletions(-) (limited to 'crystal') diff --git a/crystal/bungmobott.cr b/crystal/bungmobott.cr index 34c2328..642d0b3 100755 --- a/crystal/bungmobott.cr +++ b/crystal/bungmobott.cr @@ -112,7 +112,7 @@ ircipc = Channel( Tuple( String, String ) ).new t2sipc = Channel( Tuple( String, String ) ).new twitchipc = Channel( Tuple( String, Union( String, UInt64 ) ) ).new -obs = OBSWebSocket::Server.new( "ws://127.0.0.1:4455/" ) +obs = OBS::WebSocket.new( "ws://127.0.0.1:4455/" ) # OBS event thread spawn do @@ -122,7 +122,7 @@ spawn do obs.inputs[key].delete! end end - obs.reqchan.send( { evchan, "subscribe events" } ) + obs.eventsub_add( evchan ) while json = evchan.receive # A Fiber.yield occurs after this to make sure "json" doesn't get overwritten before we can use it. spawn do @@ -132,7 +132,7 @@ spawn do ircipc.send( { "#" + settings["channel"], "| obs: switched scene to " + ( d["eventData"]["sceneName"]?.as_s? || "unknown" ) } ) when "MediaInputPlaybackEnded" if d["eventData"]["inputName"].as_s =~ /^media-temporary-/ - obs.reqchan.send( { nil, OBSWebSocket.req( "RemoveInput", UUID.random.to_s, JSON.parse({ "inputName" => d["eventData"]["inputName"].as_s }.to_json) ) } ) + obs.send( OBS.req( "RemoveInput", UUID.random.to_s, JSON.parse({ "inputName" => d["eventData"]["inputName"].as_s }.to_json) ) ) elsif d["eventData"]["inputName"].as_s =~ /^media-/ obs.scenes.current.metascene[d["eventData"]["inputName"].as_s][0].disable! end @@ -162,7 +162,7 @@ spawn do end when "SourceFilterEnableStateChanged" edata = d["eventData"] - ircipc.send( { "##{settings["channel"]}", "| obs: source #{edata["sourceName"].as_s} filter #{edata["filterName"].as_s} visibility is currently #{edata["filterEnabled"].as_s}" } ) + ircipc.send( { "##{settings["channel"]}", "| obs: source #{edata["sourceName"].as_s} filter #{edata["filterName"].as_s} visibility is currently #{edata["filterEnabled"].as_bool}" } ) end end Fiber.yield @@ -197,7 +197,16 @@ spawn do end end -def obstemporarymediacreate( obs : OBSWebSocket::Server, sname : String, iname, path : String ) +def obsrandommediaenable( obs : OBS::WebSocket, siname : String ) + if ( Random.rand(3) < 2 ) + obs.scenes.current.metascene[siname][0].enable! + else + randsiname = obs.scenes.current.metascene.keys.select( /^#{siname}/ ).sample( 1 )[0] + obs.scenes.current.metascene[randsiname][0].enable! + end +end + +def obstemporarymediacreate( obs : OBS::WebSocket, sname : String, iname, path : String ) iname = "media-temporary-effect-#{iname}" isettings = Hash( String, String | Bool | Int64 | Float64 ){ "advanced" => true, @@ -212,7 +221,7 @@ def obstemporarymediacreate( obs : OBSWebSocket::Server, sname : String, iname, # Skip ORM stuff and configure the SceneItem as fast as we possibly can if ( rdata = response["responseData"]? ) && ( goodtransform = obs.sources.last_known_real_transform?( iname ) ) siid = rdata["sceneItemId"].as_i64 - obs.reqchan.send( { nil, OBSWebSocket.req( "SetSceneItemTransform", UUID.random.to_s, JSON.parse( { "sceneName" => sname, "sceneItemId" => siid, "sceneItemTransform" => { "positionX" => goodtransform.to_h["positionX"], "positionY" => goodtransform.to_h["positionY"] } }.to_json ) ) } ) + obs.send( OBS.req( "SetSceneItemTransform", UUID.random.to_s, JSON.parse( { "sceneName" => sname, "sceneItemId" => siid, "sceneItemTransform" => { "positionX" => goodtransform.to_h["positionX"], "positionY" => goodtransform.to_h["positionY"] } }.to_json ) ) ) end end @@ -600,8 +609,15 @@ loop do end end end - if ( message.params[1] =~ /thanks.*obama/i ) - obs.scenes["meta-foreground"]["media-youdied-thanksobama"].enable! + case message.params[1] + when /pl(ease|z).+nerf/i + obsrandommediaenable( obs, "media-youdied-nerf" ) + when /you.+died/i + obsrandommediaenable( obs, "media-youdied" ) + when /did +nothing +wrong/i + obsrandommediaenable( obs, "media-youdied-tiggs" ) + when /thanks.+obama/i + obsrandommediaenable( obs, "media-youdied-thanksobama" ) end next unless ( ( match = message.params[1].match(/^ *!([A-Za-z]+) (([a-zA-Z0-9= _\:,.&'\/?;\\\(\)\[\]+\-]|!)+)/) || message.params[1].match(/^ *!([A-Za-z]+)/) ) ) cmd = match[1] @@ -717,7 +733,7 @@ loop do ircipc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument." } ) end elsif ( cmd =~ /^(metaminute|youdied)$/ ) - obs.scenes.current.metascene["media-#{cmd}"][0].enable! + obsrandommediaenable( obs, "media-#{cmd}" ) elsif ( cmd =~ /^fart(s|)$/ ) && ( sub || mod || own || vip ) if effects.values.select( /^farts/ ).size > 0 if ( match[2]? ) && ( match[2].match( /^([0-9]+)/ ) && ( match[2].to_i > 1 ) && ( match[2].to_i <= 32 ) ) @@ -777,7 +793,6 @@ loop do if match[2]? && match[2] =~ /^([a-zA-Z0-9 -])+$/ definition = urbandef( match[2] ) ircipc.send( { "##{settings["channel"]}", definition[0,400] } ) - # FIXME: maybe somehow fold this into the existing voice logic t2s( t2sipc, settings, userdir, chatuser, definition[0,400] ) else ircipc.send( { "##{settings["channel"]}", "| Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." } ) diff --git a/crystal/eventsub.cr b/crystal/eventsub.cr index 6014ebf..b472b4b 100644 --- a/crystal/eventsub.cr +++ b/crystal/eventsub.cr @@ -15,17 +15,28 @@ settings = Hash(String, String).new end end -# enable explosions? -explosions = Hash( String, String ).new -if File.exists?( settings["configdir"] + "/explosionlist.txt" ) - File.each_line( settings["configdir"] + "/explosionlist.txt" ) do |line| - explosions[ line.downcase ] = line - end +settings["configdir"] = "/home/jrayhawk/.config/bungmobott/" + +if ENV["LOCALAPPDATA"]? + settings["configdir"] = Path.windows( ENV["LOCALAPPDATA"] + "\\bungmobott\\" ).to_s + settings["statedir"] = Path.windows( ENV["LOCALAPPDATA"] + "\\bungmobott\\state\\" ).to_s end -obs = OBSWebSocket::Server.new( "ws://127.0.0.1:4455/" ) +ENV["XDG_CONFIG_HOME"]? && ( settings["configdir"] = ENV["XDG_CONFIG_HOME"] + "/bungmobott/" ) -def obstemporarymediacreate( obs : OBSWebSocket::Server, sname : String, iname, path : String ) +Dir.mkdir_p( settings["configdir"] ) + +# enable effects? +effects = Hash( String, String ).new +if File.exists?( settings["configdir"] + "/effects.txt" ) + File.each_line( settings["configdir"] + "/effects.txt" ) do |line| + effects[ line.downcase ] = line + end +end +explosioncount = 0 +youdied = false + +def obstemporarymediacreate( obs : OBS::WebSocket, sname : String, iname, path : String ) iname = "media-temporary-explosion-#{iname}" isettings = Hash( String, String | Bool | Int64 | Float64 ){ "advanced" => true, @@ -39,6 +50,15 @@ def obstemporarymediacreate( obs : OBSWebSocket::Server, sname : String, iname, response = obs.scenes[sname].createinput( iname, "ffmpeg_source", isettings ) end +def obsrandommediaenable( obs : OBS::WebSocket, siname : String ) + if ( Random.rand(3) < 2 ) + obs.scenes.current.metascene[siname][0].enable! + else + randsiname = obs.scenes.current.metascene.keys.select( /^#{siname}/ ).sample( 1 )[0] + obs.scenes.current.metascene[randsiname][0].enable! + end +end + def ircmsg( channel : String, msg : String) if msg !~ /(\r|\n)/ sock = Socket.unix @@ -75,7 +95,6 @@ File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| digest = "sha256=" + OpenSSL::HMAC.hexdigest( :sha256, settings["eventsub_secret"], ENV["HTTP_TWITCH_EVENTSUB_MESSAGE_ID"] + ENV["HTTP_TWITCH_EVENTSUB_MESSAGE_TIMESTAMP"] + input ) if json["challenge"]? && ( ENV["HTTP_TWITCH_EVENTSUB_MESSAGE_SIGNATURE"] == digest ) - STDOUT.puts( json["challenge"] ) file.puts( json["challenge"] ) elsif json["event"]? @@ -91,6 +110,7 @@ File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now following!" ) when "channel.ban" ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now banned!" ) + youdied = true when "channel.unban" ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now unbanned!" ) when "channel.raid" @@ -101,13 +121,8 @@ File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| sub_broadcaster = ( json["event"]["broadcaster_user_login"]?.as_s? || "unknown" ) sub_plan = ( json["event"]["tier"]?.as_s? || "unknown" ) #sub_months = ( json["event"]["cumulative_months"]?.as_i? || 0 ) - unless json["event"]["is_gift"].as_bool - effectsmsg( "overlay gltext 10 " + sub_recver + " subscribed!" ) - spawn do - explosions.values.sample( 5 ).each do | explosion | - obstemporarymediacreate( obs, "meta-foreground", explosion, "C:/cygwin64/home/user/effects/explosions/#{explosion}.webm" ) - end - end + unless json["event"]["is_gift"].as_bool # If gift, let count get size-limited in channel.subscription.gift below instead + explosioncount += 5 end ircmsg( settings["channel"], sub_recver.to_s + " has subscribed at sub level #" + sub_plan.to_s + " bungmoBlobDance bungmoBlobDance bungmoBlobDance bungmoBlobDance" ) when "channel.subscription.gift" @@ -121,11 +136,9 @@ File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| spawn do count = sub_total * 5 ( count > 50 ) && ( count = 50 ) - explosions.values.sample( count ).each do | explosion | - obstemporarymediacreate( obs, "meta-foreground", explosion, "C:/cygwin64/home/user/effects/explosions/#{explosion}.webm" ) - end + explosioncount += count end - when "channel.subscription.message" + when "channel.subscription.message" sub_sender = ( json["event"]["user_login"]?.as_s? || "anonymous" ) sub_plan = ( json["event"]["tier"]?.as_s? || "unknown" ) sub_months = ( json["event"]["cumulative_months"]?.as_i? || 0 ) @@ -150,6 +163,18 @@ File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| end +if youdied + obs = OBS::WebSocket.new( "ws://127.0.0.1:4455/", retry: false ) + obsrandommediaenable( obs, "media-youdied" ) +end + +if ( explosioncount > 0 ) + obs = OBS::WebSocket.new( "ws://127.0.0.1:4455/", retry: false ) + effects.values.select(/^explosions/).sample( explosioncount ).each do | effect | + obstemporarymediacreate( obs, "meta-foreground", effect.gsub(/[\/ ]/,"_"), "C:/cygwin64/home/user/effects/#{effect}") + end +end +exit #{"subscription" => # {"id" => "3c1c3a9c-748e-4374-8e61-2c0210755af3", -- cgit v1.2.3