mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Working on speech rec
This commit is contained in:
parent
23e9dd6a97
commit
9dd2ab43c2
@ -325,6 +325,9 @@ if (! defined('APP_NAME')) {
|
|||||||
define('SKYPE_API_URL', 'https://apis.skype.com/v3');
|
define('SKYPE_API_URL', 'https://apis.skype.com/v3');
|
||||||
define('MSBOT_STATE_URL', 'https://state.botframework.com/v3');
|
define('MSBOT_STATE_URL', 'https://state.botframework.com/v3');
|
||||||
|
|
||||||
|
define('BOT_PLATFORM_WEB_APP', 'WebApp');
|
||||||
|
define('BOT_PLATFORM_SKYPE', 'Skype');
|
||||||
|
|
||||||
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
|
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
|
||||||
|
|
||||||
define('COUNT_FREE_DESIGNS', 4);
|
define('COUNT_FREE_DESIGNS', 4);
|
||||||
|
@ -80,7 +80,7 @@ class BotController extends Controller
|
|||||||
$user->account->loadLocalizationSettings();
|
$user->account->loadLocalizationSettings();
|
||||||
|
|
||||||
$data = $this->parseMessage($text);
|
$data = $this->parseMessage($text);
|
||||||
$intent = BaseIntent::createIntent($state, $data);
|
$intent = BaseIntent::createIntent($platform, $state, $data);
|
||||||
$response = $intent->process();
|
$response = $intent->process();
|
||||||
$state = $intent->getState();
|
$state = $intent->getState();
|
||||||
}
|
}
|
||||||
@ -97,6 +97,14 @@ class BotController extends Controller
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleCommand()
|
||||||
|
{
|
||||||
|
$data = $this->parseMessage(request()->command);
|
||||||
|
$intent = BaseIntent::createIntent(BOT_PLATFORM_WEB_APP, false, $data);
|
||||||
|
|
||||||
|
return $intent->process();
|
||||||
|
}
|
||||||
|
|
||||||
private function authenticate($input)
|
private function authenticate($input)
|
||||||
{
|
{
|
||||||
$token = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : false;
|
$token = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : false;
|
||||||
|
@ -127,6 +127,7 @@ Route::group(['middleware' => 'auth:user'], function () {
|
|||||||
Route::get('check_invoice_number/{invoice_id?}', 'InvoiceController@checkInvoiceNumber');
|
Route::get('check_invoice_number/{invoice_id?}', 'InvoiceController@checkInvoiceNumber');
|
||||||
Route::post('save_sidebar_state', 'UserController@saveSidebarState');
|
Route::post('save_sidebar_state', 'UserController@saveSidebarState');
|
||||||
Route::post('contact_us', 'HomeController@contactUs');
|
Route::post('contact_us', 'HomeController@contactUs');
|
||||||
|
Route::post('handle_command', 'BotController@handleCommand');
|
||||||
|
|
||||||
Route::get('settings/user_details', 'AccountController@showUserDetails');
|
Route::get('settings/user_details', 'AccountController@showUserDetails');
|
||||||
Route::post('settings/user_details', 'AccountController@saveUserDetails');
|
Route::post('settings/user_details', 'AccountController@saveUserDetails');
|
||||||
|
@ -32,7 +32,7 @@ class BaseIntent
|
|||||||
//var_dump($state);
|
//var_dump($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createIntent($state, $data)
|
public static function createIntent($platform, $state, $data)
|
||||||
{
|
{
|
||||||
if (! count($data->intents)) {
|
if (! count($data->intents)) {
|
||||||
throw new Exception(trans('texts.intent_not_found'));
|
throw new Exception(trans('texts.intent_not_found'));
|
||||||
@ -48,13 +48,18 @@ class BaseIntent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $entityType) {
|
if ($state && ! $entityType) {
|
||||||
$entityType = $state->current->entityType;
|
$entityType = $state->current->entityType;
|
||||||
}
|
}
|
||||||
|
|
||||||
$entityType = ucwords(strtolower($entityType));
|
$entityType = ucwords(strtolower($entityType));
|
||||||
$intent = str_replace('Entity', $entityType, $intent);
|
$intent = str_replace('Entity', $entityType, $intent);
|
||||||
$className = "App\\Ninja\\Intents\\{$intent}Intent";
|
|
||||||
|
if ($platform == BOT_PLATFORM_WEB_APP) {
|
||||||
|
$className = "App\\Ninja\\Intents\\WebApp\\{$intent}Intent";
|
||||||
|
} else {
|
||||||
|
$className = "App\\Ninja\\Intents\\{$intent}Intent";
|
||||||
|
}
|
||||||
|
|
||||||
//echo "Intent: $intent<p>";
|
//echo "Intent: $intent<p>";
|
||||||
|
|
||||||
|
28
app/Ninja/Intents/WebApp/CreateInvoiceIntent.php
Normal file
28
app/Ninja/Intents/WebApp/CreateInvoiceIntent.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Ninja\Intents\WebApp;
|
||||||
|
|
||||||
|
use App\Models\EntityModel;
|
||||||
|
use App\Ninja\Intents\InvoiceIntent;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class CreateInvoiceIntent extends InvoiceIntent
|
||||||
|
{
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
$client = $this->requestClient();
|
||||||
|
$invoiceItems = $this->requestInvoiceItems();
|
||||||
|
|
||||||
|
if (! $client) {
|
||||||
|
throw new Exception(trans('texts.client_not_found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_merge($this->requestFields(), [
|
||||||
|
'client_id' => $client->public_id,
|
||||||
|
'invoice_items' => $invoiceItems,
|
||||||
|
]);
|
||||||
|
|
||||||
|
//var_dump($data);
|
||||||
|
dd($data);
|
||||||
|
}
|
||||||
|
}
|
@ -309,12 +309,15 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form id="search-form" class="navbar-form navbar-right" role="search">
|
{!! Former::open('/handle_command')->id('search-form')->addClass('navbar-form navbar-right')->role('search') !!}
|
||||||
<div class="form-group">
|
<div class="form-group has-feedback">
|
||||||
<input type="text" id="search" style="width: 240px;padding-top:0px;padding-bottom:0px"
|
<input type="text" name="command" id="search" style="width: 240px;padding-top:0px;padding-bottom:0px;margin-right:12px;"
|
||||||
class="form-control" placeholder="{{ trans('texts.search') . ': ' . trans('texts.search_hotkey')}}">
|
class="form-control" placeholder="{{ trans('texts.search') . ': ' . trans('texts.search_hotkey')}}"/>
|
||||||
|
@if (Utils::isNinja())
|
||||||
|
@include('partials/speech_recognition')
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</form>
|
{!! Former::close() !!}
|
||||||
|
|
||||||
@if (false && Utils::isAdmin())
|
@if (false && Utils::isAdmin())
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
215
resources/views/partials/speech_recognition.blade.php
Normal file
215
resources/views/partials/speech_recognition.blade.php
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
<i class="fa fa-microphone form-control-feedback" style="font-size:16px;padding-top:8px" aria-hidden="true"></i>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function() {
|
||||||
|
$('#search').keypress(function(event) {
|
||||||
|
if (event.keyCode === 13) {
|
||||||
|
$('#search-form').submit();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
var langs =
|
||||||
|
[['Afrikaans', ['af-ZA']],
|
||||||
|
['Bahasa Indonesia',['id-ID']],
|
||||||
|
['Bahasa Melayu', ['ms-MY']],
|
||||||
|
['Català', ['ca-ES']],
|
||||||
|
['Čeština', ['cs-CZ']],
|
||||||
|
['Dansk', ['da-DK']],
|
||||||
|
['Deutsch', ['de-DE']],
|
||||||
|
['English', ['en-AU', 'Australia'],
|
||||||
|
['en-CA', 'Canada'],
|
||||||
|
['en-IN', 'India'],
|
||||||
|
['en-NZ', 'New Zealand'],
|
||||||
|
['en-ZA', 'South Africa'],
|
||||||
|
['en-GB', 'United Kingdom'],
|
||||||
|
['en-US', 'United States']],
|
||||||
|
['Español', ['es-AR', 'Argentina'],
|
||||||
|
['es-BO', 'Bolivia'],
|
||||||
|
['es-CL', 'Chile'],
|
||||||
|
['es-CO', 'Colombia'],
|
||||||
|
['es-CR', 'Costa Rica'],
|
||||||
|
['es-EC', 'Ecuador'],
|
||||||
|
['es-SV', 'El Salvador'],
|
||||||
|
['es-ES', 'España'],
|
||||||
|
['es-US', 'Estados Unidos'],
|
||||||
|
['es-GT', 'Guatemala'],
|
||||||
|
['es-HN', 'Honduras'],
|
||||||
|
['es-MX', 'México'],
|
||||||
|
['es-NI', 'Nicaragua'],
|
||||||
|
['es-PA', 'Panamá'],
|
||||||
|
['es-PY', 'Paraguay'],
|
||||||
|
['es-PE', 'Perú'],
|
||||||
|
['es-PR', 'Puerto Rico'],
|
||||||
|
['es-DO', 'República Dominicana'],
|
||||||
|
['es-UY', 'Uruguay'],
|
||||||
|
['es-VE', 'Venezuela']],
|
||||||
|
['Euskara', ['eu-ES']],
|
||||||
|
['Filipino', ['fil-PH']],
|
||||||
|
['Français', ['fr-FR']],
|
||||||
|
['Galego', ['gl-ES']],
|
||||||
|
['Hrvatski', ['hr_HR']],
|
||||||
|
['IsiZulu', ['zu-ZA']],
|
||||||
|
['Íslenska', ['is-IS']],
|
||||||
|
['Italiano', ['it-IT', 'Italia'],
|
||||||
|
['it-CH', 'Svizzera']],
|
||||||
|
['Lietuvių', ['lt-LT']],
|
||||||
|
['Magyar', ['hu-HU']],
|
||||||
|
['Nederlands', ['nl-NL']],
|
||||||
|
['Norsk bokmål', ['nb-NO']],
|
||||||
|
['Polski', ['pl-PL']],
|
||||||
|
['Português', ['pt-BR', 'Brasil'],
|
||||||
|
['pt-PT', 'Portugal']],
|
||||||
|
['Română', ['ro-RO']],
|
||||||
|
['Slovenščina', ['sl-SI']],
|
||||||
|
['Slovenčina', ['sk-SK']],
|
||||||
|
['Suomi', ['fi-FI']],
|
||||||
|
['Svenska', ['sv-SE']],
|
||||||
|
['Tiếng Việt', ['vi-VN']],
|
||||||
|
['Türkçe', ['tr-TR']],
|
||||||
|
['Ελληνικά', ['el-GR']],
|
||||||
|
['български', ['bg-BG']],
|
||||||
|
['Pусский', ['ru-RU']],
|
||||||
|
['Српски', ['sr-RS']],
|
||||||
|
['Українська', ['uk-UA']],
|
||||||
|
['한국어', ['ko-KR']],
|
||||||
|
['中文', ['cmn-Hans-CN', '普通话 (中国大陆)'],
|
||||||
|
['cmn-Hans-HK', '普通话 (香港)'],
|
||||||
|
['cmn-Hant-TW', '中文 (台灣)'],
|
||||||
|
['yue-Hant-HK', '粵語 (香港)']],
|
||||||
|
['日本語', ['ja-JP']],
|
||||||
|
['हिन्दी', ['hi-IN']],
|
||||||
|
['ภาษาไทย', ['th-TH']]];
|
||||||
|
|
||||||
|
|
||||||
|
var final_transcript = '';
|
||||||
|
var recognizing = false;
|
||||||
|
var ignore_onend;
|
||||||
|
var start_timestamp;
|
||||||
|
|
||||||
|
if (!('webkitSpeechRecognition' in window)) {
|
||||||
|
upgrade();
|
||||||
|
} else {
|
||||||
|
//start_button.style.display = 'inline-block';
|
||||||
|
var recognition = new webkitSpeechRecognition();
|
||||||
|
recognition.continuous = true;
|
||||||
|
recognition.interimResults = true;
|
||||||
|
|
||||||
|
recognition.onstart = function() {
|
||||||
|
recognizing = true;
|
||||||
|
showInfo('info_speak_now');
|
||||||
|
//start_img.src = '/intl/en/chrome/assets/common/images/content/mic-animate.gif';
|
||||||
|
};
|
||||||
|
|
||||||
|
recognition.onerror = function(event) {
|
||||||
|
if (event.error == 'no-speech') {
|
||||||
|
//start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
|
||||||
|
showInfo('info_no_speech');
|
||||||
|
ignore_onend = true;
|
||||||
|
}
|
||||||
|
if (event.error == 'audio-capture') {
|
||||||
|
//start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
|
||||||
|
showInfo('info_no_microphone');
|
||||||
|
ignore_onend = true;
|
||||||
|
}
|
||||||
|
if (event.error == 'not-allowed') {
|
||||||
|
if (event.timeStamp - start_timestamp < 100) {
|
||||||
|
showInfo('info_blocked');
|
||||||
|
} else {
|
||||||
|
showInfo('info_denied');
|
||||||
|
}
|
||||||
|
ignore_onend = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
recognition.onend = function() {
|
||||||
|
recognizing = false;
|
||||||
|
if (ignore_onend) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
|
||||||
|
if (!final_transcript) {
|
||||||
|
showInfo('info_start');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showInfo('');
|
||||||
|
if (window.getSelection) {
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNode(document.getElementById('final_span'));
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
recognition.onresult = function(event) {
|
||||||
|
var interim_transcript = '';
|
||||||
|
if (typeof(event.results) == 'undefined') {
|
||||||
|
recognition.onend = null;
|
||||||
|
recognition.stop();
|
||||||
|
upgrade();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var i = event.resultIndex; i < event.results.length; ++i) {
|
||||||
|
if (event.results[i].isFinal) {
|
||||||
|
final_transcript += event.results[i][0].transcript;
|
||||||
|
} else {
|
||||||
|
interim_transcript += event.results[i][0].transcript;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final_transcript = capitalize(final_transcript);
|
||||||
|
//final_span.innerHTML = linebreak(final_transcript);
|
||||||
|
//interim_span.innerHTML = linebreak(interim_transcript);
|
||||||
|
console.log('final_span: %s', linebreak(final_transcript));
|
||||||
|
console.log('interim_span: %s', linebreak(interim_transcript));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade() {
|
||||||
|
start_button.style.visibility = 'hidden';
|
||||||
|
showInfo('info_upgrade');
|
||||||
|
}
|
||||||
|
|
||||||
|
var two_line = /\n\n/g;
|
||||||
|
var one_line = /\n/g;
|
||||||
|
function linebreak(s) {
|
||||||
|
return s.replace(two_line, '<p></p>').replace(one_line, '<br>');
|
||||||
|
}
|
||||||
|
|
||||||
|
var first_char = /\S/;
|
||||||
|
function capitalize(s) {
|
||||||
|
return s.replace(first_char, function(m) { return m.toUpperCase(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function startButton(event) {
|
||||||
|
if (recognizing) {
|
||||||
|
recognition.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final_transcript = '';
|
||||||
|
recognition.lang = select_dialect.value;
|
||||||
|
recognition.start();
|
||||||
|
ignore_onend = false;
|
||||||
|
final_span.innerHTML = '';
|
||||||
|
interim_span.innerHTML = '';
|
||||||
|
//start_img.src = '/intl/en/chrome/assets/common/images/content/mic-slash.gif';
|
||||||
|
showInfo('info_allow');
|
||||||
|
start_timestamp = event.timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showInfo(s) {
|
||||||
|
console.log('Info: ' + s);
|
||||||
|
/*
|
||||||
|
if (s) {
|
||||||
|
for (var child = info.firstChild; child; child = child.nextSibling) {
|
||||||
|
if (child.style) {
|
||||||
|
child.style.display = child.id == s ? 'inline' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info.style.visibility = 'visible';
|
||||||
|
} else {
|
||||||
|
info.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user