From a5b5239cf4cc8840dfbcbf8881b4596ca4cab3b1 Mon Sep 17 00:00:00 2001
From: Lucio Zambon <lucio.zambon@elettra.eu>
Date: Fri, 14 Jun 2024 03:41:45 +0000
Subject: [PATCH] Update talk.php

---
 speech/talk.php | 208 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 177 insertions(+), 31 deletions(-)

diff --git a/speech/talk.php b/speech/talk.php
index a9df299..bf890a0 100644
--- a/speech/talk.php
+++ b/speech/talk.php
@@ -1,10 +1,48 @@
 <?php
+	$hs = ['192.168.231.21'=>'do', '192.168.231.22'=>'re', '192.168.231.23'=>'mi', '192.168.231.24'=>'fa', '192.168.231.25'=>'sol', '192.168.231.26'=>'la', '192.168.231.27'=>'si'];
+	$lang = empty($_REQUEST['lang'])? 'en': substr($_REQUEST['lang'], 0, 2);
+	$host = isset($hs[$_SERVER['REMOTE_ADDR']])? $hs[$_SERVER['REMOTE_ADDR']]: $_SERVER['REMOTE_ADDR'];
 	if (!empty($_REQUEST['init'])) {
 		$t = $_REQUEST['init']-0;
 		if ($t==0 || $t>1000000000000) die('');
 		file_put_contents("./token", $t);
 	}
