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 at sub level #" + sub_plan.to_s + " bungmoBlobDance bungmoBlobDance bungmoBlobDance bungmoBlobDance" ) 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_sender} has gifted #{sub_total} tier #{sub_plan} subscription for a total of #{sub_cumulative}" ) 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 ) sub_msg = ( json["event"]["message"]["text"]?.as_s? || "" ) effectsmsg( "overlay gltext 10 " + sub_sender + " subscribed!" ) ircmsg( settings["channel"], sub_sender.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}} #