From a8a3df4009e629941868b66df108e39de417ae4d Mon Sep 17 00:00:00 2001
From: Lucio Zambon <lucio.zambon@elettra.eu>
Date: Wed, 19 Jun 2024 01:09:35 +0000
Subject: [PATCH] Update talk.php

---
 speech/talk.php | 286 ++++--------------------------------------------
 1 file changed, 23 insertions(+), 263 deletions(-)

diff --git a/speech/talk.php b/speech/talk.php
index 2a45335..f1949a3 100644
--- a/speech/talk.php
+++ b/speech/talk.php
@@ -1,17 +1,21 @@
 <?php
+	require_once("../../conf.php");
+	require_once("../../lib/sql_interface.php");
+	$sql = open_db();
 	$local = isset($_REQUEST['cdn'])? false: true; // true = use only locally installed modules, false = use cdn
 	$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'])? 'it': substr($_REQUEST['lang'], 0, 2);
 	$host = isset($hs[$_SERVER['REMOTE_ADDR']])? $hs[$_SERVER['REMOTE_ADDR']]: $_SERVER['REMOTE_ADDR'];
+	function mylog() {
+		file_put_contents('./logs'.date('Y').'.txt', date('Y-m-d H:i:s').' '.$_SERVER['REMOTE_ADDR'].'_'.$_SERVER['HTTP_X_FORWARDED_FOR'].' - '.$_SERVER['QUERY_STRING'].PHP_EOL , FILE_APPEND | LOCK_EX);
+	}
 	if (!empty($_REQUEST['init'])) {
 		$t = $_REQUEST['init']-0;
 		if ($t==0 || $t>1000000000000) die('');
 		file_put_contents("./token", $t);
 	}
+	else if (!empty($_REQUEST)) mylog();
 	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');
