Skip to content

Commit

Permalink
Updates Google Assistant to allow for multiple simple responses (#211)
Browse files Browse the repository at this point in the history
* Allowing for multiple simple responses in Google Assistant

* Fixes some types and little cleanup

* updated dependencies

* Fixes many documentation build issues

* a mention to google assistant in the dialogflow platforms

* refactor to take render directives into it's own function
  • Loading branch information
armonge committed Mar 6, 2019
1 parent 5799002 commit fc14059
Show file tree
Hide file tree
Showing 23 changed files with 355 additions and 104 deletions.
3 changes: 0 additions & 3 deletions .nycrc
@@ -1,6 +1,4 @@
{
"check-coverage": false,
"per-file": true,
"include": [
"src/**/*.ts",
"src/**/*.js"
Expand All @@ -14,7 +12,6 @@
".ts",
".js"
],
"cache": true,
"all": true
}

4 changes: 2 additions & 2 deletions docs/alexa-directives.rst
Expand Up @@ -96,7 +96,7 @@ Voxa provides a `DisplayTemplate` builder that can be used with the `alexaRender
Alexa Presentation Language (APL) Templates
--------------
-------------------------------------------
`Alexa Documentation <https://developer.amazon.com/docs/alexa-presentation-language/apl-overview.html>`_
Expand Down Expand Up @@ -152,7 +152,7 @@ One important thing to know is that is you sent a Render Template and a APL Temp
Alexa Presentation Language (APL) Commands
--------------
------------------------------------------
`Alexa Documentation <https://developer.amazon.com/docs/alexa-presentation-language/apl-commands.html>`_
Expand Down
2 changes: 1 addition & 1 deletion docs/alexa-reply.rst
@@ -1,7 +1,7 @@
.. _alexa-reply:

The ``AlexaReply`` Object
====================
=========================


.. js:class:: AlexaReply()
Expand Down
Empty file removed docs/botframework.rst
Empty file.
2 changes: 1 addition & 1 deletion docs/dialogflow-events.rst
Expand Up @@ -3,7 +3,7 @@
.. _googleassistant-event:

The ``GoogleAssistantEvent`` Object
==============================
===================================

.. js:class:: GoogleAssistantEvent(event, lambdaContext)

Expand Down
62 changes: 51 additions & 11 deletions docs/dialogflow-platforms.rst
Expand Up @@ -7,6 +7,20 @@ Dialogflow offers a variety of integrations so you share your base code across s

More integrations comming soon to Voxa

.. _google_assistant:

Google Assistant
----------------

The most common Dialogflow integration is the GoogleAssistantPlatform.

.. code-block:: javascript
const { GoogleAssistantPlatform } = require('voxa');
const app = new VoxaApp({ views, variables });
const googleAction = new GoogleAssistantPlatform(app);
.. _facebook:

Expand All @@ -30,7 +44,9 @@ Voxa will use this token to perform some authentication operations like sending

Voxa also offers a variety of built-in rich components for you to send along with your response. For now, you can integrate the following:

- Account Linking button
Account Linking button
----------------------

You need to include in your controller the following field: ``facebookAccountLink``, which takes a URL to go into the account linking flow. For more information about the account linking flow, check how to add a `Log In Button <https://developers.facebook.com/docs/messenger-platform/send-messages/buttons#login>`_, and `Account Linking <https://developers.facebook.com/docs/messenger-platform/identity/account-linking>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -59,7 +75,9 @@ Or you can also handle these values from your views file
}
}
- Account Unlink button
Account Unlink button
---------------------

You need to include in your controller the following field: ``facebookAccountUnlink``, which can take any value like a boolean, just to indicate to Voxa we're adding this button to the response. For more information about the account linking flow, check how to add a `Log Out Button <https://developers.facebook.com/docs/messenger-platform/send-messages/buttons#logout>`_, and `Account Linking <https://developers.facebook.com/docs/messenger-platform/identity/account-linking>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -89,7 +107,9 @@ Or you can also handle these values from your views file
}
- Location Quick Reply
Location Quick Reply
--------------------

You need to include in your controller the following field: ``facebookQuickReplyLocation``, which takes a string with the title of the message that goes along with the button requesting user's location. For more information about the account linking flow, check how to add a `Location Quick Reply <https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies#locations>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -119,7 +139,9 @@ Or you can also handle these values from your views file
}
- Phone Number Quick Reply
Phone Number Quick Reply
------------------------

You need to include in your controller the following field: ``facebookQuickReplyPhoneNumber``, which takes a string with the title of the message that goes along with the button requesting user's phone number. For more information about the account linking flow, check how to add a `User Phone Number Quick Reply <https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies#phone>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -149,7 +171,9 @@ Or you can also handle these values from your views file
}
- Text Quick Reply
Text Quick Reply
----------------

