node-red-contrib-chatbot
Version:
REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required
238 lines (232 loc) • 11.6 kB
HTML
<script type="text/javascript">
var RedBotAlexaTags = [
{
id: '1',
label: '<amazon:effect> - Applies Amazon-specific effects to the speech',
value: '<amazon:effect name="whispered"></amazon:effect>'
},
{
id: '2',
label: '<audio> - Play external or predefined MP£',
value: '<audio src="soundbank:" />'
},
{
id: '3',
label: '<break> - Represents a pause in the speech',
value: '<break strength="weak"/>'
},
{
id: '4',
label: '<emphasis> - Emphasize the tagged words',
value: '<emphasis level="strong">really like</emphasis>'
},
{
id: '5',
label: '<lang> - adapts the pronunciation',
value: '<lang xml:lang="it-IT">ciao</lang>'
},
{
id: '7',
label: '<p> - provides extra-strong breaks before and after the paragraph',
value: '<p></p>'
},
{
id: '8',
label: '<phoneme> - phonemic/phonetic pronunciation',
value: '<phoneme alphabet="ipa" ph=""></phoneme>'
},
{
id: '9',
label: '<prosody> - modifies the volume, pitch, and rate of the tagged speech',
value: '<prosody volume="x-loud" pitch="x-high" rate="x-slow"></prosody>'
},
{
id: '10',
label: '<s> - represents a sentence with strong breaks before and after the tag',
value: '<s></s>'
},
{
id: '11',
label: '<say-as> - describes how the text should be interpreted',
value: '<say-as interpret-as="digits"></say-as>'
},
{
id: '12',
label: '<sub> - pronounce the specified word or phrase as a different word or phrase',
value: '<sub alias=""></sub>'
},
{
id: '13',
label: '<voice> - speak the text with the specified Amazon Polly voice',
value: '<voice name="Carla"></voice>'
},
{
id: '14',
label: '<w> - customizes the pronunciation of words by specifying the word\'s part of speech',
value: '<w role="amazon:VB">read</w>'
}
];
$.RedBot.registerType('chatbot-alexa-speech', {
category: $.RedBot.config.name,
color: '#FFCC66',
defaults: {
name: {
value: ''
},
speechType: {
value: 'plainText'
},
text: {
value: ''
},
ssml: {
value: '<speak>\n\n</speak>'
},
playBehavior: {
value: 'enqueue'
},
reprompt: {
value: false
}
},
inputs: 1,
outputs: 1,
paletteLabel: 'Alexa Speech',
icon: 'chatbot-voice.png',
label: function() {
return (this.name != null && this.name !== '' ? this.name : 'Alexa Speech')
+ (this.reprompt ? ' (Repropmpt)' : '');
},
oneditsave: function() {
if ($('#node-input-speechType').val() === 'ssml') {
$('#node-input-ssml').val(this.editor.getValue());
$('#node-input-text').val('');
} else {
$('#node-input-ssml').val('');
}
// destroy the editor
this.editor.destroy();
delete this.editor;
},
oneditprepare: function() {
var _this = this;
$('#node-input-speechType')
.change(function() {
var type = $(this).val();
$('.form-row.only-for').hide();
$('.form-row.only-for-' + type).show();
});
$('.form-row.only-for').hide();
$('.form-row.only-for-' + this.speechType).show();
$('.btn-add-tag')
.click(function(e) {
e.preventDefault();
$('.add-tag').show();
});
this.editor = RED.editor.createEditor({
id: 'node-input-ssml-editor',
mode: 'ace/mode/html',
value: $('#node-input-ssml').val(),
globals: {
node: true,
msg:true,
context:true,
RED: true,
util: true,
flow: true,
global: true,
console: true,
Buffer: true,
setTimeout: true,
clearTimeout: true,
setInterval: true,
clearInterval: true
}
});
var select = $('#alexa-ssml-tags')
.change(function() {
var id = $(this).val();
var snippet = null;
RedBotAlexaTags.forEach(function(option) {
if (option.id === id) {
snippet = option.value;
}
});
if (snippet != null) {
_this.editor.session.insert(_this.editor.getCursorPosition(), snippet);
}
$('.add-tag').hide();
});
RedBotAlexaTags.forEach(function(option) {
select.append('<option value="' + option.id + '">' + option.label + '</option>');
});
}
});
</script>
<script type="text/x-red" data-template-name="chatbot-alexa-speech">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-speechType">Type</label>
<select id="node-input-speechType" placeholder="Select speech type" style="width:auto;">
<option value="plainText">Plain Text</option>
<option value="ssml">Speech Synthesis Markup Language</option>
</select>
</div>
<div class="form-row only-for only-for-plainText">
<label for="node-input-text">Text</label>
<textarea id="node-input-text" placeholder="" style="width:93%;height:100px;"></textarea>
</div>
<div class="form-row only-for only-for-ssml">
<label for="node-input-ssml" style="width:auto;">
Speech Synthesis Markup Language
<a href="#" style="font-size:12px;" class="btn-add-tag">(add tag)</a>
</label>
<input type="hidden" id="node-input-ssml" autofocus="autofocus">
<div class="add-tag" style="display:none;margin-bottom:5px;">
<select id="alexa-ssml-tags" style="width:100%;">
<option value="">Select tags</option>
</select>
</div>
<div style="height: 150px; min-height:150px;" class="node-text-editor" id="node-input-ssml-editor"></div>
</div>
<div class="form-row">
<label for="node-input-playBehavior">Play Behaviour</label>
<select id="node-input-playBehavior" placeholder="Select speech type" style="width:auto;">
<option value="enqueue">Enqueue</option>
<option value="replaceAll">Replace All</option>
<option value="replaceEnqueued">Replace Enquueued</option>
</select>
</div>
<div class="form-row">
<label for="node-input-reprompt">Reprompt</label>
<input type="checkbox" value="true" id="node-input-reprompt">
</div>
</script>
<script type="text/x-red" data-help-name="chatbot-alexa-speech"><p>Open the <a href="https://developer.amazon.com/alexa/console/ask">Alexa Developer Console</a> and create a new <strong>skill</strong>:</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/34cacc3a-3d2b-46be-883e-9da288a01ae3/example-alexa-1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124944Z&X-Amz-Expires=3600&X-Amz-Signature=679aa934a89d9e95569769ce710c0389d0071123b6997f75ce332251a9467e6c&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Example 1"></p>
<p>Be sure to select the <em>custom</em> model and <em>Start from scratch</em> in the following step.</p>
<p>Then you have to pickup the invocation name, it the name of your chatbot that will answer to sentences like <em>“Alexa, ask my-chatbot-name to …”</em>.</p>
<p><strong>Alexa</strong> needs a callback to send the requests to: it must be a https endpoint (a self signed certificate it’s not enough). For testing we’ll use <strong>ngrok</strong> to create a https tunnel for our local <strong>Node-RED</strong> instance. Install it, then open a shell window and run</p>
<pre><code class="language-bash">ngrok http 127.0.0.1:1880
</code></pre>
<p>You should get something like</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/58f7c691-68c9-4b1e-a781-5195cc281f0b/facebook-1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124944Z&X-Amz-Expires=3600&X-Amz-Signature=d07f4addf7823efb70ae19e3972db92834a4d072d8b0bce1bd65730688c6b56a&X-Amz-SignedHeaders=host&x-id=GetObject" alt=""></p>
<p>Grab the https address you get, something like <em><a href="https://123123.ngrok.io">https://123123.ngrok.io</a></em>, this is the base url that points back to your <strong>Node-RED</strong> instance.</p>
<p>The callback is</p>
<pre><code class="language-plain">http://youraddress.ngrok.io/redbot/alexa
</code></pre>
<p>This callback should fill the field <em>Default region</em> in the <em>Endpoint</em> session</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/1faafaf8-a853-4701-8af6-6dab18f9732b/example-alexa-2.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124944Z&X-Amz-Expires=3600&X-Amz-Signature=734af8284094ed0dc818cd0c300c9fea99f246aaa9d29d2c6c149c78f6a68cbd&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Example 2"></p>
<p>We’re ready to create the first simple flow:</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/1b2f58a1-7809-4d64-89cd-4b8451db57de/example-alexa-3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124944Z&X-Amz-Expires=3600&X-Amz-Signature=d63d111ebdd870b164874137d793dcc9fd9df17dee05b9d8473b3da329058516&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Example 3"></p>
<p><em>Note:</em> the <code>Alexa Receiver</code> node configuration doesn’t need any particular configuration (no tokens or secret key like other chatbots), for testing the default one is ok.</p>
<p>Now switch to the test page from the menu and type</p>
<pre><code class="language-plain">start my-chatbot-name
</code></pre>
<p>you should hear the answer defined in the <a href="https://www.notion.so/08bc9f05559a47819fd07a4bacc28c73">Alexa Speech node</a> and see in the console the <a href="https://www.notion.so/4a49f90897d8444fa8a780ea40d6b26e">Events</a> of type <em>start</em></p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/7d1e7ac5-b4f8-4bc9-b3c4-fc5eac7d5ebe/example-alexa-4.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124944Z&X-Amz-Expires=3600&X-Amz-Signature=084ae977fde73977dd072db94b15a370c53517fde368817b959cfe890ebb1591&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Example 4"></p>
<p><strong>Important:</strong> <strong>Alexa</strong> chatbots works differently compared to other chatbot APIs like <strong>Telegram</strong> or <strong>Facebook</strong>: calls are synchronous, when <strong>Alexa</strong> calls the <strong>RedBot</strong>’s endpoint it expects an immediate response. Internally <strong>RedBot</strong> will store the <em>response</em> object in the <strong>Node-RED</strong> message and will use it in the final <code>Alexa Sender node</code>. For this reason the flow (nodes between the receiver to the sender nodes) cannot last more than the <strong>Alexa</strong> timeout (<strong>3000 ms</strong>).</p>
</script>