diff options
author | Joe Rayhawk <jrayhawk+git@omgwallhack.org> | 2024-02-26 18:34:17 -0800 |
---|---|---|
committer | Joe Rayhawk <jrayhawk@fairlystable.org> | 2024-02-27 03:14:39 -0800 |
commit | 545d60e306e29b39a58f4467b799d55f1b82b854 (patch) | |
tree | 244c2629a8863a2473b446eb355f281c386da9f7 | |
parent | e04324d824a2e427c7229bd6b58006a26e16202f (diff) | |
download | twitchtools-545d60e306e29b39a58f4467b799d55f1b82b854.tar.gz twitchtools-545d60e306e29b39a58f4467b799d55f1b82b854.zip |
crystal/tcpsocket.cr: add OptionsParser
-rw-r--r-- | crystal/tcpsocket.cr | 467 |
1 files changed, 274 insertions, 193 deletions
diff --git a/crystal/tcpsocket.cr b/crystal/tcpsocket.cr index c9cdf84..8194eb6 100644 --- a/crystal/tcpsocket.cr +++ b/crystal/tcpsocket.cr @@ -10,10 +10,13 @@ require "crystal_mpd" require "obswebsocket" require "yaml" require "bungmobott" +require "file_utils" +require "option_parser" STDOUT.sync = true STDOUT.flush_on_newline = true +# Convenience mixins struct Nil def as_s? self @@ -40,6 +43,25 @@ class OpenSSL::SSL::Socket::Client end end +macro send_and_log( ifc, value ) + puts( "#{Fiber.current.name} tx {{ifc}}: #{{{value}}}" ) + {{ifc}}.send( {{value}} ) +end + +# IRC say +macro say( service, channel, text ) + case {{service}} + when "twitch" + send_and_log( twitchircifc, { "#" + {{channel}}, {{text}} } ) + when "gamesurge" + send_and_log( gamesurgeircifc, { "#" + {{channel}}, {{text}} } ) + when "twitch_remote" + send_and_log( bbscliifc, "say twitch " + {{text}} ) + when "gamesurge_remote" + send_and_log( bbscliifc, "say gamesurge " + {{text}} ) + end +end + # Say() in all available primary channels macro say_all_self_chan( text ) if fibers["Twitch::IRC"]? @@ -55,21 +77,6 @@ macro say_all_self_chan( text ) end end -# IRC say -macro say( service, channel, text ) -#def say( ipc : Channel( Tuple( String, String ) ), channel : String, text : String ) - case {{service}} - when "twitch" - twitchircipc.send( { "#" + {{channel}}, {{text}} } ) - when "gamesurge" - ircipc.send( { "#" + {{channel}}, {{text}} } ) - when "twitch_remote" - bbscliipc.send( "say twitch " + {{text}} ) - when "gamesurge_remote" - bbscliipc.send( "say gamesurge " + {{text}} ) - end -end - macro testrefuser2uid( path ) {% if flag?(:windows) %} File.exists?( {{path}} ) && ( File.read( {{ path }} ) =~ /^[0-9]+$/ ) @@ -113,9 +120,34 @@ rescue exio : IO::Error end configfile = Path[configdir + "config.txt"].normalize -if ARGV.size >= 1 - configfile = Path[ ARGV[0] ].normalize +if File.exists?( File.expand_path( "config.txt" ) ) + configfile = Path[File.expand_path( "config.txt" )].normalize +end + +secretsfile = Path[ configdir + "secrets.txt" ].normalize +if File.exists?( File.expand_path( "secrets.txt" ) ) + secretsfile = Path[File.expand_path( "secrets.txt" )].normalize end + +OptionParser.parse do |parser| + parser.banner = "Usage: #{PROGRAM_NAME} (arguments...)" + parser.on("-c FILE", "--config=FILE", "YAML configuration file") { |file| configfile = Path[file].normalize } + parser.on("-s FILE", "--secrets=FILE", "YAML secrets file") { |file| secretsfile = Path[file].normalize } + {% if flag?(:windows) %} + parser.on("--install-mss-voices", "Download and install Microsoft Speech Services voices") do + t2s_mss_voice_install() + end + {% end %} + parser.on("-h", "--help", "Show help") do + puts( parser ) + exit + end + parser.invalid_option do |flag| + STDERR.puts "ERROR: #{flag} is not a valid option." + STDERR.puts parser + end +end + puts configfile if File.exists?( configfile ) @@ -144,10 +176,6 @@ if ( config.join_channels && ! config.join_channels.not_nil!.yaml_unmapped.empty ppe config.join_channels.not_nil!.yaml_unmapped end -secretsfile = Path[ configdir + "secrets.txt" ].normalize -if ARGV.size >= 2 - secretsfile = Path[ ARGV[1] ].normalize -end if File.exists?( secretsfile ) secrets = BungmoBott::Secrets.from_yaml( File.read( secretsfile ) ) @@ -260,7 +288,7 @@ if ( mss || gcloud || aws ) && config.voice_list text2speech = true if File.exists?( config.voice_list.not_nil! ) File.read( config.voice_list.not_nil! ).strip.split( "\n" ).each do |voice| - voices[voice.downcase] = voice.strip + voices[voice.strip.downcase] = voice.strip end #else #regeneratevoicelist() @@ -271,36 +299,34 @@ end lastvoice = Array(String).new -# channel message subscriptions: { service, chan } => [ client, client ] -#channelsubs = Hash( Tuple( String, String ), Array( OpenSSL::SSL::Socket::Server | Channel( Tuple( String, FastIRC::Message ) ) ) ).new +# Inter-Fiber Communication Channels +# BungmoBott::Socket IRC channel subscriptions: { { service, chan } => [ client, client ] } channelsubs = Hash( Tuple( String, String ), Array( OpenSSL::SSL::Socket::Server) ).new # Unencrypted #connections = Hash(TCPSocket, Hash(String, String)).new # Encrypted connections = Hash(OpenSSL::SSL::Socket::Server, Hash(String, String)).new -ircipc = Channel( Tuple( String, String ) ).new -# commandircipc: serv, chan, user, msg -commandircipc = Channel( Tuple( String, FastIRC::Message ) ).new -commandipc = Channel( String ).new -# t2sipc: voice, text -t2sipc = Channel( Tuple( String, String ) ).new -gamesurgeircipc = Channel( Tuple( String, String ) ).new -twitchircipc = Channel( Tuple( String, String ) ).new -twitchapiipc = Channel( Tuple( String, String | UInt64 ) ).new -bbscliipc = Channel( String ).new -bbssrvipc = Channel( String ).new +gamesurgeircifc = Channel( Tuple( String, String ) ).new +# commandifc: serv, chan, user, msg +commandifc = Channel( Tuple( String, FastIRC::Message ) ).new +# t2sifc: voice, text +t2sifc = Channel( Tuple( String, String ) ).new +twitchircifc = Channel( Tuple( String, String ) ).new +twitchapiifc = Channel( Tuple( String, String | UInt64 ) ).new +bbscliifc = Channel( String ).new +# currently unused +#bbssrvifc = Channel( String ).new waitgroup = Channel( String ).new - -fiberipc = Channel( Fiber ).new +fiberifc = Channel( Fiber ).new fibers = Hash( String, Fiber ).new evchan = Channel( JSON::Any ).new obs : Nil | OBS::WebSocket = nil if config.obs_connect obs = OBS::WebSocket.new( "ws://#{config.obs_connect}/", secrets.obs_password ) - # OBS event thread - spawn name: "obs_event_thread" do - fiberipc.send( Fiber.current ) + # OBS event fiber + spawn name: "OBS::WebSocket" do + fiberifc.send( Fiber.current ) obs.scenes["meta-foreground"].to_h.each_key do | key | if key =~ /^media-temporary-/ obs.inputs[key].delete! @@ -309,7 +335,7 @@ if config.obs_connect 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 + spawn name: "OBS::WebSocket event" do d = json # Copy *immediately* case d["eventType"].as_s when "CurrentProgramSceneChanged" @@ -355,8 +381,9 @@ if config.obs_connect pp ex ensure waitgroup.send( Fiber.current.name.not_nil! ) + puts( "#{Fiber.current.name} tx waitgroup: #{Fiber.current.name}" ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end @@ -398,16 +425,18 @@ def urbandef( term : String ) end # FIXME: maybe break this out into separate functions later -def getvoice( voicelist : String, userdir : String, chatuser : String ) - if File.exists?( userdir + "/voice" ) - voice_output = File.read( userdir + "/voice" ).strip +def getvoice( voicelist : String, userdir : Path, chatuser : String ) + voicefile = Path.new( userdir, "voice" ).normalize + voicenamesubfile = Path.new( userdir, "voicesub" ).normalize + if File.exists?( voicefile ) + voice_output = File.read( voicefile ).strip voice_setting = voice_output else voice_output = File.read( voicelist ).strip.split( "\n" ).sample( 1 )[0].strip voice_setting = "random" end - if File.exists?( userdir + "/voicesub" ) - namesub = File.read( userdir + "/voicesub" ).strip + if File.exists?( voicenamesubfile ) + namesub = File.read( voicenamesubfile ).strip else namesub = chatuser end @@ -417,7 +446,7 @@ end def generatevoicelistaws( ) voices = Array(String).new JSON.parse( `aws polly describe-voices` )["Voices"].as_a.each do | v | - voices.push( v["Id"].as_s ) + voices.push( v["Id"].as_s.strip ) end return voices end @@ -430,7 +459,7 @@ def generatevoicelistgcs( gcloud_token : String ) response = HTTP::Client.exec( "GET", "https://texttospeech.googleapis.com/v1/voices?key=#{gcloud_token}", headers, nil, tls: ssl_context ) JSON.parse( response.body )["voices"].as_a.each do | v | STDERR.puts( "#{v["naturalSampleRateHertz"]} #{v["languageCodes"]} #{v["name"]}" ) - voices.push( v["name"].as_s ) + voices.push( v["name"].as_s.strip ) end return voices end @@ -452,9 +481,13 @@ def generatevoicelistwin() v = v.gsub(/ Desktop$/, "") v = v.gsub( " ", "-" ) if v =~ /[A-Za-z0-9]-[A-Za-z0-9]/ - voices.push( v ) + voices.push( v.strip ) end end + if ( voices.size < 10 ) + puts( "WARNING: Microsoft Speech Service voice count is suspiciously low." ) + puts( "You may want to visit https://www.microsoft.com/en-us/download/details.aspx?id=27224" ) + end return voices end {% end %} @@ -467,21 +500,23 @@ end macro regeneratevoicelist() if aws generatevoicelistaws().each do | voice | - voices[ voice.downcase ] = voice.strip + voices[ voice.downcase ] = voice end elsif fibers["BungmoBott::Socket client"]? - bbscliipc.send( "awsvoicelist" ) + bbscliifc.send( "awsvoicelist" ) + puts( "#{Fiber.current.name} tx bbscliifc: awsvoicelist" ) end if secrets.gcloud_token generatevoicelistgcs( secrets.gcloud_token.not_nil! ).each do | voice | - voices[ voice.downcase ] = voice.strip + voices[ voice.downcase ] = voice end elsif fibers["BungmoBott::Socket client"]? - bbscliipc.send( "gcsvoicelist" ) + bbscliifc.send( "gcsvoicelist" ) + puts( "#{Fiber.current.name} tx bbscliifc: gcsvoicelist" ) end {% if flag?(:windows) %} generatevoicelistwin().each do | voice | - voices[ voice.downcase ] = voice.strip + voices[ voice.downcase ] = voice end {% end %} writevoices() @@ -499,14 +534,14 @@ def file_list( path : String ) : Array( String ) end # TODO: add piping into mpv on POSIX -def playaudiodata( tempdir, data : Bytes ) - filepath="#{tempdir}#{Time.utc.to_unix_ms}.mp3" +def playaudiodata( tempdir : Path | String, data : Bytes ) + filepath=Path.new( tempdir, "#{Time.utc.to_unix_ms}.mp3" ).normalize File.write( filepath, data ) playaudiofile( filepath ) File.delete( filepath ) end -def playaudiofile( filepath : String ) +def playaudiofile( filepath : Path ) {% if flag?(:windows) %} p = Process.new( "powershell.exe", @@ -535,36 +570,36 @@ def playaudiofile( filepath : String ) end # user, uid, userdir,lastseen, oldname -def userlog( config : BungmoBott::Config, service : String, message : FastIRC::Message ) : Tuple( String, UInt64 | Nil, String, Int32 | Int64, String | Nil ) | Nil +def userlog( config : BungmoBott::Config, service : String, message : FastIRC::Message ) : Tuple( String, UInt64 | Nil, Path, Int32 | Int64, String | Nil ) | Nil unless ( ( prefix = message.prefix ) && ( chatuser = prefix.source ) ) return nil end if service =~ /^twitch/ if ( uid = message.tags["user-id"]? ) - basedir = config.statedir + "/twitch" - userdir = basedir + "/uids/" + uid + basedir = Path.new( config.statedir, "twitch" ).normalize + userdir = Path.new( basedir, "uids", uid ).normalize if File.directory?( userdir ) lastseen = File.info( userdir ).modification_time.to_unix else lastseen = 0 end - Dir.mkdir_p( basedir + "/names" ) - Dir.mkdir_p( userdir + "/names" ) + Dir.mkdir_p( Path.new( basedir, "names" ).normalize ) + Dir.mkdir_p( Path.new( userdir, "names" ).normalize ) File.touch( userdir ) - unless testrefuser2uid( userdir + "/names/" + chatuser ) + unless testrefuser2uid( Path.new( userdir, "names", chatuser ).normalize ) oldname = nil datelatest = Time::UNIX_EPOCH - Dir.each_child( userdir + "/names/" ) do |name| - namedate = File.info( userdir + "/names/" + name ).modification_time + Dir.each_child( Path.new( userdir, "names" ).normalize ) do |name| + namedate = File.info( Path.new( userdir, "names", name ).normalize ).modification_time if namedate > datelatest oldname = name datelatest = namedate end end - genrefuser2uid( userdir + "/names/" + chatuser, uid, 3 ) + genrefuser2uid( Path.new( userdir, "names", chatuser ).normalize, uid, 3 ) end - unless testrefuser2uid( basedir + "/names/" + chatuser ) - genrefuser2uid( basedir + "/names/" + chatuser, uid, 1 ) + unless testrefuser2uid( Path.new( basedir, "names", chatuser ).normalize ) + genrefuser2uid( Path.new( basedir, "names", chatuser ).normalize, uid, 1 ) end uid = uid.to_u64 else # No uid? @@ -572,8 +607,8 @@ def userlog( config : BungmoBott::Config, service : String, message : FastIRC::M return( nil ) end elsif( service =~ /^gamesurge/ ) - basedir = config.statedir + "/gamesurge" - userdir = basedir + "/names/" + chatuser + basedir = Path.new( config.statedir, "gamesurge" ).normalize + userdir = Path.new( basedir, "names", chatuser ).normalize if File.directory?( userdir ) lastseen = File.info( userdir ).modification_time.to_unix File.touch( userdir ) @@ -592,6 +627,42 @@ rescue ex return nil end +{% if flag?(:windows) %} +def t2s_mss_voice_install() + puts "Downloading Microsoft Speech Services voice index" + puts "https://www.microsoft.com/en-us/download/details.aspx?id=27224" + ENV["TEMP"]? || ( STDERR.puts "TEMP environment variable undefined" && exit 2 ) + ssl_context = OpenSSL::SSL::Context::Client.new + response = HTTP::Client.exec( "GET", "https://www.microsoft.com/en-us/download/details.aspx?id=27224", tls: ssl_context ) + if ( response.status_code == 200 ) + response.body.split("\"").select(/^https.+MSSpeech.+\.msi$/).each do | msi_url | + puts "Downloading: #{msi_url}" + ssl_context = OpenSSL::SSL::Context::Client.new + response = HTTP::Client.exec( "GET", msi_url, tls: ssl_context ) + if ( ( response.status_code == 200 ) && ( response.content_type == "application/octet-stream" ) && ( match = /^.+\/(.+msi)$/.match(msi_url) ) ) + msi_path = Path.new( Path[ENV["LOCALAPPDATA"]].normalize, "Temp", match[1] ) + puts "Writing : #{msi_path}" + File.write( msi_path, response.body ) + puts "Installing : #{msi_path}" + p = Process.new( + "msiexec", [ "/i", msi_path.normalize.to_s ], output: STDOUT, error: STDERR, + ) + p.wait + puts "Deleting : #{msi_path}" + File.delete( msi_path ) + else + end + end + else + puts response.status_code + pp response.headers + puts response.body + exit 1 + end + exit +end +{% end %} + # Currently only used in flag?(:unix) def t2smsg( config : BungmoBott::Config, msg : String) if File.exists?( config.rundir + "/.t2s.sock" ) @@ -604,7 +675,7 @@ rescue ex pp ex end -def t2s( t2sipc : Channel, config : BungmoBott::Config, userdir : String, chatuser : String, text : String ) +def t2s( t2sifc : Channel, config : BungmoBott::Config, userdir : Path, chatuser : String, text : String ) if ( text !~ /^ *(!|\|)/ ) namesub, voice_setting, voice = getvoice( config.voice_list.not_nil!, userdir, chatuser ) subs = Array( Tuple( Regex, String ) ){ @@ -652,7 +723,8 @@ def t2s( t2sipc : Channel, config : BungmoBott::Config, userdir : String, chatus text = text.gsub( subtuple[0], subtuple[1] ) end #{% if flag?(:windows) %} - t2sipc.send( { voice, "#{namesub} #{text}" } ) + t2sifc.send( { voice, "#{namesub} #{text}" } ) + puts( "#{Fiber.current.name} tx t2sifc: #{voice}, #{namesub} #{text}" ) #{% else %} # t2smsg( config, "#{voice} #{namesub} #{text}" ) #{% end %} @@ -663,12 +735,13 @@ def t2s( t2sipc : Channel, config : BungmoBott::Config, userdir : String, chatus end spawn name: "command_dispatch" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do - while commandmsg : Tuple( String, FastIRC::Message ) = commandircipc.receive - spawn do + while commandmsg : Tuple( String, FastIRC::Message ) = commandifc.receive + spawn name: "command_dispatch ifc rx" do service = String.new local_commandmsg = commandmsg + puts( "#{Fiber.current.name}: #{local_commandmsg}" ) if local_commandmsg.is_a?( Tuple( String, FastIRC::Message ) ) && local_commandmsg[0].is_a?( String ) service = local_commandmsg[0] message : FastIRC::Message = local_commandmsg[1] @@ -676,7 +749,8 @@ spawn name: "command_dispatch" do unless service.empty? if config.bungmobott_listen && ! ircchannel.empty? # Do we send to the bungmobott_listen fiber? Probably no need. - #bbssrvipc.send( "#{message.to_s}" ) + #bbssrvifc.send( "#{message.to_s}" ) + #puts( "#{Fiber.current.name} tx bbssrvifc: #{message.to_s}" ) if channelsubs[ { service, ircchannel } ]? channelsubs[ { service, ircchannel } ].each do |channelsub| if channelsub.is_a? OpenSSL::SSL::Socket::Server @@ -688,13 +762,18 @@ spawn name: "command_dispatch" do next unless ( userlogreturn = userlog( config, service, message ) ) chatuser, uid, userdir, lastseen, oldname = userlogreturn + pp userlogreturn # Have we seen this user lately? if ( ( Time.utc.to_unix - lastseen ) >= 14400 ) if service =~ /^twitch/ && uid.is_a?( UInt64 ) - twitchapiipc.send( { "get_user", uid.to_s } ) - twitchapiipc.send( { "get_followers", uid.to_s } ) + if twitchapi + puts( "#{Fiber.current.name} tx twitchapiifc: get_user, #{uid}" ) + twitchapiifc.send( { "get_user", uid.to_s } ) + puts( "#{Fiber.current.name} tx twitchapiifc: get_followers, #{uid}" ) + twitchapiifc.send( { "get_followers", uid.to_s } ) + end prevnames = Array( String ).new - if ( prevnames = Dir.children( "#{userdir}/names" ) ) && ( prevnames.size > 1 ) + if ( prevnames = Dir.children( Path.new( userdir, "names" ).normalize ) ) && ( prevnames.size > 1 ) prevnames.delete( chatuser ) puts "\033[38;5;14m#{chatuser} previous names: #{prevnames.join(", ")}\033[0m" end @@ -703,8 +782,8 @@ spawn name: "command_dispatch" do # This file hierarchy gets manually set up for now. # Maybe someday let mods do something like: # !fanfare add pipne https://pip.ne/sniff.mp3 - if File.exists?( userdir + "/fanfare/" ) - playaudiofile( userdir + "/fanfare/" + Dir.children( userdir + "/fanfare/" ).sample ) + if File.exists?( Path.new( userdir, "fanfare" ).normalize ) + playaudiofile( Path.new( userdir, "fanfare", Dir.children( Path.new( userdir, "fanfare" ).normalize ).sample ).normalize ) end end # FIXME: Generalize this across Twitch/IRC? Mods are +o? vips are +v? @@ -757,9 +836,8 @@ spawn name: "command_dispatch" do # As a matter of policy: # BungmoBott::Socket clients can only say things in their own authenticated channel # Direct IRC clients can say things whereever. - # FIXME: this needs to be service-specific if ( service =~ /^twitch/ && exec.func == "detect_rename" && uid.is_a?( UInt64 ) ) - unless oldname.is_a?( String ) + if oldname.is_a?( String ) say( service, config.chat_user.not_nil!.twitch.not_nil!, "Rename detected: #{uid}: #{oldname} -> #{chatuser}" ) end next @@ -851,9 +929,11 @@ spawn name: "command_dispatch" do end end if text2speech + voicenamesubfile = Path.new( userdir, "voicesub" ).normalize + voicefile = Path.new( userdir, "voice" ).normalize if ( exec.func == "text_to_speech" ) puts "Exec-ing text_to_speech" - if ( t2sreturn = t2s( t2sipc, config, userdir, chatuser, message.params[1] ) ) + if ( t2sreturn = t2s( t2sifc, config, userdir, chatuser, message.params[1] ) ) lastvoice.insert( 0, t2sreturn.strip ) lastvoice = lastvoice[0..4] end @@ -884,8 +964,8 @@ spawn name: "command_dispatch" do if ( match = / ([a-zA-Z0-9-_]+)/.match( message.params[1] ) ) voice = match[1].downcase if voice =~ /disabled|null|disable|none|random/ - if File.exists?( userdir + "/voice" ) - File.delete( userdir + "/voice" ) + if File.exists?( voicefile ) + File.delete( voicefile ) say( service, ircchannel, "| Voice for #{chatuser} is now random." ) else say( service, ircchannel, "| Voice for #{chatuser} is already random." ) @@ -893,9 +973,9 @@ spawn name: "command_dispatch" do elsif voices.has_key?( voice.downcase ) csvoice = voices[voice] Dir.mkdir_p( userdir ) - File.write( userdir + "/voice", csvoice ) + File.write( voicefile, csvoice ) pp userdir - say( service, ircchannel, "| Voice for #{chatuser} is now #{File.read( userdir + "/voice" ).strip}." ) + say( service, ircchannel, "| Voice for #{chatuser} is now #{File.read( voicefile ).strip}." ) else pp ( match ) say( service, ircchannel, "| Invalid voice. To see list, use !voices" ) @@ -907,8 +987,8 @@ spawn name: "command_dispatch" do end if ( exec.func == "tts_name_get" ) puts "Exec-ing " + exec.func - if File.exists?( userdir + "/voicesub" ) - say( service, ircchannel, "| Current name substitution is \"#{File.read( userdir + "/voicesub" ).strip}\"." ) + if File.exists?( voicenamesubfile ) + say( service, ircchannel, "| Current name substitution is \"#{File.read( voicenamesubfile ).strip}\"." ) else say( service, ircchannel, "| Current name substitution is disabled." ) end @@ -919,16 +999,16 @@ spawn name: "command_dispatch" do pp match[1] voicesub = match[1].downcase if voicesub =~ /^(disabled|null|disable|none)$/ - if File.exists?( userdir + "/voicesub" ) - File.delete( userdir + "/voicesub" ) + if File.exists?( voicenamesubfile ) + File.delete( voicenamesubfile ) say( service, ircchannel, "| Name substitution for #{chatuser} is now disabled." ) else say( service, ircchannel, "| Name substitution for #{chatuser} is already disabled." ) end else Dir.mkdir_p( userdir ) - File.write( userdir + "/voicesub", voicesub ) - say( service, ircchannel, "| Name substitution for #{chatuser} is now \"#{File.read( userdir + "/voicesub" ).strip}\"." ) + File.write( voicenamesubfile, voicesub ) + say( service, ircchannel, "| Name substitution for #{chatuser} is now \"#{File.read( voicenamesubfile ).strip}\"." ) end end next @@ -986,62 +1066,62 @@ spawn name: "command_dispatch" do # # download url, verify mimetype with libmagic, duplicate existing medialoop source, change "file" SourceSetting # elsif ( ( cmd =~ /^inputsetting(|s)$/ ) && ( mod || own || vip ) ) # if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ ) -# ircipc.send( { "##{settings["channel"]}", "| #{obs.inputs[match[2]].settings.to_h.to_s} " } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| #{obs.inputs[match[2]].settings.to_h.to_s} " } ) # end # elsif ( cmd == "create" && ( mod || own || vip ) ) # if ( match[2]? ) && ( match[2] =~ /^([\/a-zA-Z0-9-_]+)/ ) # obstemporarymediacreate( obs, "meta-foreground", match[2], "C:/cygwin64/home/user/effects/#{match[2]}.webm" ) # else -# ircipc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Must provide at least one source name as argument." } ) # end # # FIXME: This is only half-implemented # elsif ( ( cmd =~ /^(user)$/ ) && ( mod || own ) ) # if match[2]? && match[2] =~ /[a-z][a-z0-9_]+/ -# twitchapiipc.send( { "get_user", match[2] } ) +# twitchapiifc.send( { "get_user", match[2] } ) # elsif match[2]? && match[2] =~ /[0-9]+/ -# twitchapiipc.send( { "get_user", match[2].to_u64 } ) +# twitchapiifc.send( { "get_user", match[2].to_u64 } ) # else -# twitchapiipc.send( { "get_user", settings["channel_id"].to_u64 } ) +# twitchapiifc.send( { "get_user", settings["channel_id"].to_u64 } ) # end # elsif ( ( cmd =~ /^(status|title)$/ ) && ( mod || own ) ) # 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 ) ) -# ircipc.send( { "##{settings["channel"]}", "Title is now \"#{ json["data"][0]["title"] }\""} ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Title is now \"#{ json["data"][0]["title"] }\""} ) # else # json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) ) -# ircipc.send( { "##{settings["channel"]}", "| Title is currently \"#{ json["data"][0]["title"] }\""} ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Title is currently \"#{ json["data"][0]["title"] }\""} ) # end # elsif ( ( cmd =~ /^(game|category)$/ ) && ( mod || own ) ) # 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 ) ) -# ircipc.send( { "##{settings["channel"]}", "Game is now \"#{ json["data"][0]["game_name"] }\""} ) +# gamesurgeircifc.send( { "##{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 ) ) -# ircipc.send( { "##{settings["channel"]}", "| Game is currently \"#{ json["data"][0]["game_name"] }\""} ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Game is currently \"#{ json["data"][0]["game_name"] }\""} ) # end # elsif ( ( cmd == "urban" ) && ( mod || own || sub || vip ) ) # if match[2]? && match[2] =~ /^([a-zA-Z0-9 -])+$/ # definition = urbandef( match[2] ) -# ircipc.send( { "##{settings["channel"]}", definition[0,400] } ) -# t2s( t2sipc, settings, userdir, chatuser, definition[0,400] ) +# gamesurgeircifc.send( { "##{settings["channel"]}", definition[0,400] } ) +# t2s( t2sifc, settings, userdir, chatuser, definition[0,400] ) # else -# ircipc.send( { "##{settings["channel"]}", "| Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." } ) # end # elsif ( cmd =~ /^(shout|shoutout)$/ ) # if match[2]? && match[2] =~ /^[a-z]+$/ -# ircipc.send( { "##{settings["channel"]}", "| Go check out twitch.tv/#{match[2]}"} ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Go check out twitch.tv/#{match[2]}"} ) # effectsmsg( settings, "overlay gltext 5 Go follow #{match[2]}" ) # else -# ircipc.send( { "##{settings["channel"]}", "| Missing argument."} ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Missing argument."} ) # end # elsif ( cmd =~ /^(songrequest|sr)$/ ) && match[2]? # puts ("song detected: #{match[2]}") # if ( ( match[2] =~ /list=/ ) && ( match[2] !~ /v=/ ) ) -# ircipc.send( { "##{settings["channel"]}", "| Lists are not accepted.\n" } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Lists are not accepted.\n" } ) # elsif Process.run( "sraddsong.sh", {match[2]} ) # m = MPD::Client.new # currentsong = m.currentsong @@ -1049,9 +1129,9 @@ spawn name: "command_dispatch" do # m.next # end # if ( status = m.status ) && ( playlistinfo = m.playlistinfo ) -# ircipc.send( { "##{settings["channel"]}", "| " + playlistinfo[ status["playlistlength"].to_i - 1 ]["file"].to_s + " added in position " + status["playlistlength"].to_s } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| " + playlistinfo[ status["playlistlength"].to_i - 1 ]["file"].to_s + " added in position " + status["playlistlength"].to_s } ) # else -# ircipc.send( { "##{settings["channel"]}", "| A failure occured." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| A failure occured." } ) # end # m.disconnect # else @@ -1059,9 +1139,9 @@ spawn name: "command_dispatch" do # elsif ( cmd =~ /^current(|song)$/ ) # m = MPD::Client.new # if ( currentsong = m.currentsong ) -# ircipc.send( { "##{settings["channel"]}", "| Currently playing: " + currentsong["file"].to_s } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Currently playing: " + currentsong["file"].to_s } ) # else -# ircipc.send( { "##{settings["channel"]}", "| A failure occured." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| A failure occured." } ) # end # m.disconnect # elsif ( cmd =~ /^seek$/ ) @@ -1071,25 +1151,25 @@ spawn name: "command_dispatch" do # if ( ( musicstatus = m.status ) && ( pos = musicstatus["elapsed"].to_f.to_u64 ) ) # min=( pos / 60 ).to_u64 # sec=( pos % 60 ).to_u64 -# ircipc.send( { "##{settings["channel"]}", "| " + sprintf( "2%d:2%d", min, sec ) } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| " + sprintf( "2%d:2%d", min, sec ) } ) # else -# ircipc.send( { "##{settings["channel"]}", "| An error occurred. " } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| An error occurred. " } ) # end # m.disconnect # else -# ircipc.send( { "##{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" } ) +# gamesurgeircifc.send( { "##{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 ) -# ircipc.send( { "##{settings["channel"]}", "| Currently playing: " + currentsong["file"].to_s } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Currently playing: " + currentsong["file"].to_s } ) # else -# ircipc.send( { "##{settings["channel"]}", "| A failure occured." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| A failure occured." } ) # end # else -# ircipc.send( { "##{settings["channel"]}", "| Playlist is now empty." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| Playlist is now empty." } ) # end # m.disconnect # elsif ( cmd == "followage" ) @@ -1100,17 +1180,17 @@ spawn name: "command_dispatch" do # puts client.user_id( args[0] ).to_s # puts client.user_id( args[1] ).to_s # puts json -# ircipc.send( { "##{settings["channel"]}", "| " + json["data"][0]["followed_at"].to_s } ) +# gamesurgeircifc.send( { "##{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 -# ircipc.send( { "##{settings["channel"]}", "| " + json["data"][0]["followed_at"].to_s } ) +# gamesurgeircifc.send( { "##{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 -# ircipc.send( { "##{settings["channel"]}", "| " + json["data"][0]["followed_at"].to_s } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| " + json["data"][0]["followed_at"].to_s } ) # end # end rescue ex @@ -1123,7 +1203,7 @@ spawn name: "command_dispatch" do ensure waitgroup.send( Fiber.current.name.not_nil! ) end -fiber = fiberipc.receive +fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber def ttsgcs( languagecode : String, voice : String, text : String, gcskey : String ) : Bytes @@ -1146,26 +1226,26 @@ def ttsgcs( languagecode : String, voice : String, text : String, gcskey : Strin return Base64.decode( json["audioContent"].as_s ) end -def ttsaws( filepath : String, voice : String, text : String ) +def ttsaws( filepath : Path, voice : String, text : String ) p = Process.new( "aws", [ "polly", "synthesize-speech", "--output-format", "mp3", "--voice-id", voice, "--text", text, - filepath + filepath.to_s ], output: STDOUT, error: STDERR ) p.wait end - -# Put tts stuff into the same thread so each playback blocks the next +# Put tts stuff into the same fiber so each playback blocks the next spawn name: "text2speech" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do begin - while t2stuple = t2sipc.receive + while t2stuple = t2sifc.receive + puts( "#{Fiber.current.name}: #{t2stuple}" ) voice, text = [ *t2stuple ] if ( match = voice.match( /^Microsoft-([A-Za-z]+)/ ) ) {% if flag?(:windows) %} @@ -1196,19 +1276,19 @@ spawn name: "text2speech" do mp3data = ttsgcs( match[1], voice, text, gcloud_token ) playaudiodata( config.tempdir, mp3data ) elsif fibers["BungmoBott::Socket client"]? - bbscliipc.send( "gcst2s #{voice} #{text}" ) + bbscliifc.send( "gcst2s #{voice} #{text}" ) # The rest of this is dealt with in the BungmoBott::Socket client else STDERR.puts( "ERROR: google cloud voice requested, but no gcloud_token or BungmoBott::Socket client is available" ) end else if aws # AWS polly voices - filepath="#{config.tempdir}#{Time.utc.to_unix_ms}.mp3" + filepath=Path.new( config.tempdir, "#{Time.utc.to_unix_ms}.mp3" ).normalize ttsaws( filepath, voice, text ) playaudiofile( filepath ) File.delete( filepath ) elsif fibers["BungmoBott::Socket client"]? - bbscliipc.send( "awst2s #{voice} #{text}" ) + bbscliifc.send( "awst2s #{voice} #{text}" ) # The rest of this is dealt with in the BungmoBott::Socket client else STDERR.puts( "ERROR: aws polly voice requested, but no aws CLI executable or BungmoBott::Socket client is available" ) @@ -1224,19 +1304,20 @@ spawn name: "text2speech" do ensure waitgroup.send( Fiber.current.name.not_nil! ) end -fiber = fiberipc.receive +fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber -# Twitch API request handling thread +# Twitch API request handling fiber # FIXME: Implement ratelimiting here. if twitchclient.is_a?( Twitcr::Client ) spawn name: "Twitcr::Client" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do begin - while twitchtuple = twitchapiipc.receive + while twitchtuple = twitchapiifc.receive + puts( "#{Fiber.current.name}: #{twitchtuple}" ) cmd, arg = [ *twitchtuple ] case cmd when "get_user" @@ -1263,24 +1344,25 @@ if twitchclient.is_a?( Twitcr::Client ) ensure waitgroup.send( Fiber.current.name.not_nil! ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end if ( secrets.twitch_access_token && config.chat_user.not_nil!.twitch && config.join_channels.not_nil!.twitch ) - # Twitch::IRC thread + # Twitch::IRC fiber spawn name: "Twitch::IRC" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do begin bot = Twitch::IRC::Client.new( nick: config.chat_user.not_nil!.twitch.not_nil!, token: "oauth:" + secrets.twitch_access_token.not_nil!, log_mode: true ) bot.tags = [ "membership", "tags", "commands" ] - # Outgoing IRC message thread + # Outgoing IRC message fiber # "Most IRC servers limit messages to 512 bytes in length, including the trailing CR-LF characters." # PRIVMSG #channel message\r\n - spawn do - while tuple = twitchircipc.receive # why does this need to be a tuple? + spawn name: "Twitch::IRC ifc rx" do + while tuple = twitchircifc.receive # why does this need to be a tuple? + puts( "#{Fiber.current.name}: #{tuple}" ) sizelimit=( 512 - ( tuple[0].size + 12 ) ) if ( tuple[0] == "JOIN" ) if ( tuple[0] =~ regextwitchuser ) @@ -1296,7 +1378,7 @@ if ( secrets.twitch_access_token && config.chat_user.not_nil!.twitch && config.j # Create a handler to process incoming messages bot.on_message do |message| - spawn do + spawn name: "Twitch::IRC irc rx" do #FastIRC::Message( # @tags={ # "badge-info" => "", @@ -1338,12 +1420,12 @@ if ( secrets.twitch_access_token && config.chat_user.not_nil!.twitch && config.j # end # end - commandircipc.send( { "twitch", message } ) + commandifc.send( { "twitch", message } ) pp message pp message.params rescue ex pp ex - #twitchircipc.send( { "##{config.channel}", "An error occurred! " + ex.message.to_s } ) + #twitchircifc.send( { "##{config.channel}", "An error occurred! " + ex.message.to_s } ) # Maybe send all error messages out through the API? Have to do channel->client mappings, though. end end @@ -1369,25 +1451,25 @@ if ( secrets.twitch_access_token && config.chat_user.not_nil!.twitch && config.j ensure waitgroup.send( Fiber.current.name.not_nil! ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end if ( secrets.gamesurge_password && config.chat_user.not_nil!.gamesurge && config.join_channels.not_nil!.gamesurge ) - # GameSurge::IRC thread + # GameSurge::IRC fiber spawn name: "GameSurge::IRC" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do begin bot = GameSurge::IRC::Client.new( nick: config.chat_user.not_nil!.gamesurge.not_nil!, token: secrets.gamesurge_password.not_nil!, log_mode: true ) bot.tags = [ "membership", "tags", "commands" ] - # Outgoing IRC message thread + # Outgoing IRC message fiber # "Most IRC servers limit messages to 512 bytes in length, including the trailing CR-LF characters." # PRIVMSG #channel message\r\n - spawn do - while tuple = ircipc.receive # why does this need to be a tuple? - STDERR.puts( "#{Fiber.current} irc rx #{tuple}" ) + spawn name: "GameSurge::IRC ifc rx" do + while tuple = gamesurgeircifc.receive # why does this need to be a tuple? + puts( "#{Fiber.current.name}: #{tuple}" ) sizelimit=( 512 - ( tuple[0].size + 12 ) ) if ( tuple[0] == "JOIN" ) # FIXME: Do validation on this @@ -1400,8 +1482,8 @@ if ( secrets.gamesurge_password && config.chat_user.not_nil!.gamesurge && config # Create a handler to process incoming messages bot.on_message do |message| - spawn do - commandircipc.send( { "gamesurge", message } ) + spawn name: "GameSurge::IRC irc rx" do + commandifc.send( { "gamesurge", message } ) pp message pp message.params # elsif ( cmd =~ /^(create|addsource)/ ) @@ -1413,7 +1495,7 @@ if ( secrets.gamesurge_password && config.chat_user.not_nil!.gamesurge && config # if uri = URI.parse( args.shift ) # newargs.push( uri.to_s ) # else -# ircipc.send( { "##{settings["channel"]}", "Unable to parse URL." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Unable to parse URL." } ) # next # end # colormask : UInt32 | Nil = nil @@ -1435,34 +1517,34 @@ if ( secrets.gamesurge_password && config.chat_user.not_nil!.gamesurge && config # when /^[0-9]+$/ # direction = arg.to_u16%360 # else -# ircipc.send( { "##{settings["channel"]}", "Unable to parse color argument." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Unable to parse color argument." } ) # end # end # colormask && newargs.push( "colormask=#{colormask}" ) # direction && newargs.push( "direction=#{direction}" ) # t2smsg( settings, "download #{newargs.join(" ")}" ) # else -# ircipc.send( { "##{settings["channel"]}", "Must provide at least one URL as argument." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Must provide at least one URL as argument." } ) # end # elsif ( cmd =~ /^(delete|remove)/ ) # if ( match[2]? ) && ( match[2] =~ /^([\/a-zA-Z0-9-_]+)$/ ) # obs.inputs["medialoop-bullshit-#{match[2]}"].delete! # else -# ircipc.send( { "##{settings["channel"]}", "Must provide at least one bullshit source as argument." } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "Must provide at least one bullshit source as argument." } ) # end # elsif ( cmd == "bullshit" ) # request = Hash( String, String | Bool ).new # if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ ) # obs.scenes["meta-meta-foreground"]["meta-bullshit"].toggle! # else -# ircipc.send( { "##{settings["channel"]}", "| current sources: #{obs.scenes["meta-bullshit"].to_h.keys.map{ | s | s.sub( /^medialoop-bullshit-/, "") } .join(" ")}" } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| current sources: #{obs.scenes["meta-bullshit"].to_h.keys.map{ | s | s.sub( /^medialoop-bullshit-/, "") } .join(" ")}" } ) # end # elsif ( cmd =~ /^(system|dxdiag|computer)$/ ) && ( Crystal::DESCRIPTION =~ /linux/ ) -# ircipc.send( { "##{settings["channel"]}", "| https://bungmonkey.omgwallhack.org/tmp/DxDiag.txt" } ) +# gamesurgeircifc.send( { "##{settings["channel"]}", "| https://bungmonkey.omgwallhack.org/tmp/DxDiag.txt" } ) # end rescue ex pp ex - ircipc.send( { "##{config.chat_user.not_nil!.gamesurge.not_nil!}", "An error occurred! " + ex.message.to_s } ) + gamesurgeircifc.send( { "##{config.chat_user.not_nil!.gamesurge.not_nil!}", "An error occurred! " + ex.message.to_s } ) end end @@ -1484,33 +1566,32 @@ if ( secrets.gamesurge_password && config.chat_user.not_nil!.gamesurge && config ensure waitgroup.send( Fiber.current.name.not_nil! ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end -# BungmoBott::Socket client thread +# BungmoBott::Socket client fiber if config.bungmobott_connect bbscli_host, bbscli_port = config.bungmobott_connect.not_nil!.split(":") - puts "spawning BungmoBott::Socket client" spawn name: "BungmoBott::Socket client" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) loop do - puts "looping BungmoBott::Socket client" + puts "#{Fiber.current.name} connecting #{config.bungmobott_connect}" user = config.chat_user.not_nil!.twitch.not_nil! bungmobott_key = secrets.bungmobott_key.not_nil! ssl_socket = OpenSSL::SSL::Socket::Client.new( TCPSocket.new( bbscli_host, bbscli_port.to_u16 ), OpenSSL::SSL::Context::Client.new ) ssl_socket.sync = true negotiated = false - spawn do + spawn name: "BungmoBott::Socket client ssl rx" do while message = ssl_socket.gets - puts "BungmoBott::Socket cli recv: " + message.gsub( bungmobott_key, "CENSORED" ) + puts "#{Fiber.current.name}: " + message.gsub( bungmobott_key, "CENSORED" ) if message =~ /^error/i raise Exception.new("BungmoBott::Socket Error: #{message}") elsif message =~ /^authed/ negotiated = true #ssl_socket.puts( "say twitch #{user} test" ) elsif ( match = message.match( /^msg (twitch|gamesurge)/ ) ) - commandircipc.send( { "#{match[1]}_remote", FastIRC.parse_line( message.split(" ")[2..].join(" ") ) } ) + commandifc.send( { "#{match[1]}_remote", FastIRC.parse_line( message.split(" ")[2..].join(" ") ) } ) elsif ( match = message.match( /^awst2s ([0-9]+)/ ) ) datasize = match[1].to_u32 audiodata = Bytes.new( datasize ) @@ -1535,11 +1616,9 @@ if config.bungmobott_connect end end ssl_socket.puts( "auth #{user} #{bungmobott_key}" ) - while input = bbscliipc.receive + while input = bbscliifc.receive + puts( "#{Fiber.current.name} ssl tx: #{input}" ) # ssl_socket gets redefined in the event of I/O errors, so we deal with it here. - #if ( climsg = input.match( /^irc +twitch +JOIN \#+([a-zA-Z0-9_]+) *$/ ) ) - #end - puts( "bbscli tx: " + input ) ssl_socket.puts( input ) end end @@ -1549,14 +1628,14 @@ if config.bungmobott_connect waitgroup.send( Fiber.current.name.not_nil! ) sleep 2 end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end -# BungmoBott::Socket thread +# BungmoBott::Socket fiber if config.bungmobott_listen spawn name: "BungmoBott::Socket server" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) ip, port = config.bungmobott_listen.not_nil!.split(":") tcp_server = TCPServer.new( ip, port.to_i ) ssl_context = OpenSSL::SSL::Context::Server.new @@ -1573,7 +1652,7 @@ if config.bungmobott_listen #while tcp_server.accept? do | clientsocket | while clientsocket = tcp_server.accept? - spawn do + spawn name: "BungmoBott::Socket server tcp rx" do client = OpenSSL::SSL::Socket::Server.new(clientsocket, ssl_context) client.flush_on_newline=true @@ -1596,7 +1675,7 @@ if config.bungmobott_listen ircchannel = match[3] if ircservice == "twitch" client.puts "joining #{ircservice} \##{ircchannel}" - twitchircipc.send( { "JOIN", ircchannel } ) + twitchircifc.send( { "JOIN", ircchannel } ) unless channelsubs[ { ircservice, "#" + ircchannel } ]? channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server ).new end @@ -1604,7 +1683,7 @@ if config.bungmobott_listen pp channelsubs elsif ircservice == "gamesurge" client.puts "joining #{ircservice} \##{ircchannel}" - ircipc.send( { "JOIN", ircchannel } ) + gamesurgeircifc.send( { "JOIN", ircchannel } ) unless channelsubs[ { ircservice, "#" + ircchannel } ]? channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server ).new end @@ -1616,7 +1695,7 @@ if config.bungmobott_listen if ( match = message.match( /^awsvoicelist$/i ) ) client.puts "awsvoicelist " + generatevoicelistaws().join(" ") elsif ( match = message.match( /^awst2s ([a-zA-Z-]+) (.+)/i ) ) - filepath="#{config.tempdir}#{Time.utc.to_unix_ms}.mp3" + filepath=Path.new( config.tempdir, "#{Time.utc.to_unix_ms}.mp3" ).normalize ttsaws( filepath, match[1], match[2] ) mp3datasize = File.size( filepath ) mp3data = Bytes.new( mp3datasize ) @@ -1646,7 +1725,7 @@ if config.bungmobott_listen elsif ( match = message.match( /^say (twitch|gamesurge) (.+)/i ) ) say( match[1], connections[client]["user"], match[2] ) elsif ( message =~ /testchannelsubs/ ) - #commandircipc.send( "testchannelsubs" ) + #commandifc.send( "testchannelsubs" ) end else @@ -1656,7 +1735,6 @@ if config.bungmobott_listen remotekey = match[2] if File.exists?( config.statedir + "apikeys/" + remoteuser ) File.each_line( config.statedir + "apikeys/" + remoteuser ) do |localkey| - puts "comparing #{localkey} to #{remotekey}" if ( localkey == remotekey ) connections[client]["authed"] = "true" puts "authed #{ remoteuser }" @@ -1664,6 +1742,9 @@ if config.bungmobott_listen connections[client]["user"] = remoteuser connections[client]["key"] = remotekey break + else + puts "WARNING: auth failure: #{localkey} did not match #{remotekey}" + # maybe quiet this down once users start using multiple keys end end end @@ -1694,54 +1775,54 @@ if config.bungmobott_listen ensure waitgroup.send( Fiber.current.name.not_nil! ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end if config.join_channels spawn name: "join_channels" do - fiberipc.send( Fiber.current ) + fiberifc.send( Fiber.current ) if fibers["GameSurge::IRC"]? && config.join_channels.not_nil!.gamesurge ircservice = "gamesurge" config.join_channels.not_nil!.gamesurge.not_nil!.each do |ircchannel| - ircipc.send( { "JOIN", ircchannel } ) + gamesurgeircifc.send( { "JOIN", ircchannel } ) unless channelsubs[ { ircservice, ircchannel } ]? channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server ).new # Do we ever care about this? #channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server | Channel( Tuple( String, FastIRC::Message ) ) ).new end end - elsif fibers["BungmoBott::Socket client"]? + elsif fibers["BungmoBott::Socket client"]? && config.join_channels.not_nil!.gamesurge ircservice = "gamesurge" config.join_channels.not_nil!.gamesurge.not_nil!.each do |ircchannel| - bbscliipc.send( "irc gamesurge JOIN \#" + ircchannel ) + bbscliifc.send( "irc gamesurge JOIN \#" + ircchannel ) end end if fibers["Twitch::IRC"]? && config.join_channels.not_nil!.twitch ircservice = "twitch" config.join_channels.not_nil!.twitch.not_nil!.each do |ircchannel| - twitchircipc.send( { "JOIN", ircchannel } ) + twitchircifc.send( { "JOIN", ircchannel } ) unless channelsubs[ { ircservice, ircchannel } ]? channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server ).new # Do we ever care about this? #channelsubs[ { ircservice, "#" + ircchannel } ] = Array( OpenSSL::SSL::Socket::Server | Channel( Tuple( String, FastIRC::Message ) ) ).new end end - elsif fibers["BungmoBott::Socket client"]? + elsif fibers["BungmoBott::Socket client"]? && config.join_channels.not_nil!.twitch ircservice = "twitch" config.join_channels.not_nil!.twitch.not_nil!.each do |ircchannel| - bbscliipc.send( "irc twitch JOIN \#" + ircchannel ) + bbscliifc.send( "irc twitch JOIN \#" + ircchannel ) end end ensure waitgroup.send( Fiber.current.name.not_nil! ) end - fiber = fiberipc.receive + fiber = fiberifc.receive fibers[fiber.name.not_nil!] = fiber end puts "Spawned fibers:" -pp fibers +pp fibers.keys fibers.size.times do fiber = waitgroup.receive |