UNPKG

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
<script type="text/javascript"> var RedBotAlexaTags = [ { id: '1', label: '&lt;amazon:effect&gt; - Applies Amazon-specific effects to the speech', value: '<amazon:effect name="whispered"></amazon:effect>' }, { id: '2', label: '&lt;audio&gt; - Play external or predefined MP£', value: '<audio src="soundbank:" />' }, { id: '3', label: '&lt;break&gt; - Represents a pause in the speech', value: '<break strength="weak"/>' }, { id: '4', label: '&lt;emphasis&gt; - Emphasize the tagged words', value: '<emphasis level="strong">really like</emphasis>' }, { id: '5', label: '&lt;lang&gt; - adapts the pronunciation', value: '<lang xml:lang="it-IT">ciao</lang>' }, { id: '7', label: '&lt;p&gt; - provides extra-strong breaks before and after the paragraph', value: '<p></p>' }, { id: '8', label: '&lt;phoneme&gt; - phonemic/phonetic pronunciation', value: '<phoneme alphabet="ipa" ph=""></phoneme>' }, { id: '9', label: '&lt;prosody&gt; - 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: '&lt;s&gt; - represents a sentence with strong breaks before and after the tag', value: '<s></s>' }, { id: '11', label: '&lt;say-as&gt; - describes how the text should be interpreted', value: '<say-as interpret-as="digits"></say-as>' }, { id: '12', label: '&lt;sub&gt; - pronounce the specified word or phrase as a different word or phrase', value: '<sub alias=""></sub>' }, { id: '13', label: '&lt;voice&gt; - speak the text with the specified Amazon Polly voice', value: '<voice name="Carla"></voice>' }, { id: '14', label: '&lt;w&gt; - 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>