You need to include in your controller the following field: ``directives``, which takes an array of directives, and the one you're going to send is a FacebookQuickReplyText directive, that takes 2 parameters:
- message: string with the title of the message that goes along with the button requesting user's email.
- replyArray: a IFacebookQuickReply object or array of objets with the options to render in the chat.
Expand Down Expand Up @@ -225,7 +249,9 @@ Or you can also handle these values from your views file
},
- Email Quick Reply
Email Quick Reply
-----------------

You need to include in your controller the following field: ``facebookQuickReplyUserEmail``, which takes a string with the title of the message that goes along with the button requesting user's email. For more information about the account linking flow, check how to add a `User Email Quick Reply <https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies#email>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -255,7 +281,9 @@ Or you can also handle these values from your views file
}
- Postbacks buttons (Suggestion chips)
Postbacks buttons (Suggestion chips)
------------------------------------

You need to include in your controller the following field: ``facebookSuggestionChips``, which could be a simple string that the Voxa renderer will get from your views file with an array of strings, or directly an array of strings. For more information about this, check how to add `Postback Buttons <https://developers.facebook.com/docs/messenger-platform/send-messages/buttons#postback>`_.

.. code-block:: javascript
Expand Down Expand Up @@ -287,10 +315,13 @@ Or you can also handle these values from your views file
}
- Carousel
Carousel
--------

You need to include in your controller the following field: ``facebookCarousel``, which takes an object with an array of elements to be taken as items in a generic list of buttons. For more information about the carousel, check how to add a `Generic Template <https://developers.facebook.com/docs/messenger-platform/send-messages/template/generic>`_.

.. code-block:: javascript
const {
FACEBOOK_BUTTONS,
FACEBOOK_WEBVIEW_HEIGHT_RATIO,
Expand Down Expand Up @@ -406,10 +437,13 @@ Or you can also handle these values from your views file
},
- List
List
----

You need to include in your controller the following field: ``facebookList``, which takes an object with an array of elements to be taken as items in a list of buttons. For more information about the carousel, check how to add a `List Template <https://developers.facebook.com/docs/messenger-platform/send-messages/template/list>`_.

.. code-block:: javascript
const {
FACEBOOK_BUTTONS,
FACEBOOK_WEBVIEW_HEIGHT_RATIO,
Expand Down Expand Up @@ -544,10 +578,13 @@ Or you can also handle these values from your views file
},
- Button Template
Button Template
---------------

You need to include in your controller the following field: ``facebookButtonTemplate``, which takes an object with an array of buttons to be taken as items in a list of buttons. For more information about the button template, check how to add a `Button Template <https://developers.facebook.com/docs/messenger-platform/send-messages/template/button>`_.

.. code-block:: javascript
const {
FACEBOOK_BUTTONS,
FacebookButtonTemplateBuilder,
Expand Down Expand Up @@ -637,10 +674,13 @@ Or you can also handle these values from your views file
},
- Open Graph Template
Open Graph Template
-------------------

You need to include in your controller the following field: ``facebookOpenGraphTemplate``, which takes an object with an array of buttons to be taken as items in a list of buttons and a url for the open graph link. For more information about the button template, check how to add a `Open Graph Template <https://developers.facebook.com/docs/messenger-platform/send-messages/template/open-graph>`_.

.. code-block:: javascript
const {
FACEBOOK_BUTTONS,
FacebookButtonTemplateBuilder,
Expand Down
Empty file removed docs/dialogflow.rst
Empty file.
Empty file removed docs/directives.rst
Empty file.
3 changes: 1 addition & 2 deletions docs/gameEngine.rst
Expand Up @@ -95,7 +95,7 @@ A very simple example on how the GameEngine.InputHandlerEvent JSON request from
}
The field `originatingRequestId`_ provides the requestId of the request to which you responded with a StartInputHandler directive. You need to save this value in your session attributes to send the `StopInputHandler <https://developer.amazon.com/docs/gadget-skills/gameengine-interface-reference.html#stop>`_ directive. You can send this directive with Voxa as follows:
The field ``originatingRequestId`` provides the requestId of the request to which you responded with a StartInputHandler directive. You need to save this value in your session attributes to send the `StopInputHandler <https://developer.amazon.com/docs/gadget-skills/gameengine-interface-reference.html#stop>`_ directive. You can send this directive with Voxa as follows:

.. code-block:: javascript
Expand All @@ -111,4 +111,3 @@ The field `originatingRequestId`_ provides the requestId of the request to which
});
This will stop Echo Button events to be sent to your skill.

1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -138,6 +138,7 @@ Links
botframework-directives
dialogflow-platforms
alexa-apis
canFulfillIntentRequest
lwa
google-sign-in
voxa-reply
Expand Down
5 changes: 4 additions & 1 deletion docs/voxa-reply.rst
Expand Up @@ -44,4 +44,7 @@ The ``reply`` Object

