From 33e8ef50262d0f17d709e381c511d9f9ffb3b210 Mon Sep 17 00:00:00 2001
From: Joe Rayhawk <jrayhawk+git@omgwallhack.org>
Date: Fri, 13 Sep 2024 00:30:30 -0700
Subject: bungmobott: gcs speech error handling

---
 crystal/bungmobott.cr | 130 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 90 insertions(+), 40 deletions(-)

(limited to 'crystal')

diff --git a/crystal/bungmobott.cr b/crystal/bungmobott.cr
index 67d5c9e..73054c2 100644
--- a/crystal/bungmobott.cr
+++ b/crystal/bungmobott.cr
@@ -397,6 +397,26 @@ end
 #  end
 #end
 
+def dictdef( term : String ) : String
+  client = TCPSocket.new("localhost", 1234)
+  client.close
+  response = client.gets
+#  unless response =~ /^220 / then return response end
+  client << "client bungmoBott\n"
+#  unless response =~ /^250 / then return response end
+  client << "match english lev #{term}\n"
+  #spawn name: "BungmoBott::Socket dictd" do
+    while message = client.gets
+      response = client.gets
+    end
+  #end
+  if response
+    return response
+  else
+    return "dict definition not found"
+  end
+end
+
 
 def urbandef( term : String )
 #{
@@ -420,10 +440,14 @@ def urbandef( term : String )
   #ssl_context.verify_mode = OpenSSL::SSL::VerifyMode::NONE
   #{% end %}
   #https://api.urbandictionary.com/v0/define?term=waifu
-  response = HTTP::Client.exec( "GET", "https://api.urbandictionary.com/v0/define?term=#{term}", tls: ssl_context )
+  response = HTTP::Client.exec( "GET", "https://api.urbandictionary.com/v0/define?term=#{URI.encode_www_form(term)}", tls: ssl_context )
   puts response.status_code
   json = JSON.parse( response.body )
-  return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /(\r|\n)/, " " )
+  if json["list"][0]?
+    return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /(\r|\n)/, " " )
+  else
+    return "Urban Dictionary definition not found."
+  end
 end
 
 # FIXME: maybe break this out into separate functions later
@@ -1238,7 +1262,7 @@ end
 fiber = fiberifc.receive
 fibers[fiber.name.not_nil!] = fiber
 
-def ttsgcs( languagecode : String, voice : String, text : String, gcskey : String ) : Bytes
+def ttsgcs( languagecode : String, voice : String, text : String, gcskey : String ) : Bytes | JSON::Any
   request = Hash( String, Hash( String, String ) ){
     "input" => { "text" => text },
     "audioConfig" => { "audioEncoding" => "MP3" },
@@ -1254,8 +1278,19 @@ def ttsgcs( languagecode : String, voice : String, text : String, gcskey : Strin
   headers["Content-Type"] = "application/json; charset=utf-8"
   response = HTTP::Client.exec( "POST", "https://texttospeech.googleapis.com/v1/text:synthesize?key=#{gcskey}", headers, request.to_json, tls: ssl_context )
 
+# {"error" => {
+#   "code" => 500,
+#   "message" => "Failed to synthesize with voice cmn-TW-Standard-B",
+#   "status" => "INTERNAL"
+# }}
+
+
   json=JSON.parse(response.body)
-  return Base64.decode( json["audioContent"].as_s )
+  if json["audioContent"]?
+    return Base64.decode( json["audioContent"].as_s )
+  else
+    return json
+  end
 end
 
 def ttsaws( filepath : Path, voice : String, text : String )
@@ -1305,8 +1340,12 @@ spawn name: "text2speech" do
           {% end %}
         elsif ( match = voice.match( /^([a-zA-Z]{2,3}-[a-zA-Z]{2})/ ) )
           if ( gcloud_token = secrets.gcloud_token ).is_a?( String ) # Google cloud voice
-            mp3data = ttsgcs( match[1], voice, text, gcloud_token )
-            playaudiodata( config.tempdir, mp3data )
+            ttsgcsreturn = ttsgcs( match[1], voice, text, gcloud_token )
+            if ttsgcsreturn.is_a?( Bytes )
+              playaudiodata( config.tempdir, ttsgcsreturn )
+            elsif ttsgcsreturn.is_a?( JSON::Any )
+              raise Exception.new("text2speech Error: gcs #{ttsgcsreturn.to_s.gsub( /\n|\r/, "" )}")
+            end
           elsif fibers["BungmoBott::Socket client"]?
             bbscliifc.send( "gcst2s #{voice} #{text}" )
             # The rest of this is dealt with in the BungmoBott::Socket client
@@ -1613,36 +1652,42 @@ if config.bungmobott_connect
       ssl_socket.sync = true
       negotiated = false
       spawn name: "BungmoBott::Socket client ssl rx" do
-        while message = ssl_socket.gets
-          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)/ ) )
-            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 )
-            ssl_socket.fill_read( audiodata )
-            playaudiodata( config.tempdir, audiodata )
-          elsif ( match = message.match( /^gcst2s ([0-9]+)/ ) )
-            datasize = match[1].to_u32
-            audiodata = Bytes.new( datasize )
-            ssl_socket.fill_read( audiodata )
-            playaudiodata( config.tempdir, audiodata )
-          elsif ( match = message.match( /^awsvoicelist (.+)$/ ) )
-            match[1].split(" ").each do | voice |
-              voices[voice.downcase] = voice
-            end
-            writevoices()
-          elsif ( match = message.match( /^gcsvoicelist (.+)$/ ) )
-            match[1].split(" ").each do | voice |
-              voices[voice.downcase] = voice
+        loop do
+          while message = ssl_socket.gets
+            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)/ ) )
+              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 )
+              ssl_socket.fill_read( audiodata )
+              playaudiodata( config.tempdir, audiodata )
+            elsif ( match = message.match( /^gcst2s ([0-9]+)/ ) )
+              datasize = match[1].to_u32
+              audiodata = Bytes.new( datasize )
+              ssl_socket.fill_read( audiodata )
+              playaudiodata( config.tempdir, audiodata )
+            elsif ( match = message.match( /^awsvoicelist (.+)$/ ) )
+              match[1].split(" ").each do | voice |
+                voices[voice.downcase] = voice
+              end
+              writevoices()
+            elsif ( match = message.match( /^gcsvoicelist (.+)$/ ) )
+              match[1].split(" ").each do | voice |
+                voices[voice.downcase] = voice
+              end
+              writevoices()
             end
