From 21cec0aad15c97f6c8c3d9415fe1ae1aae952165 Mon Sep 17 00:00:00 2001 From: Joe Rayhawk Date: Mon, 14 Mar 2022 08:11:13 -0700 Subject: crystal/eventsub.cr: new twitch eventsub consumer --- crystal/eventsub.cr | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 crystal/eventsub.cr (limited to 'crystal/eventsub.cr') diff --git a/crystal/eventsub.cr b/crystal/eventsub.cr new file mode 100644 index 0000000..328b639 --- /dev/null +++ b/crystal/eventsub.cr @@ -0,0 +1,137 @@ +require "pretty_print" +require "json" +require "openssl/hmac" + + +puts "Content-type: text/plain; charset=UTF-8" +puts + +settings = Hash(String, String).new +["eventsub_secret", "channel"].each do |key| + begin + settings[key] = File.read( "/etc/twitch/" + key ).chomp + rescue + STDERR.puts "Warning: Missing /etc/twitch/" + key + end +end + +def ircmsg( channel : String, msg : String) + if msg !~ /(\r|\n)/ + sock = Socket.unix + sock.connect Socket::UNIXAddress.new( "/etc/twitch/irc-socket".to_s ) + sock.puts( "#" + channel + " " + "eventsub: " + msg ) + sock.close + end +end + +def effectsmsg( msg : String ) + sock = Socket.unix + sock.connect Socket::UNIXAddress.new( "/etc/twitch/effects-socket" ) + sock.puts( msg ) + sock.close +rescue ex + STDERR.puts( ex ) +end + +struct Nil + def as_s? + self + end + def as_i? + self + end +end + +File.open("/tmp/eventsub.#{Process.pid}.txt", "w", 0o644 ) do |file| + + input = STDIN.gets_to_end + + begin + json = JSON.parse( input ) + + 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"]? + + case json["subscription"]["type"] + when "channel.update" + #ircmsg( settings["channel"], "#{json["event"]["broadcaster_user_login"]} is now playing #{json["event"]["category_name"]} with the title #{json["event"]["title"]}" ) + effectsmsg( "overlay gltext #{json["event"]["broadcaster_user_login"]} is now playing #{json["event"]["category_name"]} with the title #{json["event"]["title"]}" ) + when "stream.online" + ircmsg( settings["channel"], "| #{json["event"]["broadcaster_user_login"]} is now streaming!" ) + when "stream.offline" + ircmsg( settings["channel"], "| #{json["event"]["broadcaster_user_login"]} is now offline." ) + when "channel.follow" + ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now following!" ) + when "channel.ban" + ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now banned!" ) + when "channel.unban" + ircmsg( settings["channel"], "#{json["event"]["user_login"]} is now unbanned!" ) + when "channel.raid" + effectsmsg( "overlay gltext #{json["event"]["from_broadcaster_user_login"]} is raiding with #{json["event"]["viewers"]} viewer(s)!" ) + ircmsg( settings["channel"], "#{json["event"]["from_broadcaster_user_login"]} is raiding with #{json["event"]["viewers"]} viewer(s)! bungmoBlobDance bungmoBlobDance bungmoBlobDance bungmoBlobDance" ) + when "channel.subscribe" + sub_recver = ( json["event"]["user_login"]?.as_s? || "anonymous" ) + 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 ) + effectsmsg( "overlay gltext 10 " + sub_recver + " subscribed!" ) + ircmsg( settings["channel"], sub_recver.to_s + " has subscribed for " + sub_months.to_s + " months at sub level #" + sub_plan.to_s + "" ) + when "channel.subscription.gift" + sub_sender = ( json["event"]["user_login"]?.as_s? || "anonymous" ) + sub_recver = ( json["event"]["broadcaster_user_login"]?.as_s? || sub_sender ) + sub_plan = ( json["event"]["tier"]?.as_s? || "unknown" ) + sub_total = ( json["event"]["total"]?.as_s? || "0" ) + sub_cumulative = ( json["event"]["cumulative_total"]?.as_i? || 0 ) + effectsmsg( "overlay gltext 10 " + sub_sender + " donated " + sub_total + " subs!" ) + ircmsg( settings["channel"], sub_recver.to_s + " has subscribed for " + sub_cumulative.to_s + " months at sub level #" + sub_plan.to_s ) + when "channel.subscription.message" + sub_sender = ( json["event"]["user_login"]?.as_s? || "anonymous" ) + sub_recver = ( json["event"]["broadcaster_user_login"]?.as_s? || sub_sender ) + sub_plan = ( json["event"]["tier"]?.as_s? || "unknown" ) + sub_months = ( json["event"]["cumulative_months"]?.as_s? || "0" ) + sub_msg = ( json["event"]["message"]["text"]?.as_s? || "" ) + effectsmsg( "overlay gltext 10 " + sub_recver + " subscribed!" ) + ircmsg( settings["channel"], sub_recver.to_s + " has subscribed for " + sub_months.to_s + " months at sub level #" + sub_plan.to_s + ": " + sub_msg.to_s ) + end + else + STDOUT.puts( json.pretty_inspect ) + STDOUT.puts( ARGV.pretty_inspect ) + STDOUT.puts( ENV.pretty_inspect ) + STDOUT.puts( file.path ) + end + file.puts( json.pretty_inspect ) + file.puts( ARGV.pretty_inspect ) + file.puts( ENV.pretty_inspect ) + rescue ex + STDERR.puts( ex ) + STDOUT.puts( input ) + file.puts( input ) + end + +end + + +#{"subscription" => +# {"id" => "3c1c3a9c-748e-4374-8e61-2c0210755af3", +# "status" => "enabled", +# "type" => "channel.subscribe", +# "version" => "1", +# "condition" => {"broadcaster_user_id" => "59895482"}, +# "transport" => +# {"method" => "webhook", +# "callback" => "https://twitch.fairlystable.org/eventsub"}, +# "created_at" => "2021-02-09T19:13:49.618252874Z", +# "cost" => 0}, +# "event" => +# {"user_id" => "71506453", +# "user_login" => "shift_f7", +# "user_name" => "Shift_F7", +# "broadcaster_user_id" => "59895482", +# "broadcaster_user_login" => "bungmonkey", +# "broadcaster_user_name" => "BungMonkey", +# "tier" => "1000", +# "is_gift" => true}} +# -- cgit v1.2.3