For the speceific classes used in every platform you can check:

- :ref:`AlexaReply <alexa-reply>`
.. toctree::
:maxdepth: 2

alexa-reply
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -41,11 +41,11 @@
"@types/tedious": "^2.6.1",
"@types/url-join": "^4.0.0",
"@types/uuid": "^3.4.3",
"actions-on-google": "^2.5.0",
"actions-on-google": "^2.6.0",
"ask-sdk-model": "^1.11.1",
"azure-functions-ts-essentials": "^1.3.2",
"bluebird": "^3.5.1",
"botbuilder": "3",
"botbuilder": "^3.16",
"fast-xml-parser": "^3.12.13",
"google-auth-library": "1",
"i18next": "^12.1.0",
Expand Down
3 changes: 2 additions & 1 deletion run-ci.sh
Expand Up @@ -5,8 +5,9 @@ set -o xtrace
yarn run test-ci
yarn run report
yarn run lint
npx nyc check-coverage

npx typedoc --out typedoc --name Voxa --readme ./README.md --target ES5 --ignoreCompilerErrors ./src
npx typedoc --out typedoc --name Voxa --readme ./README.md --target ES2017 --ignoreCompilerErrors ./src
export NODE_VERSION=${TRAVIS_NODE_VERSION:-}
if [ -z "${NODE_VERSION}" ]; then
export NODE_VERSION=$(node --version | cut -d 'v' -f2 | cut -d'.' -f1,2)
Expand Down
59 changes: 36 additions & 23 deletions src/VoxaApp.ts
Expand Up @@ -458,30 +458,20 @@ export class VoxaApp {

const directivesKeyOrder = _.map(directiveClasses, "key");
if (transition.reply) {
const replyTransition = await this.getReplyTransitions(voxaEvent, transition);
const replyTransition = await this.getReplyTransitions(
voxaEvent,
transition,
);
transition = _.merge(transition, replyTransition);
}

const directives: IDirective[] = _(transition)
.toPairs()
.sortBy((pair) => {
.sortBy((pair: any[]) => {
const [key, value] = pair;
return _.indexOf(directivesKeyOrder, key);
})
.map(
_.spread(
function instantiateDirectives(key, value): IDirective[] {
const handlers: IDirectiveClass[] = _.filter(
directiveClasses,
(classObject: IDirectiveClass) => classObject.key === key,
);
return _.map(
handlers,
(Directive: IDirectiveClass) => new Directive(value),
) as IDirective[];
},
),
)
.map(_.spread(instantiateDirectives))
.flatten()
.concat(transition.directives || [])
.filter()
Expand All @@ -501,6 +491,26 @@ export class VoxaApp {
}

return transition;

function instantiateDirectives(key: string, value: any): IDirective[] {
let handlers: IDirectiveClass[] = _.filter(
directiveClasses,
(classObject: IDirectiveClass) => classObject.key === key,
);

if (handlers.length > 1) {
handlers = _.filter(
handlers,
(handler: IDirectiveClass) =>
handler.platform === voxaEvent.platform.name,
);
}

return _.map(
handlers,
(Directive: IDirectiveClass) => new Directive(value),
) as IDirective[];
}
}

public async saveSession(
Expand Down Expand Up @@ -542,7 +552,10 @@ export class VoxaApp {
voxaEvent.renderer = this.renderer;
}

private async getReplyTransitions(voxaEvent: IVoxaEvent, transition: ITransition): Promise<ITransition> {
private async getReplyTransitions(
voxaEvent: IVoxaEvent,
transition: ITransition,
): Promise<ITransition> {
if (!transition.reply) {
return {};
}
Expand All @@ -556,19 +569,19 @@ export class VoxaApp {
}

for (const replyItem of replies) {
const reply = await voxaEvent.renderer.renderPath(
replyItem,
voxaEvent,
);
const reply = await voxaEvent.renderer.renderPath(replyItem, voxaEvent);
const replyKeys = _.keys(reply);
const replyData = _(replyKeys)
const replyData = _(replyKeys)
.map((key) => {
return [key, replyItem + "." + key];
})
.fromPairs()
.value();

finalReply = _.mergeWith(finalReply, replyData, function customizer(objValue, srcValue) {
finalReply = _.mergeWith(finalReply, replyData, function customizer(
objValue,
srcValue,
) {
if (!objValue) {
return; // use default merge behavior
}
Expand Down
2 changes: 1 addition & 1 deletion src/directives.ts
Expand Up @@ -29,7 +29,7 @@ export interface IDirective {
) => Promise<void>;
}

function sampleOrItem(
export function sampleOrItem(
statement: string | string[],
platform: VoxaPlatform,
): string {
Expand Down

0 comments on commit fc14059

Please sign in to comment.