-            writevoices()
           end
+        rescue ex
+          pp ex
+          puts "WARNING: unhandled exception #{ex.backtrace}"
+          #say_all_self_chan( "An error occurred! " + ex.message.to_s )
         end
       end
       ssl_socket.puts( "auth #{user} #{bungmobott_key}" )
@@ -1662,7 +1707,7 @@ if config.bungmobott_connect
   fibers[fiber.name.not_nil!] = fiber
 end
 
-# BungmoBott::Socket fiber
+# BungmoBott::Socket server fiber
 if config.bungmobott_listen
   spawn name: "BungmoBott::Socket server" do
     fiberifc.send( Fiber.current )
@@ -1743,11 +1788,16 @@ if config.bungmobott_listen
                 if ( match = message.match( /^gcsvoicelist$/i ) )
                   client.puts "gcsvoicelist " + generatevoicelistgcs( ( gcloud_token ) ).join(" ")
                 elsif ( match = message.match( /^gcst2s (([a-zA-Z]{2,3}-[a-zA-Z]{2})[a-zA-Z0-9-]+) (.+)/i ) )
-                  mp3data = ttsgcs( match[2], match[1], match[3], gcloud_token )
-                  client.puts "gcst2s #{mp3data.size}"
-                  STDOUT.puts "SENT: gcst2s #{mp3data.size}"
-                  client.unbuffered_write( mp3data )
-                  STDOUT.puts "SENT: mp3data"
+                  ttsgcsreturn = ttsgcs( match[2], match[1], match[3], gcloud_token )
+                  if ttsgcsreturn.is_a?( Bytes )
+                    client.puts "gcst2s #{ttsgcsreturn.size}"
+                    STDOUT.puts "SENT: gcst2s #{ttsgcsreturn.size}"
+                    client.unbuffered_write( ttsgcsreturn )
+                    STDOUT.puts "SENT: ttsgcsreturn"
+                  elsif ttsgcsreturn.is_a?( JSON::Any )
+                    client.puts "error gcst2s #{ttsgcsreturn.to_s.gsub( /\n|\r/, "" )}"
+                    STDOUT.puts "SENT: error gcst2s #{ttsgcsreturn.to_s.gsub( /\n|\r/, "" )}"
+                  end
                 end
               else
                 client.puts "ERROR: gcloud_token missing, gcs commands disabled."
-- 
cgit v1.2.3