diff --git a/speech/talk.php b/speech/talk.php index 2a45335d73468b131cf445b5e2f77655f9609fec..f1949a3209ac46885bfc08e1b50af5290db70d66 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 + ' '); - }); - } - // 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>