@@ -21,9 +25,6 @@
 		$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) {
@@ -57,9 +58,6 @@
 		
 		*/
 		// $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, path FROM launcher WHERE $1=ANY(speech_$lang)";
 		$data = $sql->sql_secure($query, array($_REQUEST['open']));
 		$host = $_REQUEST['host'];
@@ -75,9 +73,16 @@
 		die(json_encode($data));
 	}
 	if (isset($_REQUEST['search'])) {
-		require_once("../../conf.php");
-		require_once("../../lib/sql_interface.php");
-		$sql = open_db();
+		if (isset($_REQUEST['speech'])) {
+			$speech = explode('_', strtr(strtoupper($_REQUEST['speech']), [' '=>'_', '.'=>'_']));
+			$sr = explode('_', $_REQUEST['search']);
+			foreach ($speech as $i=>$s) {
+				if ($s != $sr[$i]) {
+					$query = "INSERT INTO speechreplace (speech, replace, lang) VALUES ($1, $2, $3)";
+					$data = $sql->sql_secure($query, array($s, $sr[$i], $lang));
+				}
+			}
+		}
 		$query = "SELECT speech, replace FROM speechreplace WHERE lang=$1";
 		$data = $sql->sql_secure($query, array($lang));
 		$replace = [];
@@ -127,9 +132,6 @@
 		}
 	}
 	if (isset($_REQUEST['starter'])) {
-		require_once("../../conf.php");
-		require_once("../../lib/sql_interface.php");
-		$sql = open_db();
 		// ALTER SEQUENCE launcher_id_seq RESTART WITH 6
 		/*$sql->sql_query("INSERT INTO launcher (folder_id, title, description, exename) VALUES (2, 'Jive','Jive','jive')");
 		echo $sql->last_insert_id();
@@ -157,6 +159,10 @@
 		print_r($xml);
 		die('</pre>');
 	}
+	$query = "SELECT id, title FROM launcher WHERE exename IS NOT NULL AND id>$1";
+	$data = $sql->sql_secure($query, [5]);
+	$launcher = [];
+	foreach ($data as $d) $launcher[] = $d['title'];
 ?>
 
 <!doctype html>
@@ -170,77 +176,12 @@
 		<script src="<?php echo ($local? '../../lib/jquery/jquery-ui.min.js': 'https://cdn.jsdelivr.net/npm/jquery-ui@1.13.3/dist/jquery-ui.min.js');?>" type="text/javascript"></script>
 		<link rel="stylesheet" href="../../lib/bootstrap4/bootstrap.min.css">
 		<script src="../../lib/bootstrap4/bootstrap.bundle.min.js"></script>
+		<script src="./talk.js"></script>
 	</head>
 	<body onLoad='myload()'>
 		<div id='transcriptDiv' style='display:none;'></div>
 		<div style="max-width: 500px; text-align: center">
 			<audio id='speechText' onended='speakagain();' onerror='showLog("audio err: "+event.error)'></audio>
-			<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.php?lang='+newlang+(host.length>0? '&talk='+host: '');};
-				let locale = {};
-				function myload() {
-					fetch('./talk_locale.json').then((response) => {return response.json();}).then((rlocale) => {
-						locale = rlocale;
-						$('#title').html(rlocale[lang].talkto + host);
-						$('#micna').attr('title', rlocale[lang].micna);
-						$('#miclabel').html(rlocale[lang].miclabel + '&nbsp;&nbsp;&nbsp;');
-					});
-				}
-				// https://stackoverflow.com/questions/64405532/why-speechsynthesisutterance-is-not-working-on-chrome
-				// It's because in Chrome speech synthasis requires user interaction before it speaks e.g. a button click.
-				// https://stackoverflow.com/questions/50490304/how-to-make-audio-autoplay-on-chrome
-				const synth = window.speechSynthesis;
-				const voices = synth.getVoices();
-				const voiceLocale = {'it-IT': false, 'en-US': false};
-				for (let i=voices.length-1; i>=0; i--) {
-					if (voices[i].lang=='it-IT') voiceLocale['it-IT'] = voices[i];
-					if (voices[i].lang=='en-US') voiceLocale['en-US'] = voices[i];
-				}
-				let oldText = '';
-				let oldTime = 0;
-				function speakGenerated(textValue) {
-					if (textValue !== '') {
-						stopRec();
-						if (synth.speaking) {console.error(locale.lang.speaking);showLog(locale.lang.speaking2);return;}
-						const utterThis = new SpeechSynthesisUtterance(textValue);
-						utterThis.onend = function (event) {startRec(); console.log('SpeechSynthesisUtterance.onend');showLog('..');};
-						utterThis.onerror = function (event) {console.error('SpeechSynthesisUtterance.onerror', event.error, event);showLog(locale[lang].onerror+JSON.stringify(event.error));};
-						utterThis.voice = voiceLocale[lang]===false? voices[0]: voiceLocale[lang];
-						utterThis.pitch = 0.1;
-						utterThis.rate = 1;
-						utterThis.lang = lang;
-						showLog(lang);
-						synth.speak(utterThis);
-					}
-				}
-				let keepAlive = false;
-				let aliveTimer = -1;
-				function startRec() {
-					keepAlive = true;
-					aliveTimer = -1;
-					// showLog('start');
-					recognition.start();
-					document.getElementById('micstart').style.display = 'inline';
-					document.getElementById('micstop').style.display = 'none';
-				}
-				function stopRec() {
-					if (typeof window.SpeechRecognition == 'undefined') {$("#micstart").hide();$("#micna").show();}
-					keepAlive = false;
-					recognition.stop();
-				}
-				function commandlistinfo() {
-					alert(locale[lang].commandlistinfo);
-				}
-			</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();$("#miclabel").hide();'  id='micna'>
@@ -255,20 +196,9 @@
 			<table id ='openTable' class="table table-hover"></table>
 			<pre id='log'></pre>
 			<script>
-				if (document.location.search.indexOf('debug')==-1) $('#log').hide();
-				let speechStat = '';
-				let firstRun = true;
-				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+'\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' && document.location.search.indexOf('?d=')==-1) {
 					const tok =  Math.round(Math.random()*1000000000000+1);
 					console.log('./qr.php?data='+tok+'&host=<?php echo $host;?>');
@@ -277,177 +207,7 @@
 					document.getElementById('langselect').style.display = 'none';
 					document.getElementById('miclabel').style.display = 'none';
 				}
-				let recognition = new window.SpeechRecognition();
-				recognition.maxAlternatives = 10;
-				recognition.continuous = true;
-				recognition.interimResults = true;
-				recognition.lang = lang;
-				recognition.maxAlternatives = 3;
-				showLog('starting...'+'\n');
-				/* recognition.onresult = (event) => {
-				  // The SpeechRecognitionEvent results property returns a SpeechRecognitionResultList object
-				  // The SpeechRecognitionResultList object contains SpeechRecognitionResult objects.
-				  // It has a getter so it can be accessed like an array
-				  // The first [0] returns the SpeechRecognitionResult at position 0.
-				  // Each SpeechRecognitionResult object contains SpeechRecognitionAlternative objects
-				  // that contain individual results.
-				  // These also have getters so they can be accessed like arrays.
-				  // The second [0] returns the SpeechRecognitionAlternative at position 0.
-				  // We then return the transcript property of the SpeechRecognitionAlternative object
-				  const color = event.results[0][0].transcript;
-				  diagnostic.textContent = `Result received: ${color}.`;
-				  bg.style.backgroundColor = color;
-				};*/
-				recognition.onerror = function(event) {
-					showLog(locale[lang].errorname + event.error+', '+event.message+', '+event.lineno+'\n');
-					showLog(locale[lang].errormessage + JSON.stringify(event.error));
-					console.log(event);
-					startRec();
-				}
-				recognition.onend = function(event) {
-					showLog('.');
-					// document.getElementById('miclabel').style.display = 'none';
-					document.getElementById('micna').style.display = 'none';
-					document.getElementById('micstart').style.display = 'none';
-					document.getElementById('micstop').style.display = 'inline';
-					if (keepAlive && aliveTimer==-1) aliveTimer = setTimeout(startRec, 200);
-				}
-				recognition.onstart = function(event) {
-					if (document.location.search.indexOf('debug')==-1) $('#log').hide();
-					if (firstRun) {
-						firstRun = false;
-						recognition.stop();
-						return;
-					}
-					showLog('-');
-					document.getElementById('miclabel').style.display = 'none';
-					document.getElementById('micna').style.display = 'none';
-					document.getElementById('micstart').style.display = 'inline';
-					document.getElementById('micstop').style.display = 'none';
-				}
-				function detect_token(transcript, token) {
-					const t = token.split(';');
-					for (i in t) {
-						if (transcript.indexOf(t[i])>-1) return transcript.indexOf(t[i]) + t[i].length+1;
-					}
-					return -1;
-				}
-				function quick_add(transcript) {
-					const t = + new Date();
-					if ((transcript==oldText || (transcript=='te' && oldText.indexOf('te')>-1)) && t-oldTime<1500) return;
-					oldTime = t;
-					oldText = transcript;
-					speechStat = '';
-					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(' ', '');
-						}
-						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]);
-									}
-								}
-								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';
-							names = ['pippo', 'pluto', 'goofy', 'scrooge'];
-							// txt = txt.replace(tok+' ', '').replace('ing', 'inj').replace('inch', 'inj').split(' ').join('_').split('.').join('_').toUpperCase();
-							txt = txt.replace(tok+' ', '').split(' ').join('_').split('.').join('_').toUpperCase();
-							const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0];
-							const snd = './talk.php?search='+txt+token+"&lang="+lang;
-							$('#openTable').html('<tr><td colspan="5">' + locale[lang].searchCorrect + '</td></tr>');
-							$('#openTable').html('<tr><td>'+txt+'</td><td><input id="sname"></input></td><td><button onClick="alert(5)">'+locale[lang].searchSubmit+'</button></td></tr>');
-							$(function() {$(".sname").autocomplete({source: names, select: function(event, ui) {findComponent(ui.item.value); return false;}});});
-							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 ','');
-				}
-
-				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(' 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 ');
-							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();
+				const launcher = ["<?php echo implode('","', $launcher);?>"];
 			</script>
 		</div>
 	</body>
-- 
GitLab