-	if (!empty($_REQUEST['send'])) {
+	if (!empty($_REQUEST['speech'])) {
+		require_once("../../conf.php");
+		require_once("../../lib/sql_interface.php");
+		$sql = open_db();
+		$query = "UPDATE launcher SET speech_$lang = array_append(speech_$lang, $1) WHERE id = $2";
+		$data = $sql->sql_secure($query, array($_REQUEST['speech'],$_REQUEST['id']));
+		header('Content-Type: application/json');
+		die(json_encode($data));
+	}
+	if (!empty($_REQUEST['list'])) {
+		$t = file_get_contents("./token");
+		if ($t != $_REQUEST['token']-0) die('[]');
+		if (time() -filectime("./token") > 36000) die('{}');
+		require_once("../../conf.php");
+		require_once("../../lib/sql_interface.php");
+		$sql = open_db();
+		$query = "SELECT id FROM launcher WHERE $1=ANY(speech_$lang)";
+		$data = $sql->sql_secure($query, array($_REQUEST['list']));
+		if ($data !== false) {
+			$query = "SELECT title FROM launcher WHERE folder_id=".$data[0]['id'];
+			$data = $sql->sql_query($query);
+			die(json_encode($data));
+		}
+		else {
+			$query = "SELECT id, title, description, word_similarity(title, $1) AS ws FROM launcher ORDER BY ws DESC LIMIT 3";
+			if (isset($_REQUEST['debug'])) echo "$query;<br>";
+			$data = $sql->sql_secure($query, array($_REQUEST['list']));
+			if ($data !== false && $data[0]['ws'] > 2.0*$data[1]['ws'])  {
+				$query = "SELECT title FROM launcher WHERE folder_id=".$data[0]['id'];
+				$data = $sql->sql_query($query);
+				die(json_encode($data));
+			}
+			die(json_encode($data));
+		}
+	}
+	if (!empty($_REQUEST['open'])) {
 		/*
 		pwma=# CREATE EXTENSION pg_trgm;
 		pub_types              │ character varying(2000)[]
@@ -17,22 +55,27 @@
 		100 100 /runtime/bin/modmulti-gui
 		
 		*/
-		$t = file_get_contents("./token");
-		if ($t != $_REQUEST['token']-0) die('');
-		if (time() -filectime("./token") > 36000) die('');
+		// $t = file_get_contents("./token"); if ($t != $_REQUEST['token']-0) die('[]'); if (time() -filectime("./token") > 36000) die('{}');
 		require_once("../../conf.php");
 		require_once("../../lib/sql_interface.php");
 		$sql = open_db();
-		$query = "SELECT exename FROM launcher WHERE $1=ANY(speech_it)";
-		$data = $sql->sql_secure($query, array($_REQUEST['send']));
-		if ($data !== false) {file_put_contents("./msg", $data[0]["exename"]); die("Panel {$data[0]["exename"]} has been opened");}
+		$query = "SELECT exename, path FROM launcher WHERE $1=ANY(speech_$lang)";
+		$data = $sql->sql_secure($query, array($_REQUEST['open']));
+		$host = $_REQUEST['host'];
+		if (isset($_REQUEST['debug'])) echo "$query; \$1: {$_REQUEST['open']}<br>../../knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host";
+		if ($data !== false) {$d = file_get_contents("http://puma-01.elettra.eu/knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host"); die(json_encode($d));}
 		// die("$query<br>$err<br>\n".json_encode($data));
-		$query = "SELECT title, description, word_similarity(title, $1) AS ws FROM launcher ORDER BY ws DESC LIMIT 3";
-		$data = $sql->sql_secure($query, array($_REQUEST['send']));
+		$query = "SELECT id, title, description, exename, path, word_similarity(title, $1) AS ws FROM launcher ORDER BY ws DESC LIMIT 3";
+		$data = $sql->sql_secure($query, array($_REQUEST['open']));
+		if (isset($_REQUEST['debug'])) echo "$query;<br>".json_encode($data);
+		if ($data !== false && $data[0]['ws'] > 2.0*$data[1]['ws'] && $data[1]['ws']>0.1) {$d = file_get_contents("http://puma-01.elettra.eu/knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host"); die(json_encode($d));}
 		$err = $sql->sql_error();
 		header('Content-Type: application/json');
 		die(json_encode($data));
 	}
+	if (isset($_REQUEST['search'])) {
+		if (!empty($_REQUEST['search'])) {file_put_contents("./msg", $_REQUEST['search']); die("{$_REQUEST['search']} has been searched");}
+	}
 	if (isset($_REQUEST['read'])) {
 		set_time_limit(0);
 		/* $t = file_get_contents("./token");
@@ -40,7 +83,7 @@
 		if (time() -filectime("./token") > 36000) die('');*/
 		while (true) {
 			if (file_exists("./msg")) {
-				$f = file_get_contents("./msg");
+				$f = file_get_contents("http://puma-01.elettra.eu/panther/speech/msg");
 				if (!empty($f)) {
 					file_put_contents("./msg", '');
 					die($f);
@@ -49,10 +92,14 @@
 			usleep(100000);
 		}
 	}
+	function makeQuery($id, $e) {
+		$path = strtr($e->attributes()->path.'/', array('//'=>'/'));
+		return strtr("INSERT INTO launcher (folder_id, title, description, exename, path) VALUES ($id, \"".$e->title.'","'.$e->description.'","'.$e->attributes()->exename."\",\"$path\")", ['""'=>'NULL','"/"'=>'NULL',"'"=>'','"'=>"'"]);
+	}
 	function elementArray($id, $element) {
 		global $sql;
 		foreach ($element as $e) {
-			$query = strtr("INSERT INTO launcher (folder_id, title, description, exename) VALUES ($id, \"".$e->title.'","'.$e->description.'","'.$e->attributes()->exename."\")", ['""'=>'NULL',"'"=>'','"'=>"'"]);
+			$query = makeQuery($id, $e);
 			echo "$query;<br>\n";
 			$sql->sql_query($query);
 		}
@@ -60,7 +107,7 @@
 	function folderArray($id, $folder) {
 		global $sql;
 		foreach ($folder as $i=>$e) {
-			$query = strtr("INSERT INTO launcher (folder_id, title, description, exename) VALUES ($id, \"".$e->title.'","'.$e->description.'","'.$e->attributes()->exename."\")", ['""'=>'NULL',"'"=>'','"'=>"'"]);
+			$query = makeQuery($id, $e);
 			echo "$query;<br>\n";
 			$sql->sql_query($query);
 			$lastid = $sql->last_insert_id() - 0;
@@ -108,18 +155,24 @@
 		<meta name="viewport" content="width=device-width, initial-scale=1">
 		<title>CS Talk</title>
 		<script src="../../lib/jquery/jquery.min.js"></script>
+		<link rel="stylesheet" href="https://puma-01.elettra.eu/lib/bootstrap4/bootstrap.min.css">
+		<script src="https://puma-01.elettra.eu/lib/bootstrap4/bootstrap.bundle.min.js"></script>
 	</head>
 	<body onLoad='myload()'>
 		<div style="max-width: 500px; text-align: center">
 			<audio id='speechText' onended='speakagain();' onerror='showLog("audio err: "+event.error)'></audio>
+			<table id ='openTable' class="table table-hover"></table>
 			<script>
+				window.openData = [];
+				const t0 = + new Date();
+				let mode = '';
 				if (document.location.search.indexOf('background=')>-1) {
 					const a = document.location.search.split('background=')[1].split('&')[0];
 					$('body').css('background-color', +a > 0? '#'+a: a);
 				}
 				const lang = document.location.search.indexOf('lang=')>-1 && document.location.search.split('lang=')[1].split('&')[0]=='en'? 'en-US': 'it-IT'; // BCP 47 language
 				const host = document.location.search.indexOf('talk=')>-1? document.location.search.split('talk=')[1].split('&')[0].replace('ee', 'pcl-elettra-cre-0').replace('ef','pcl-elettra-crf-0'): '';
-				function switchLocale(newlang) {document.location = './talk.html?lang='+newlang+(host.length>0? '&talk='+host: '');};
+				function switchLocale(newlang) {document.location = './talk.php?lang='+newlang+(host.length>0? '&talk='+host: '');};
 				let locale = {};
 				function myload() {
 					fetch('./talk_locale.json').then((response) => {return response.json();}).then((rlocale) => {
@@ -177,7 +230,7 @@
 			</script>
 			<span style='color: darkgreen; font-weight: bold;' id='title'>Talk to ...</span>
 
-			<img src='./microphone-na.png' title='not available' onClick='$("#micstart").show();$("#micna").hide();'  id='micna'>
+			<img src='./microphone-na.png' title='not available' onClick='$("#micstart").show();$("#micna").hide();$("#miclabel").hide();'  id='micna'>
 			<img src='./microphone-on.png' onClick='stopRec()' id='micstart' style='display: none; padding-right: 60px;'>
 			<img src='./microphone-off.png' onClick='startRec()' id='micstop' style='display: none; padding-right: 60px;'>
 			<div style='cursor: pointer;padding-right: 5px; text-align: right; margin-top: -1.3em;' id='langselect'>
@@ -186,25 +239,27 @@
 				<span style='color: darkgreen; font-weight: bold;' onClick='commandlistinfo()'> ? </span>
 			</div>
 			<span style='color: darkblue; font-weight: bold;' id='miclabel'>comandi vocali&nbsp;&nbsp;&nbsp;</span>
-			<pre id='log' style='display:".(isset($_REQUEST['debug'])? 'block': 'none').";'></pre>
+			<pre id='log'></pre>
 			<script>
-				// document.body.style.backgroundColor = 'black'
+				if (document.location.search.indexOf('debug')==-1) $('#log').hide();
 				let speechStat = '';
 				let firstRun = true;
-				function showLog(currentToken) {
+				function showLog(currentToken, p) {
+					console.log(p);
+					console.trace(currentToken);
 					// Show log in console and UI.
 					const logElement = document.querySelector('#log');
-					logElement.textContent = logElement.textContent+currentToken;
+					logElement.textContent = logElement.textContent+'\n'+JSON.stringify(currentToken);
 				}
 				// showLog('webkitSpeechRecognition: '+ typeof window.webkitSpeechRecognition);
 				// showLog('SpeechRecognition: '+ typeof window.SpeechRecognition);
 				window.SpeechRecognition = window.webkitSpeechRecognition || window.SpeechRecognition;
 				let finalTranscript = '';
-				if (typeof window.SpeechRecognition == 'undefined') {
+				if (typeof window.SpeechRecognition == 'undefined' && document.location.search.indexOf('?d=')==-1) {
 					const tok =  Math.round(Math.random()*1000000000000+1);
-					console.log('./qr.php?data='+tok);
-					fetch('./talk.php?init='+tok);
-					document.getElementById('micstart').src = './qr.php?data='+tok;
+					console.log('./qr.php?data='+tok+'&host=<?php echo $host;?>');
+					// fetch('./talk.php?init='+tok+'&host=<?php echo $host;?>');
+					document.getElementById('micstart').src = './qr.php?data='+tok+'&host=<?php echo $host;?>';
 					document.getElementById('langselect').style.display = 'none';
 					document.getElementById('miclabel').style.display = 'none';
 				}
@@ -253,7 +308,6 @@
 					document.getElementById('micstart').style.display = 'inline';
 					document.getElementById('micstop').style.display = 'none';
 				}
-				const open = {"facility": ["sr", "ptb", "booster", "bts"],"section": 28};
 				function detect_token(transcript, token) {
 					const t = token.split(';');
 					for (i in t) {
@@ -267,15 +321,82 @@
 					oldTime = t;
 					oldText = transcript;
 					speechStat = '';
-					const i = detect_token(transcript, locale[lang].section);
-					if (i>-1) {
-						showLog('section: '+i+'--'+transcript.substring(i));
-						if (transcript.substring(i).length>0) {
-							const snd = './talk.php?send=S'+transcript.substring(i)+'&token='+document.location.search.split('talk=')[1].split('&')[0];
-							fetch(snd).then((response) => {return response.json();}).then((rlocale) => {alert(rlocale);});
+					let txt = transcript.toLowerCase();
+					if (txt.length>0) {
+						const tok = txt.split(' ')[0];
+						if (locale[lang].open.indexOf(tok)>-1) {
+							mode = 'open';
+							txt = txt.replace(tok, '').replace(' ', '');
 						}
-						return;
+						if (mode=='open' && txt.length>0) {
+							const snd = './talk.php?open='+txt.toLowerCase().replace('.', '')+'&token='+document.location.search.split('?d=')[1].split('&')[0]+"&lang="+lang+"&host="+document.location.search.split('host=')[1].split('&')[0];
+							showLog(snd);
+							showLog(' host: '+host);
+							fetch(snd).then((response) => {return response.json();}).then((rlocale) => {
+								if (rlocale.length>=3 && rlocale[0].ws) {
+									$('#openTable').html('<tr><td colspan="5">' + locale[lang].openSelect + '</td></tr>');
+									for (let i=0; i<3; i++) {
+										$('#openTable').html($('#openTable').html()+'<tr><td>'+(i+1)+'</td><td>'+rlocale[i].title+'</td><td>'+rlocale[i].description+'</td><td>'+rlocale[i].exename+'</td></tr>');
+										window.openData.push(rlocale[i]);
+										// showLog(rlocale[i]);
+										// showLog(window.openData);
+									}
+								}
+								window.openData.push(txt);								
+								showLog('window.openData1');
+								showLog(window.openData)
+								mode = 'openTable';
+								txt = '';
+							});
+						}
+						if (mode=='openTable' && txt.length>0) {
+							showLog('window.openData2');
+							showLog(window.openData);
+							showLog(txt);
+							txt = txt.replace('numero ', '');
+							let num = -1;
+							if (txt.indexOf(locale[lang].zero)>-1) num = -1;
+							if (txt.indexOf(locale[lang].one)>-1) num = 0;
+							if (txt.indexOf(locale[lang].two)>-1) num = 1;
+							if (txt.indexOf(locale[lang].three)>-1) num = 2;
+							if (!isNaN(txt)) num = txt - 1;
+							showLog(num);
+							const exe = (window.openData[num].path? window.openData[num].path: '/runtime/bin/')+ window.openData[num].exename + '&host=' + document.location.search.split('host=')[1].split('&')[0];
+							showLog(exe);
+							if (num>-1) {
+								showLog("https://puma-01.elettra.eu/knob/launcher.php?open="+exe);
+								fetch("https://puma-01.elettra.eu/knob/launcher.php?open="+exe)
+									.then((response) => {return response.json();})
+									.then((rlocale) => {showLog(rlocale);});
+								showLog("./talk.php?speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id);
+								fetch("./talk.php?speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id)
+									.then((response) => {return response.json();})
+									.then((rlocale) => {showLog(rlocale);});
+							}
+							mode = '';
+							$('#openTable').html('');
+						}
+						if (locale[lang].search.indexOf(tok)>-1) {
+							mode = 'search';
+							txt = txt.replace(tok+' ', '').replace('ing', 'inj').replace('inch', 'inj').split(' ').join('_').split('.').join('_').toUpperCase();
+							const snd = './talk.php?search='+txt+'&token='+document.location.search.split('?d=')[1].split('&')[0];
+							showLog(snd);
+							fetch(snd).then((response) => {return response.json();}).then((rlocale) => {showLog(rlocale); alert(rlocale);});
+							mode = '';
+						}
+						if (locale[lang].list.indexOf(tok)>-1) {
+							mode = 'list';
+							txt = txt.replace(tok, '').replace(' ', '');
+						}
+						if (mode=='list') {
+							const snd = './talk.php?list='+tok+'&token='+document.location.search.split('?d=')[1].split('&')[0];
+							fetch(snd).then((response) => {return response.json();}).then((rlocale) => {showLog(rlocale); alert(rlocale);});
+							mode = '';
+						}
+						showLog('mode: '+mode+', tok: '+tok);
 					}
+					return;
+					// }
 					// else {showLog('+ '+transcript);}
 					transcript.replace('sky ','');
 				}
@@ -284,7 +405,8 @@
 					let interimTranscript = '';
 					for (let i = event.resultIndex, len = event.results.length; i < len; i++) {
 						let transcript = event.results[i][0].transcript;
-						if (event.results[i][0].transcript.length) showLog('i: '+i+', transcripts: '+event.results[i][0].transcript+(event.results[i][1]? ', transcripts: '+event.results[i][1].transcript:'')+'\n');
+						// const dt = + new Time() - t0;
+						if (event.results[i][0].transcript.length) showLog(' mode '+mode+', i: '+i+', transcripts: '+event.results[i][0].transcript+(event.results[i][1]? ', transcripts: '+event.results[i][1].transcript:'')+'\n');
 						if (event.results[i].isFinal) {
 							quick_add(transcript.toLowerCase());
 							var meno = transcript.toLowerCase().indexOf('meno ');
@@ -303,6 +425,30 @@
 					// document.getElementById('transcriptDiv').innerHTML = finalTranscript + '<i style=\"color:#00d;\">' + interimTranscript + '</i>';
 					document.getElementById('transcriptDiv').innerHTML =  '<i style=\"color:#00d;\">' + finalTranscript + '</i>';
 				}
+				/*recognition.onresult = (event) => {
+					let interimTranscript = '';
+					for (let i = event.resultIndex, len = event.results.length; i < len; i++) {
+						let transcript = event.results[i][0].transcript;
+						const dt = new Time() - t0;
+						if (event.results[i][0].transcript.length) showLog(dt+' i: '+i+', transcripts: '+event.results[i][0].transcript+(event.results[i][1]? ', transcripts: '+event.results[i][1].transcript:'')+'\n');
+						if (event.results[i].isFinal) {
+							quick_add(transcript.toLowerCase());
+							var meno = transcript.toLowerCase().indexOf('meno ');
+							console.log(meno, transcript.substring(meno+5,meno+6), transcript.substring(meno+5,meno+6) % 1);
+							if (meno>-1 && transcript.substring(meno+5,meno+6) % 1 === 0) {
+								console.log('replace');
+								transcript = transcript.replace(transcript.substring(meno,meno+5), '-');
+							}
+							// finalTranscript += transcript+'<br>\\n';
+							if (transcript.length>0) finalTranscript = transcript;
+						} else {
+							interimTranscript += transcript+'<br>\\n';
+						}
+						document.getElementById('transcriptDiv').innerHTML = '<i style=\"color:#ddd;\">' + interimTranscript + '</i>';
+					}
+					// document.getElementById('transcriptDiv').innerHTML = finalTranscript + '<i style=\"color:#00d;\">' + interimTranscript + '</i>';
+					document.getElementById('transcriptDiv').innerHTML =  '<i style=\"color:#00d;\">' + finalTranscript + '</i>';
+				}*/
 				showLog('start'+'\n');
 				recognition.start();
 			</script>
-- 
GitLab