Voxa Application¶
-
class
VoxaApp
(config)¶ Arguments: - config – Configuration for your skill, it should include Views and Variables and optionally a model and a list of appIds.
If appIds is present then the framework will check every alexa event and enforce the application id to match one of the specified application ids.
const app = new VoxaApp.pp({ Model, variables, views, appIds });
-
VoxaApp.
execute
(event, context)¶ The main entry point for the Skill execution
Arguments: - event – The event sent by the platform.
- context – The context of the lambda function
Returns: Promise: A response resolving to a javascript object to be sent as a result to Alexa.
app.execute(event, context) .then(result => callback(null, result)) .catch(callback);
-
VoxaApp.
onState
(stateName, handler)¶ Maps a handler to a state
Arguments: - stateName (string) – The name of the state
- handler (function/object) – The controller to handle the state
- intent (string/array) – The intents that this state will handle
Returns: An object or a promise that resolves to an object that specifies a transition to another state and/or a view to render
app.onState('entry', { LaunchIntent: 'launch', 'AMAZON.HelpIntent': 'help', }); app.onState('launch', (voxaEvent) => { return { tell: 'LaunchIntent.OpenResponse', to: 'die' }; });
Also you can use a shorthand version to define a controller. This is very useful when having a controller that only returns a transition
voxaApp.onState('launch', { flow: 'yield' reply: 'LaunchIntent.OpenResponse', to: 'nextState' } );
You can also set the intent that the controller will handle. If set, any other triggered intent will not enter into the controller.
voxaApp.onState("agreed?", { to: "PurchaseAccepted" }, "YesIntent"); voxaApp.onState("agreed?", { to: "TransactionCancelled" }, ["NoIntent", "CancelIntent"]); voxaApp.onState("agreed?", { to: "agreed?", reply: "Help.ArticleExplanation", flow: "yield" }, "HelpIntent"); voxaApp.onState("agreed?", { to: "agreed?", reply: "UnknownInput", flow: "yield" });
The order on how you declare your controllers matter in Voxa
You can set multiple controllers for a single state, so how do you know which code will be executed? The first one that Voxa finds. Take this example:
voxaApp.onState('ProcessUserRequest', (voxaEvent) => { // Some code return { tell: 'ThankYouResponse', to: 'die' }; }); voxaApp.onState('ProcessUserRequest', (voxaEvent) => { // Some other code return { tell: 'GoodbyeResponse', to: 'die' }; });
If the state machine goes to the ProcessUserRequest, the code running will always be the first one, so the user will always hear the ThankYouResponse.
The only scenario where this is overwritten is when you have more than one handler for the same state, and one of them has one or more intents defined. If the user triggers the intent that’s inside the list of one-controller intents, Voxa will give it priority. For example, take this code:
voxaApp.onState("agreed?", { to: "PurchaseAccepted" }, "YesIntent"); voxaApp.onState("agreed?", { to: "agreed?", reply: "UnknownInput", flow: "yield" }); voxaApp.onState("agreed?", { to: "TransactionCancelled" }, ["NoIntent", "CancelIntent"]);
If the user triggers the NoIntent, and the state machine goes to the agreed? state, the user will listen to the TransactionCancelled response, it doesn’t matter if the controller is placed above or below a controller without defined intents, the priority will go to the controller with the defined intent.
-
VoxaApp.
onIntent
(intentName, handler)¶ A shortcut for definining state controllers that map directly to an intent
Arguments: - intentName (string) – The name of the intent
- handler (function/object) – The controller to handle the state
Returns: An object or a promise that resolves to an object that specifies a transition to another state and/or a view to render
app.onIntent('HelpIntent', (voxaEvent) => { return { tell: 'HelpIntent.HelpAboutSkill' }; });
-
VoxaApp.
onIntentRequest
(callback[, atLast])¶ This is executed for all
IntentRequest
events, default behavior is to execute the State Machine machinery, you generally don’t need to override this.Arguments: - callback (function) –
- last (bool) –
Returns: Promise
-
VoxaApp.
onLaunchRequest
(callback[, atLast])¶ Adds a callback to be executed when processing a
LaunchRequest
, the default behavior is to fake the alexa event as anIntentRequest
with aLaunchIntent
and just defer to theonIntentRequest
handlers. You generally don’t need to override this.
-
VoxaApp.
onBeforeStateChanged
(callback[, atLast])¶ This is executed before entering every state, it can be used to track state changes or make changes to the alexa event object
-
VoxaApp.
onBeforeReplySent
(callback[, atLast])¶ Adds a callback to be executed just before sending the reply, internally this is used to add the serialized model and next state to the session.
It can be used to alter the reply, or for example to track the final response sent to a user in analytics.
app.onBeforeReplySent((voxaEvent, reply) => { const rendered = reply.write(); analytics.track(voxaEvent, rendered) });
-
VoxaApp.
onAfterStateChanged
(callback[, atLast])¶ Adds callbacks to be executed on the result of a state transition, this are called after every transition and internally it’s used to render the transition
reply
using the views and variablesThe callbacks get
voxaEvent
,reply
andtransition
params, it should return the transition objectapp.onAfterStateChanged((voxaEvent, reply, transition) => { if (transition.reply === 'LaunchIntent.PlayTodayLesson') { transition.reply = _.sample(['LaunchIntent.PlayTodayLesson1', 'LaunchIntent.PlayTodayLesson2']); } return transition; });
-
VoxaApp.
onUnhandledState
(callback[, atLast])¶ Adds a callback to be executed when a state transition fails to generate a result, this usually happens when redirecting to a missing state or an entry call for a non configured intent, the handlers get a alexa event parameter and should return a transition the same as a state controller would.
-
VoxaApp.
onSessionStarted
(callback[, atLast])¶ Adds a callback to the
onSessinStarted
event, this executes for all events wherevoxaEvent.session.new === true
This can be useful to track analytics
app.onSessionStarted((voxaEvent, reply) => { analytics.trackSessionStarted(voxaEvent); });
-
VoxaApp.
onRequestStarted
(callback[, atLast])¶ Adds a callback to be executed whenever there’s a
LaunchRequest
,IntentRequest
or aSessionEndedRequest
, this can be used to initialize your analytics or get your account linking user data. Internally it’s used to initialize the model based on the event sessionapp.onRequestStarted((voxaEvent, reply) => { let data = ... // deserialized from the platform's session voxaEvent.model = this.config.Model.deserialize(data, voxaEvent); });
-
VoxaApp.
onSessionEnded
(callback[, atLast])¶ Adds a callback to the
onSessionEnded
event, this is called for everySessionEndedRequest
or when the skill returns a transition to a state whereisTerminal === true
, normally this is a transition to thedie
state. You would normally use this to track analytics
-
VoxaApp.onSystem.
ExceptionEncountered
(callback[, atLast])¶ This handles System.ExceptionEncountered event that are sent to your skill when a response to an
AudioPlayer
event causes an errorreturn Promise.reduce(errorHandlers, (result, errorHandler) => { if (result) { return result; } return Promise.resolve(errorHandler(voxaEvent, error)); }, null);
Error handlers¶
You can register many error handlers to be used for the different kind of errors the application could generate. They all follow the same logic where if the first error type is not handled then the default is to be deferred to the more general error handler that ultimately just returns a default error reply.
They’re executed sequentially and will stop when the first handler returns a reply.
-
VoxaApp.
onError
(callback[, atLast])¶ This is the more general handler and will catch all unhandled errors in the framework, it gets
(voxaEvent, error)
parameters as argumentsapp.onError((voxaEvent, error) => { return new Reply(voxaEvent, { tell: 'An unrecoverable error occurred.' }) .write(); });
Playback Controller handlers¶
Handle events from the AudioPlayer interface
-
audioPlayerCallback
(voxaEvent, reply)¶ All audio player middleware callbacks get a alexa event and a reply object
Arguments: - voxaEvent (AlexaEvent) – The alexa event sent by Alexa
- reply (object) – A reply to be sent as a response
Returns object write: Your alexa event handler should return an appropriate response according to the event type, this generally means appending to the reply object
In the following example the alexa event handler returns a
REPLACE_ENQUEUED
directive to aPlaybackNearlyFinished()
event.app['onAudioPlayer.PlaybackNearlyFinished']((voxaEvent, reply) => { const playAudio = new PlayAudio({ behavior: "REPLACE_ALL", offsetInMilliseconds: 0, token: "", url: 'https://www.dl-sounds.com/wp-content/uploads/edd/2016/09/Classical-Bed3-preview.mp3' }); playAudio.writeToReply(reply); return reply; });
-
VoxaApp.onAudioPlayer.
PlaybackStarted
(callback[, atLast])¶
-
VoxaApp.onAudioPlayer.
PlaybackFinished
(callback[, atLast])¶
-
VoxaApp.onAudioPlayer.
PlaybackStopped
(callback[, atLast])¶
-
VoxaApp.onAudioPlayer.
PlaybackFailed
(callback[, atLast])¶
-
VoxaApp.onAudioPlayer.
PlaybackNearlyFinished
(callback[, atLast])¶
-
VoxaApp.onPlaybackController.
NextCommandIssued
(callback[, atLast])¶
-
VoxaApp.onPlaybackController.
PauseCommandIssued
(callback[, atLast])¶
-
VoxaApp.onPlaybackController.
PlayCommandIssued
(callback[, atLast])¶
-
VoxaApp.onPlaybackController.
PreviousCommandIssued
(callback[, atLast])¶
Alexa Skill Event handlers¶
Handle request for the Alexa Skill Events
-
alexaSkillEventCallback
(alexaEvent)¶ All the alexa skill event callbacks get a alexa event and a reply object
Arguments: - alexaEvent (AlexaEvent) – The alexa event sent by Alexa
- reply (object) – A reply to be sent as the response
Returns object reply: Alexa only needs an acknowledgement that you received and processed the event so it doesn’t need to resend the event. Just returning the reply object is enough
This is an example on how your skill can process a
SkillEnabled()
event.app['onAlexaSkillEvent.SkillEnabled']((alexaEvent, reply) => { const userId = alexaEvent.user.userId; console.log(`skill was enabled for user: ${userId}`); return reply; });
-
VoxaApp.onAlexaSkillEvent.
SkillAccountLinked
(callback[, atLast])¶
-
VoxaApp.onAlexaSkillEvent.
SkillEnabled
(callback[, atLast])¶
-
VoxaApp.onAlexaSkillEvent.
SkillDisabled
(callback[, atLast])¶
-
VoxaApp.onAlexaSkillEvent.
SkillPermissionAccepted
(callback[, atLast])¶
-
VoxaApp.onAlexaSkillEvent.
SkillPermissionChanged
(callback[, atLast])¶
Alexa List Event handlers¶
Handle request for the Alexa List Events
-
alexaListEventCallback
(alexaEvent)¶ All the alexa list event callbacks get a alexa event and a reply object
Arguments: - alexaEvent (AlexaEvent) – The alexa event sent by Alexa
- reply (object) – A reply to be sent as the response
Returns object reply: Alexa only needs an acknowledgement that you received and processed the event so it doesn’t need to resend the event. Just returning the reply object is enough
This is an example on how your skill can process a
ItemsCreated()
event.app['onAlexaHouseholdListEvent.ItemsCreated']((alexaEvent, reply) => { const listId = alexaEvent.request.body.listId; const userId = alexaEvent.user.userId; console.log(`Items created for list: ${listId}` for user ${userId}); return reply; });
-
VoxaApp.onAlexaHouseholdListEvent.
ItemsCreated
(callback[, atLast])¶
-
VoxaApp.onAlexaHouseholdListEvent.
ItemsUpdated
(callback[, atLast])¶
-
VoxaApp.onAlexaHouseholdListEvent.
ItemsDeleted
(callback[, atLast])¶