voxa
Version:
A fsm (state machine) framework for Alexa, Dialogflow, Facebook Messenger and Botframework apps using Node.js
200 lines (167 loc) • 5.28 kB
text/typescript
/*
* Directives are functions that apply changes on the reply object. They can be registered as keys on the voxa
* application and then used on transitions
*
* For example, the reply directive is used as part of the transition to render ask, say, tell, reprompt or directives.
*
* return { reply: 'View' }
*/
import * as bluebird from "bluebird";
import * as _ from "lodash";
import { VoxaPlatform } from "./platforms/VoxaPlatform";
import { ITransition } from "./StateMachine";
import { IVoxaEvent } from "./VoxaEvent";
import { IVoxaReply } from "./VoxaReply";
export interface IDirectiveClass {
platform: string; // botframework, dialogflow or alexa
key: string; // The key in the transition that links to the specific directive
new (...args: any[]): IDirective;
}
export interface IDirective {
writeToReply: (
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
) => Promise<void>;
}
export function sampleOrItem(
statement: string | string[],
platform: VoxaPlatform,
): string {
if (_.isArray(statement)) {
if (platform.config.test) {
return _.head(statement) as string;
}
return _.sample(statement) as string;
}
return statement;
}
export class Reprompt implements IDirective {
public static key: string = "reprompt";
public static platform: string = "core";
constructor(public viewPath: string) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
const statement = await event.renderer.renderPath(this.viewPath, event);
reply.addReprompt(sampleOrItem(statement, event.platform));
}
}
export interface IAskStatement {
ask: string;
reprompt?: string;
}
export class Ask implements IDirective {
public static key: string = "ask";
public static platform: string = "core";
public viewPaths: string[];
constructor(viewPaths: string | string[]) {
this.viewPaths = _.isString(viewPaths) ? [viewPaths] : viewPaths;
}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
transition.flow = "yield";
transition.say = this.viewPaths;
for (const viewPath of this.viewPaths) {
const statement = await event.renderer.renderPath(viewPath, event);
if (!statement.ask) {
reply.addStatement(sampleOrItem(statement, event.platform));
} else {
this.addStatementToReply(statement, reply, event);
}
}
}
private addStatementToReply(
statement: IAskStatement,
reply: IVoxaReply,
event: IVoxaEvent,
) {
reply.addStatement(sampleOrItem(statement.ask, event.platform));
if (statement.reprompt) {
reply.addReprompt(sampleOrItem(statement.reprompt, event.platform));
}
}
}
export class Say implements IDirective {
public static key: string = "say";
public static platform: string = "core";
constructor(public viewPaths: string | string[]) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
let viewPaths = this.viewPaths;
if (_.isString(viewPaths)) {
viewPaths = [viewPaths];
}
await bluebird.mapSeries(viewPaths, async (view: string) => {
const statement = await event.renderer.renderPath(view, event);
reply.addStatement(sampleOrItem(statement, event.platform));
});
}
}
export class SayP implements IDirective {
public static key: string = "sayp";
public static platform: string = "core";
constructor(public statement: string) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
reply.addStatement(this.statement);
}
}
export class Tell implements IDirective {
public static key: string = "tell";
public static platform: string = "core";
constructor(public viewPath: string) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
const statement = await event.renderer.renderPath(this.viewPath, event);
reply.addStatement(sampleOrItem(statement, event.platform));
reply.terminate();
transition.flow = "terminate";
transition.say = this.viewPath;
}
}
export class Text implements IDirective {
public static key: string = "text";
public static platform: string = "core";
constructor(public viewPaths: string | string[]) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
let viewPaths = this.viewPaths;
if (_.isString(viewPaths)) {
viewPaths = [viewPaths];
}
await bluebird.mapSeries(viewPaths, async (view: string) => {
const statement = await event.renderer.renderPath(view, event);
reply.addStatement(sampleOrItem(statement, event.platform), true);
});
}
}
export class TextP implements IDirective {
public static key: string = "textp";
public static platform: string = "core";
constructor(public text: string) {}
public async writeToReply(
reply: IVoxaReply,
event: IVoxaEvent,
transition: ITransition,
): Promise<void> {
reply.addStatement(this.text, true);
}
}