summaryrefslogtreecommitdiff
path: root/crystal
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-03-16 19:05:20 -0700
committerJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-03-16 19:05:20 -0700
commit8a7e4ec6a0e737058251ae4b8d1c1eaf4b712d8d (patch)
tree9df3c50305549b76cb14b3195391eb3c7bd976a1 /crystal
parent26d9235aec0ce897acbbf39f4ca1b5b019862c72 (diff)
downloadtwitchtools-8a7e4ec6a0e737058251ae4b8d1c1eaf4b712d8d.tar.gz
twitchtools-8a7e4ec6a0e737058251ae4b8d1c1eaf4b712d8d.zip
crystal/irc.cr: add obs integration and parallelize everything
Diffstat (limited to 'crystal')
-rw-r--r--crystal/irc.cr664
1 files changed, 412 insertions, 252 deletions
diff --git a/crystal/irc.cr b/crystal/irc.cr
index ceddd56..391f2c8 100644
--- a/crystal/irc.cr
+++ b/crystal/irc.cr
@@ -7,6 +7,12 @@ require "crystal_mpd"
STDOUT.sync = true
+struct Nil
+ def as_s?
+ self
+ end
+end
+
settings = Hash(String, String).new
settings["home"] = Path.home.to_s
@@ -18,6 +24,9 @@ settings["home"] = Path.home.to_s
end
end
+obsipc = Channel( String ).new
+ircipc = Channel( Tuple( String, String ) ).new
+
snifflast = Int64.new(0)
client = Twitcr::Client.new( settings )
@@ -113,6 +122,7 @@ def getvoice( settings : Hash(String, String), userdir : String, chatuser : Stri
return( [namesub, voice_setting, voice_output ] )
end
+# text2speech
def t2s( settings : Hash(String, String), userdir : String, chatuser : String, text : String )
if ( text !~ /^ *(!|\|)/ )
namesub, voice_setting, voice = getvoice( settings, userdir, chatuser )
@@ -132,281 +142,431 @@ end
lastvoice = Array(String).new
-bot = Twitch::IRC::Client.new( nick: "bungmonkey", token: "oauth:" + settings["access_token"], log_mode: true )
-bot.tags = [ "membership", "tags", "commands" ]
-
-# Reconnect on IO::Error?
+# OBS
+spawn do
+ loop do
+ begin
-# Create a handler to process incoming messages
-bot.on_message do |message|
- spawn do
- next unless ( userlogreturn = userlog( settings, message ) )
- chatuser, uid, userdir = userlogreturn
- if ( chatuser == "pipne" ) && ( ( Time.utc.to_unix - snifflast ) >= 14400 )
- snifflast = Time.utc.to_unix
- t2smsg( chatuser + " sniff null" )
- end
- if ( t2sreturn = t2s( settings, userdir, chatuser, message.params[1] ) )
- lastvoice.insert( 0, t2sreturn )
- lastvoice = lastvoice[0..4]
+ obs_pubsub = HTTP::WebSocket.new( URI.parse( "ws://127.0.0.1:4444/" ), HTTP::Headers{"Cookie" => "SESSIONID=1234"} )
+ # Outgoing
+ spawn do
+ while msg = obsipc.receive
+ pp msg
+ obs_pubsub.send( msg )
+ end
+ end
+ # Incoming
+ obs_pubsub.on_message do | message |
+ json = JSON.parse( message )
+ if json["error"]?
+ puts json["error"]
+ ircipc.send( { "#" + settings["channel"], "| obs: #{json["error"]}" } )
+ next
+ end
+ case json["update-type"]?
+ when "StreamStatus" # these are a bit noisy,
+ next # so skip them
+ when "SwitchScenes"
+ ircipc.send( { "#" + settings["channel"], "| obs: switched scene to " + ( json["scene-name"]?.as_s? || "unknown" ) } )
+ when "MediaEnded"
+ request = Hash( String, String | Bool ){
+ "request-type" => "SetSceneItemProperties",
+ "message-id" => "SetSceneItemProperties",
+ "item" => json["sourceName"].as_s,
+ "visible" => false
+ }
+ #ircipc.send( { "##{settings["channel"]}", "Disabling #{json["sourceName"].as_s}" } )
+ obsipc.send( request.to_json )
+ when "SourceFilterVisibilityChanged"
+ ircipc.send( { "##{settings["channel"]}", "| obs: source #{json["sourceName"]} filter #{json["filterName"]} visibility is now #{json["filterEnabled"]}" } )
+ end
+ print( "RECEIVED: ")
+ print( json.to_pretty_json )
+ print( "\n")
+ case json["message-id"]?
+ when "GetCurrentScene"
+ ircipc.send( { "#" + settings["channel"], "| obs: " + json["sources"].as_a.map{ |source| source["name"] }.join(", ") } )
+ when "GetSourceFilters"
+ ircipc.send( { "#" + settings["channel"], "| obs: " + json["filters"].as_a.map{ |filter| filter["name"] }.join(", ") } )
+ when "GetSceneList"
+ ircipc.send( { "#" + settings["channel"], "| obs: " + json["scenes"].as_a.map{ |scene| scene["name"] }.join(", ") } )
+ when "toggle-filter"
+ name = json["filters"][0]["name"].as_s
+ visible = ( json["filters"][0]["enabled"].as_bool == false )
+ ircipc.send( { "#" + settings["channel"], "| obs: Setting visibility of filter #{name} to #{visible}" } )
+ obsipc.send( "{ \"request-type\": \"SetSourceFilterVisibility\", \"message-id\": \"SetSourceFilterVisibility\", \"sourceName\": \"#{name}\", \"visible\": #{visible} }" )
+ #This is a dumb hack to toggle SetSceneItemProperty visibility
+ when "toggle-source"
+ name = json["name"].as_s
+ visible = ( json["visible"].as_bool == false )
+ ircipc.send( { "#" + settings["channel"], "| obs: Setting visibility of source #{name} to #{visible}" } )
+ obsipc.send( "{ \"request-type\": \"SetSceneItemProperties\", \"message-id\": \"SetSceneItemProperties\", \"item\": \"#{name}\", \"visible\": #{visible} }" )
+ end
+ end
+ obs_pubsub.run
+ rescue ex : Socket::ConnectError
+ # these are a bit noisy
+ pp ex
+ obs_pubsub && obs_pubsub.close
+ rescue ex
+ ircmsg( settings["home"], settings["channel"], "irc.cr: " + ex.to_s.gsub(/\r|\n/, ' ') )
+ puts ex
+ obs_pubsub && obs_pubsub.close
+ end
+ sleep 10
+ next
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]
- own = ( message.tags["room-id"] == message.tags["user-id"] )
- vip = ( message.tags["badges"].to_s.matches?( /(^|,)vip\// ) )
- mod = ( message.tags["mod"] == "1" )
- sub = ( message.tags["subscriber"] == "1" )
- if ( ( cmd =~ /^(substitute|voicesub)$/ ) && ( mod || sub ) )
- case message.params[1].split( " " ).size
- when 1
- if File.exists?( userdir + "/voicesub" )
- bot.message( "#bungmonkey", "| Current name substitution is \"#{File.read( userdir + "/voicesub" )}\"." )
- else
- bot.message( "#bungmonkey", "| Current name substitution is disabled." )
+end
+
+# IRC
+loop do
+ begin
+
+ bot = Twitch::IRC::Client.new( nick: settings["channel"], token: "oauth:" + settings["access_token"], log_mode: true )
+ bot.tags = [ "membership", "tags", "commands" ]
+
+ # Outgoing
+ spawn do
+ while msgtuple = ircipc.receive
+bot.message( msgtuple[0], msgtuple[1][0..480] )
end
- else
- if match[2]?
- voicesub = match[2].downcase
- if voicesub =~ /^(disabled|null|disable|none)$/
+ end
+
+ # Create a handler to process incoming messages
+ bot.on_message do |message|
+ spawn do
+ next unless ( userlogreturn = userlog( settings, message ) )
+ chatuser, uid, userdir = userlogreturn
+ if ( chatuser == "pipne" ) && ( ( Time.utc.to_unix - snifflast ) >= 14400 )
+ snifflast = Time.utc.to_unix
+ t2smsg( chatuser + " sniff null" )
+ end
+ if ( t2sreturn = t2s( settings, userdir, chatuser, message.params[1] ) )
+ lastvoice.insert( 0, t2sreturn )
+ lastvoice = lastvoice[0..4]
+ 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]
+ own = ( message.tags["room-id"] == message.tags["user-id"] )
+ vip = ( message.tags["badges"].to_s.matches?( /(^|,)vip\// ) )
+ mod = ( message.tags["mod"] == "1" )
+ sub = ( message.tags["subscriber"] == "1" )
+ if ( ( cmd =~ /^(substitute|voicesub)$/ ) && ( mod || sub ) )
+ case message.params[1].split( " " ).size
+ when 1
if File.exists?( userdir + "/voicesub" )
- File.delete( userdir + "/voicesub" )
- bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is now disabled." )
+ bot.message( "#bungmonkey", "| Current name substitution is \"#{File.read( userdir + "/voicesub" )}\"." )
else
- bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is already disabled." )
+ bot.message( "#bungmonkey", "| Current name substitution is disabled." )
end
else
- File.directory?( userdir ) || Dir.mkdir( userdir )
- File.write( userdir + "/voicesub", voicesub )
- bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is now \"#{File.read( userdir + "/voicesub" )}\"." )
+ if match[2]?
+ voicesub = match[2].downcase
+ if voicesub =~ /^(disabled|null|disable|none)$/
+ if File.exists?( userdir + "/voicesub" )
+ File.delete( userdir + "/voicesub" )
+ bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is now disabled." )
+ else
+ bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is already disabled." )
+ end
+ else
+ File.directory?( userdir ) || Dir.mkdir( userdir )
+ File.write( userdir + "/voicesub", voicesub )
+ bot.message( "#bungmonkey", "| Name substitution for #{chatuser} is now \"#{File.read( userdir + "/voicesub" )}\"." )
+ end
+ end
end
- end
- end
- elsif ( cmd =~ /^(commands|help)$/ )
- bot.message( "#bungmonkey", "| https://bungmonkey.omgwallhack.org/txt/commands.txt" )
- elsif ( ( cmd == "lastvoice" ) && ( mod || sub ) )
- unless lastvoice.empty?
- bot.message( "#bungmonkey", "| Last voices were " + lastvoice.join( ", " ) )
- else
- bot.message( "#bungmonkey", "| No voices used so far." )
- end
- elsif ( ( cmd =~ /^(voices|voicelist)$/ ) && ( mod || sub ) )
- bot.message( "#bungmonkey", "| https://bungmonkey.omgwallhack.org/voicelist.txt" )
- elsif ( ( cmd =~ /^(setvoice|voice)$/ ) && ( mod || sub ) )
- case message.params[1].split( " " ).size
- when 1
- namesub, voice_setting, voice_output = getvoice( settings, userdir, chatuser )
- bot.message( "#bungmonkey", "| Current voice is #{voice_setting}" )
- when 2
- if match[2]?
- voice = match[2].downcase
- if voice =~ /disabled|null|disable|none|random/
- if File.exists?( userdir + "/voice" )
- File.delete( userdir + "/voice" )
- bot.message( "#bungmonkey", "| Voice for #{chatuser} is now random." )
+ elsif ( cmd =~ /^(commands|help)$/ )
+ bot.message( "#bungmonkey", "| https://bungmonkey.omgwallhack.org/txt/commands.txt" )
+ elsif ( cmd =~ /^(dexem)$/ )
+ ircipc.send( { "#bungmonkey", "| You're doing great work, Dexem!" } )
+ elsif ( ( cmd == "lastvoice" ) && ( mod || sub ) )
+ unless lastvoice.empty?
+ bot.message( "#bungmonkey", "| Last voices were " + lastvoice.join( ", " ) )
+ else
+ bot.message( "#bungmonkey", "| No voices used so far." )
+ end
+ elsif ( ( cmd =~ /^(voices|voicelist)$/ ) && ( mod || sub ) )
+ bot.message( "#bungmonkey", "| https://bungmonkey.omgwallhack.org/voicelist.txt" )
+ elsif ( ( cmd =~ /^(setvoice|voice)$/ ) && ( mod || sub ) )
+ case message.params[1].split( " " ).size
+ when 1
+ namesub, voice_setting, voice_output = getvoice( settings, userdir, chatuser )
+ bot.message( "#bungmonkey", "| Current voice is #{voice_setting}" )
+ when 2
+ if match[2]?
+ voice = match[2].downcase
+ if voice =~ /disabled|null|disable|none|random/
+ if File.exists?( userdir + "/voice" )
+ File.delete( userdir + "/voice" )
+ bot.message( "#bungmonkey", "| Voice for #{chatuser} is now random." )
+ else
+ bot.message( "#bungmonkey", "| Voice for #{chatuser} is already random." )
+ end
+ elsif voices.has_key?( voice )
+ csvoice = voices[voice]
+ File.directory?( userdir ) || Dir.mkdir( userdir )
+ File.write( userdir + "/voice", csvoice )
+ pp userdir
+ bot.message( "#bungmonkey", "| Voice for #{chatuser} is now #{File.read( userdir + "/voice" )}." )
+ # TODO: make separate script to print streamelements URLs to client machine
+ else
+ pp ( match )
+ bot.message( "#bungmonkey", "| Invalid voice. To see list, use !voices" )
+ end
+ end
+ when 3
+ else
+ end
+ elsif ( ( cmd =~ /^scene$/ ) && ( mod || own ) )
+ 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 =~ /^source$/ ) && ( mod || own ) )
+ request = Hash( String, String | Bool ).new
+ if ( match[2]? ) && ( sourceargs = match[2].match( /^([a-zA-Z0-9-_]+) +(true|false)/ ) )
+ request["request-type"] = "SetSceneItemProperties"
+ request["message-id"] = "SetSceneItemProperties"
+ request["item"] = sourceargs[1]
+ sourceargs[2] == "true" && ( request["visible"] = true )
+ sourceargs[2] == "false" && ( request["visible"] = false )
+
+ ircipc.send( { "##{settings["channel"]}", "Setting source #{sourceargs[1]} visibility to #{sourceargs[2]}" } )
+ obsipc.send( request.to_json )
+ elsif ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
+ request["request-type"] = "GetSceneItemProperties"
+ request["message-id"] = "toggle-source"
+ request["item"] = match[2]
+ obsipc.send( request.to_json )
+ else
+ request["request-type"] = "GetCurrentScene"
+ request["message-id"] = "GetCurrentScene"
+ obsipc.send( request.to_json )
+ end
+ elsif ( ( cmd =~ /^filter$/ ) && ( mod || own ) )
+ request = Hash( String, String | Bool ){
+ "request-type" => "GetSourceFilters"
+ }
+ if ( match[2]? ) && ( filterargs = match[2].match( /^([a-zA-Z0-9-_]+) +([a-zA-Z0-9-_]+) (true|false)/ ) )
+ request["request-type"] = "SetSourceFilterVisibility"
+ request["message-id"] = "SetSourceFilterVisibility"
+ request["sourceName"] = filterargs[1]
+ request["filterName"] = filterargs[2]
+ #request["filterEnabled"] = filterargs[3]
+ filterargs[3] == "true" && ( request["filterEnabled"] = true )
+ filterargs[3] == "false" && ( request["filterEnabled"] = false )
+ obsipc.send( request.to_json )
+ elsif ( match[2]? ) && ( filterargs = match[2].match( /^([a-zA-Z0-9-_]+) +([a-zA-Z0-9-_]+)/ ) )
+ request["message-id"] = "toggle-filter"
+ request["sourceName"] = filterargs[1]
+ request["filterName"] = filterargs[2]
+ obsipc.send( request.to_json )
+ elsif ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
+ request["sourceName"] = match[2]
+ request["message-id"] = "GetSourceFilters"
+ obsipc.send( request.to_json )
+ else
+ ircipc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument, and optionally one filter name." } )
+ end
+ elsif ( cmd =~ /^(metaminute|youdied)$/ )
+ request = Hash( String, String | Bool ).new
+ request["request-type"] = "SetSceneItemProperties"
+ request["message-id"] = "SetSceneItemProperties"
+ request["item"] = "media-" + cmd
+ # This breaks playback (???)
+ #request["visible"] = false
+ #obsipc.send( request.to_json )
+ #sleep 0.5
+ # I should probably set this up to add the source, and then delete the source at the end of playback.
+ request["visible"] = true
+ ircipc.send( { "##{settings["channel"]}", "Playing media-#{cmd}" } )
+ obsipc.send( request.to_json )
+ elsif ( ( cmd =~ /^(status|title)$/ ) && ( mod || own ) )
+ begin
+ if match[2]?
+ client.put_channel!( settings["channel_id"].to_u64, title: match[2] )
+ json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
+ ircmsg( settings["home"], settings["channel"], "Title is now \"#{ json["data"][0]["title"] }\"")
+ else
+ json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
+ ircmsg( settings["home"], settings["channel"], "| Title is currently \"#{ json["data"][0]["title"] }\"")
+ end
+ rescue ex
+ ircmsg( settings["home"], settings["channel"], "| An error occurred! " + ex.message.to_s )
+ end
+ elsif ( ( cmd =~ /^(game|category)$/ ) && ( mod || own ) )
+ begin
+ if match[2]?
+ puts "2 matches"
+ client.put_channel!( settings["channel_id"].to_u64, game: match[2] )
+ json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
+ ircmsg( settings["home"], settings["channel"], "Game is now \"#{ json["data"][0]["game_name"] }\"")
else
- bot.message( "#bungmonkey", "| Voice for #{chatuser} is already random." )
+ puts "1 matches"
+ json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
+ ircmsg( settings["home"], settings["channel"], "| Game is currently \"#{ json["data"][0]["game_name"] }\"")
end
- elsif voices.has_key?( voice )
- csvoice = voices[voice]
- File.directory?( userdir ) || Dir.mkdir( userdir )
- File.write( userdir + "/voice", csvoice )
- pp userdir
- bot.message( "#bungmonkey", "| Voice for #{chatuser} is now #{File.read( userdir + "/voice" )}." )
- # TODO: make separate script to print streamelements URLs to client machine
+ rescue ex
+ ircmsg( settings["home"], settings["channel"], "| An error occurred! " + ex.message.to_s )
+ end
+ elsif ( ( cmd == "urban" ) && ( mod || own || sub || vip ) )
+ if match[2]? && match[2] =~ /^([a-zA-Z0-9 -])+$/
+ definition = urbandef( match[2] )
+ ircmsg( settings["home"], settings["channel"], definition[0,400] )
else
- pp ( match )
- bot.message( "#bungmonkey", "| Invalid voice. To see list, use !voices" )
+ ircmsg( settings["home"], settings["channel"], "| Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." )
end
- end
- when 3
- else
- end
- elsif ( ( cmd =~ /^(status|title)$/ ) && ( mod || own ) )
- begin
- if match[2]?
- client.put_channel!( settings["channel_id"].to_u64, title: match[2] )
- json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
- ircmsg( settings["home"], settings["channel"], "Title is now \"#{ json["data"][0]["title"] }\"")
- else
- json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
- ircmsg( settings["home"], settings["channel"], "| Title is currently \"#{ json["data"][0]["title"] }\"")
- end
- rescue ex
- ircmsg( settings["home"], settings["channel"], "| An error occurred! " + ex.message.to_s )
- end
- elsif ( ( cmd =~ /^(game|category)$/ ) && ( mod || own ) )
- begin
- if match[2]?
- puts "2 matches"
- client.put_channel!( settings["channel_id"].to_u64, game: match[2] )
- json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
- ircmsg( settings["home"], settings["channel"], "Game is now \"#{ json["data"][0]["game_name"] }\"")
- else
- puts "1 matches"
- json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
- ircmsg( settings["home"], settings["channel"], "| Game is currently \"#{ json["data"][0]["game_name"] }\"")
- end
- rescue ex
- ircmsg( settings["home"], settings["channel"], "| An error occurred! " + ex.message.to_s )
- end
- elsif ( ( cmd == "urban" ) && ( mod || own || sub || vip ) )
- if match[2]? && match[2] =~ /^([a-zA-Z0-9 -])+$/
- definition = urbandef( match[2] )
- ircmsg( settings["home"], settings["channel"], definition[0,400] )
- else
- ircmsg( settings["home"], settings["channel"], "| Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." )
- end
- elsif ( cmd == "matrix" )
- effectsmsg( "overlay glmatrix" )
- elsif ( cmd =~ /juggle|juggler/ )
- effectsmsg( "overlay juggler3d" )
- elsif ( cmd =~ /fireworks|firework/ )
- effectsmsg( "overlay fireworkx" )
- elsif ( cmd == "pipes" )
- if match[2]? && match[2] =~ /^(fast|faster)$/
- effectsmsg( "overlay pipes " + match[2] )
- else
- effectsmsg( "overlay pipes" )
- end
- elsif ( cmd == "jellyfish" )
- effectsmsg( "overlay hydrostat" )
- elsif ( cmd == "gluten" )
- effectsmsg( "overlay flyingtoasters" )
- elsif ( cmd =~ /^(glsnake|glmatrix|gibson|xmatrix|flyingtoasters|moebiusgears|fireworkx|hydrostat|hypertorus|jigsaw|juggler3d|kaleidocycle|kumppa|molecule|noof|polyhedra)$/ )
- effectsmsg( "overlay " + cmd )
- elsif ( cmd =~ /gltext|cowsay|xcowsay/ )
- if ( match[2]? ) && ( gltextargs = match[2].match( /^([0-9]+) +(.+)$/ ) )
- seconds=UInt64.new( 1 )
- seconds=gltextargs[1].to_u64
- if ( own || mod || vip )
- effectsmsg( "overlay #{cmd} #{match[2]}" )
- puts "matched #{cmd} #{match[2]}"
- elsif ( sub )
- if ( seconds > 20 )
- seconds=20
+ elsif ( cmd == "matrix" )
+ effectsmsg( "overlay glmatrix" )
+ elsif ( cmd =~ /juggle|juggler/ )
+ effectsmsg( "overlay juggler3d" )
+ elsif ( cmd =~ /fireworks|firework/ )
+ effectsmsg( "overlay fireworkx" )
+ elsif ( cmd == "pipes" )
+ if match[2]? && match[2] =~ /^(fast|faster)$/
+ effectsmsg( "overlay pipes " + match[2] )
+ else
+ effectsmsg( "overlay pipes" )
end
- effectsmsg( "overlay #{cmd} #{seconds} #{gltextargs[2]}" )
- puts "matched #{cmd} #{seconds} #{gltextargs[2]}"
- else
- if ( seconds > 5 )
- seconds=5
+ elsif ( cmd == "jellyfish" )
+ effectsmsg( "overlay hydrostat" )
+ elsif ( cmd == "gluten" )
+ effectsmsg( "overlay flyingtoasters" )
+ elsif ( cmd =~ /^(glsnake|glmatrix|gibson|xmatrix|flyingtoasters|moebiusgears|fireworkx|hydrostat|hypertorus|jigsaw|juggler3d|kaleidocycle|kumppa|molecule|noof|polyhedra)$/ )
+ effectsmsg( "overlay " + cmd )
+ elsif ( cmd =~ /gltext|cowsay|xcowsay/ )
+ if ( match[2]? ) && ( gltextargs = match[2].match( /^([0-9]+) +(.+)$/ ) )
+ seconds=UInt64.new( 1 )
+ seconds=gltextargs[1].to_u64
+ if ( own || mod || vip )
+ effectsmsg( "overlay #{cmd} #{match[2]}" )
+ puts "matched #{cmd} #{match[2]}"
+ elsif ( sub )
+ if ( seconds > 20 )
+ seconds=20
+ end
+ effectsmsg( "overlay #{cmd} #{seconds} #{gltextargs[2]}" )
+ puts "matched #{cmd} #{seconds} #{gltextargs[2]}"
+ else
+ if ( seconds > 5 )
+ seconds=5
+ end
+ effectsmsg( "overlay #{cmd} #{seconds} #{gltextargs[2]}" )
+ puts "matched #{cmd} #{seconds} #{gltextargs[2]}"
+ end
+ elsif match[2]? && match[2] =~ /^.+$/
+ effectsmsg( "overlay #{cmd} #{match[2]}" )
+ puts "matched #{cmd} #{match[2]}"
+ else
+ effectsmsg( "overlay #{cmd}" )
+ puts "failed to match gltext"
end
- effectsmsg( "overlay #{cmd} #{seconds} #{gltextargs[2]}" )
- puts "matched #{cmd} #{seconds} #{gltextargs[2]}"
- end
- elsif match[2]? && match[2] =~ /^.+$/
- effectsmsg( "overlay #{cmd} #{match[2]}" )
- puts "matched #{cmd} #{match[2]}"
- else
- effectsmsg( "overlay #{cmd}" )
- puts "failed to match gltext"
- end
- elsif ( cmd =~ /cow|cowabunga|holycow/ )
- if match[2]? && match[2] =~ /^([0-9])+$/
- effectsmsg( "overlay bouncingcow #{match[2]}" )
- else
- effectsmsg( "overlay bouncingcow" )
- end
- elsif ( cmd == "overlay" )
- if match[2]? && match[2] =~ /^[a-z]+$/
- ircmsg( settings["home"], settings["channel"], "| overlay requires an argument consisting wholly of lower case characters.")
- effectsmsg( "overlay #{match[2]}" )
- else
- end
- elsif ( cmd == "hackerman" )
- ircmsg( settings["home"], settings["channel"], "| https://bungmonkey.omgwallhack.org/img/hackerman.jpg" )
- elsif ( cmd =~ /^(songrequest|sr)$/ ) && match[2]?
- puts ("song detected: #{match[2]}")
- if ( ( match[2] =~ /list=/ ) && ( match[2] !~ /v=/ ) )
- ircmsg( settings["home"], settings["channel"], "| Lists are not accepted.\n" )
- elsif Process.run( "sraddsong.sh", {match[2]} )
- m = MPD::Client.new
- currentsong = m.currentsong
- if ( currentsong ) && ( currentsong["file"].to_s == "http://music/music.ogg" )
+ elsif ( cmd =~ /cow|cowabunga|holycow/ )
+ if match[2]? && match[2] =~ /^([0-9])+$/
+ effectsmsg( "overlay bouncingcow #{match[2]}" )
+ else
+ effectsmsg( "overlay bouncingcow" )
+ end
+ elsif ( cmd == "overlay" )
+ if match[2]? && match[2] =~ /^[a-z]+$/
+ ircmsg( settings["home"], settings["channel"], "| overlay requires an argument consisting wholly of lower case characters.")
+ effectsmsg( "overlay #{match[2]}" )
+ else
+ end
+ elsif ( cmd == "hackerman" )
+ ircmsg( settings["home"], settings["channel"], "| https://bungmonkey.omgwallhack.org/img/hackerman.jpg" )
+ elsif ( cmd =~ /^(songrequest|sr)$/ ) && match[2]?
+ puts ("song detected: #{match[2]}")
+ if ( ( match[2] =~ /list=/ ) && ( match[2] !~ /v=/ ) )
+ ircmsg( settings["home"], settings["channel"], "| Lists are not accepted.\n" )
+ elsif Process.run( "sraddsong.sh", {match[2]} )
+ m = MPD::Client.new
+ currentsong = m.currentsong
+ if ( currentsong ) && ( currentsong["file"].to_s == "http://music/music.ogg" )
+ m.next
+ end
+ if ( status = m.status ) && ( playlistinfo = m.playlistinfo )
+ ircmsg( settings["home"], settings["channel"], "| " + playlistinfo[ status["playlistlength"].to_i - 1 ]["file"].to_s + " added in position " + status["playlistlength"].to_s )
+ else
+ ircmsg( settings["home"], settings["channel"], "| A failure occured." )
+ end
+ m.disconnect
+ else
+ end
+ elsif ( cmd =~ /^current(|song)$/ )
+ m = MPD::Client.new
+ if ( currentsong = m.currentsong )
+ ircmsg( settings["home"], settings["channel"], "| Currently playing: " + currentsong["file"].to_s )
+ else
+ ircmsg( settings["home"], settings["channel"], "| A failure occured." )
+ end
+ m.disconnect
+ elsif ( cmd =~ /^seek$/ )
+ if ( ( match[2] ) && ( match[2] =~ /([+-]|)[0-9]/ ) )
+ m = MPD::Client.new
+ m.seekcur( match[2] )
+ if ( ( musicstatus = m.status ) && ( pos = musicstatus["elapsed"].to_f.to_u64 ) )
+ min=( pos / 60 ).to_u64
+ sec=( pos % 60 ).to_u64
+ ircmsg( settings["home"], settings["channel"], "| " + sprintf( "2%d:2%d", min, sec ) )
+ else
+ ircmsg( settings["home"], settings["channel"], "| An error occurred. " )
+ end
+ m.disconnect
+ else
+ ircmsg( settings["home"], settings["channel"], "| Seek requires an argument of an absolute position in integer number of seconds, or a relative position in in signed integer number of seconds such as +60" )
+ end
+ elsif ( cmd =~ /^next(|song)$/ )
+ m = MPD::Client.new
m.next
- end
- if ( status = m.status ) && ( playlistinfo = m.playlistinfo )
- ircmsg( settings["home"], settings["channel"], "| " + playlistinfo[ status["playlistlength"].to_i - 1 ]["file"].to_s + " added in position " + status["playlistlength"].to_s )
- else
- ircmsg( settings["home"], settings["channel"], "| A failure occured." )
- end
- m.disconnect
- else
- end
- elsif ( cmd =~ /^current(|song)$/ )
- m = MPD::Client.new
- if ( currentsong = m.currentsong )
- ircmsg( settings["home"], settings["channel"], "| Currently playing: " + currentsong["file"].to_s )
- else
- ircmsg( settings["home"], settings["channel"], "| A failure occured." )
- end
- m.disconnect
- elsif ( cmd =~ /^seek$/ )
- if ( ( match[2] ) && ( match[2] =~ /([+-]|)[0-9]/ ) )
- m = MPD::Client.new
- m.seekcur( match[2] )
- if ( ( musicstatus = m.status ) && ( pos = musicstatus["elapsed"].to_f.to_u64 ) )
- min=( pos / 60 ).to_u64
- sec=( pos % 60 ).to_u64
- ircmsg( settings["home"], settings["channel"], "| " + sprintf( "2%d:2%d", min, sec ) )
- else
- ircmsg( settings["home"], settings["channel"], "| An error occurred. " )
- end
- m.disconnect
- else
- ircmsg( settings["home"], settings["channel"], "| Seek requires an argument of an absolute position in integer number of seconds, or a relative position in in signed integer number of seconds such as +60" )
- end
- elsif ( cmd =~ /^next(|song)$/ )
- m = MPD::Client.new
- m.next
- if ( status = m.status ) && ( status["playlistlength"].to_i > 0 )
- if ( currentsong = m.nextsong )
- ircmsg( settings["home"], settings["channel"], "| Currently playing: " + currentsong["file"].to_s )
- else
- ircmsg( settings["home"], settings["channel"], "| A failure occured." )
- end
- else
- ircmsg( settings["home"], settings["channel"], "| Playlist is now empty." )
- end
- m.disconnect
- elsif ( cmd == "followage" )
- begin
- if match[2]?
- args = match[2].split(/\s/)
- if args[1]?
- json = JSON.parse( client.get_user_follows( from: client.user_id( args[0] ).to_u64 , to: client.user_id( args[1] ).to_u64 ) )
- puts client.user_id( args[0] ).to_s
- puts client.user_id( args[1] ).to_s
- puts json
- ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
- elsif args[0]?
- json = JSON.parse( client.get_user_follows( from: client.user_id( args[0] ).to_u64 , to: settings["channel_id"].to_u64 ) )
- puts client.user_id( args[0] ).to_s
- puts json
- ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
+ if ( status = m.status ) && ( status["playlistlength"].to_i > 0 )
+ if ( currentsong = m.nextsong )
+ ircmsg( settings["home"], settings["channel"], "| Currently playing: " + currentsong["file"].to_s )
+ else
+ ircmsg( settings["home"], settings["channel"], "| A failure occured." )
+ end
+ else
+ ircmsg( settings["home"], settings["channel"], "| Playlist is now empty." )
+ end
+ m.disconnect
+ elsif ( cmd == "followage" )
+ begin
+ if match[2]?
+ args = match[2].split(/\s/)
+ if args[1]?
+ json = JSON.parse( client.get_user_follows( from: client.user_id( args[0] ).to_u64 , to: client.user_id( args[1] ).to_u64 ) )
+ puts client.user_id( args[0] ).to_s
+ puts client.user_id( args[1] ).to_s
+ puts json
+ ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
+ elsif args[0]?
+ json = JSON.parse( client.get_user_follows( from: client.user_id( args[0] ).to_u64 , to: settings["channel_id"].to_u64 ) )
+ puts client.user_id( args[0] ).to_s
+ puts json
+ ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
+ end
+ else
+ json = JSON.parse( client.get_user_follows( from: uid.to_u64 , to: settings["channel_id"].to_u64 ) )
+ puts json
+ ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
+ end
+ rescue ex
+ ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
end
- else
- json = JSON.parse( client.get_user_follows( from: uid.to_u64 , to: settings["channel_id"].to_u64 ) )
- puts json
- ircmsg( settings["home"], settings["channel"], "| " + json["data"][0]["followed_at"].to_s )
end
- rescue ex
- ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
+ end
end
- end
- end
-end
-
-rooms = Array( String ).new
-rooms = [ "#bungmonkey", "kr3wzz" ]
+ rooms = Array( String ).new
+ rooms = [ "#bungmonkey", "kr3wzz" ]
-while true
- begin
-# Connect to Twitch
+ # Connect to Twitch
bot.run( rooms.map{ | room | room.sub( /^#/, "") } )
rescue ex : IO::Error
pp ex
+ sleep 1
# loop to reconnect
rescue ex
pp ex