Skip to content

Commit

Permalink
Project doorperson.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zemnmez committed Jan 9, 2025
1 parent ee4c73e commit 5a31e87
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 56 deletions.
57 changes: 1 addition & 56 deletions ts/pulumi/lib/contact_flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,64 +9,9 @@ import {
Input,
} from '@pulumi/pulumi';

import { ContactFlowLanguage } from '#root/ts/pulumi/lib/contact_flow_language.js';
import { Err, Ok, Result } from '#root/ts/result.js';

interface ActionBase {
Identifier: string;
Type: string;
Parameters: unknown;
Transitions?: {
NextAction?: string;
Errors?: string[];
Conditions?: string[];
};
}

export interface EndFlowExecutionAction extends ActionBase {
Type: 'DisconnectParticipant';
Parameters: Record<string, never>;
Transitions?: Record<string, never>;
}

export interface MessageParticipantAction extends ActionBase {
Type: 'MessageParticipant';
Parameters: {
/**
* A prompt ID or prompt ARN to play to the participant along with gathering input. May not be specified if Text or SSML is also specified.
* Must be specified either statically or as a single valid JSONPath identifier
*/
PromptId?: string;
/**
* An optional string that defines text to send to the participant along with gathering input.
* May not be specified if PromptId or SSML is also specified. May be specified statically or dynamically.
*/
Text?: string;
/**
* An optional string that defines SSML to send to the participant along with gathering input. May not be specified if Text or
* PromptId is also specified May be specified statically or dynamically.
*/
SSML?: string;
media?: {
uri: string;
SourceType: 'S3';
MediaType: 'Audio';
};
};
Transitions: {
NextAction: string;
};
}

export type ContactFlowAction =
| MessageParticipantAction
| EndFlowExecutionAction;

export interface ContactFlowLanguage {
Version: '2019-10-30';
StartAction: string;
Actions: ContactFlowAction[];
}

export interface Args extends Omit<ContactFlowArgs, 'content'> {
content: Input<ContactFlowLanguage>;
}
Expand Down
117 changes: 117 additions & 0 deletions ts/pulumi/lib/contact_flow_composer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import * as regular_contact_flow from '#root/ts/pulumi/lib/contact_flow_language.js';

export interface ActionBase {
Type: string;
Parameters: unknown;
Transitions?: {
NextAction?: ContactFlowAction;
Errors?: ErrorTransition[];
Conditions?: string[];
};
}

export interface ErrorTransition {
NextAction: ContactFlowAction,
ErrorType: string
}

export interface ConditionTransition {
NextAction: ContactFlowAction,
Condition: unknown // TBD
}



export interface EndFlowExecutionAction extends ActionBase {
Type: 'DisconnectParticipant';
Parameters: Record<string, never>;
Transitions?: Record<string, never>;
}

export interface MessageParticipantAction extends ActionBase {
Type: 'MessageParticipant';
Parameters: {
/**
* A prompt ID or prompt ARN to play to the participant along with gathering input. May not be specified if Text or SSML is also specified.
* Must be specified either statically or as a single valid JSONPath identifier
*/
PromptId?: string;
/**
* An optional string that defines text to send to the participant along with gathering input.
* May not be specified if PromptId or SSML is also specified. May be specified statically or dynamically.
*/
Text?: string;
/**
* An optional string that defines SSML to send to the participant along with gathering input. May not be specified if Text or
* PromptId is also specified May be specified statically or dynamically.
*/
SSML?: string;
media?: {
uri: string;
SourceType: 'S3';
MediaType: 'Audio';
};
};
Transitions: {
NextAction: ContactFlowAction;
};
}

export type ContactFlowAction =
| MessageParticipantAction
| EndFlowExecutionAction;



export function compileContactFlow(main: ContactFlowAction): regular_contact_flow.ContactFlowLanguage {
const [self, actions] = _compileContactFlow(main, "root");
return {
Version: "2019-10-30",
StartAction: self.Identifier,
Actions: [...actions] as regular_contact_flow.ContactFlowAction[]

}
}

function _compileContactFlow(main: ActionBase, id: string): [
self: regular_contact_flow.ActionBase,
subActions: Set<regular_contact_flow.ActionBase>
] {
let actions = new Set<regular_contact_flow.ActionBase>();
const n = {
...main,
Identifier: id,
}

let ctr = 0;

function translateAction(a: ContactFlowAction): string {
const myId = `${id}|${ctr++}`;
const [, subActions] = _compileContactFlow(
a,
`${id}|${ctr++}`
);

actions = actions.union(
subActions
);

return myId;
}

const Transitions = n.Transitions
? {
NextAction: n.Transitions.NextAction ?
translateAction(n.Transitions.NextAction) :
n.Transitions.NextAction
} : n.Transitions;

const self = {
...n,
Transitions
};

actions.add(self)

return [ self, actions ]
}
68 changes: 68 additions & 0 deletions ts/pulumi/lib/contact_flow_language.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@



export interface ActionBase {
Identifier: string;
Type: string;
Parameters: unknown;
Transitions?: {
NextAction?: string;
Errors?: ErrorTransition[];
Conditions?: string[];
};
}

export interface ErrorTransition {
NextAction: string,
ErrorType: string
}

export interface ConditionTransition {
NextAction: string,
Condition: unknown // TBD
}

export interface EndFlowExecutionAction extends ActionBase {
Type: 'DisconnectParticipant';
Parameters: Record<string, never>;
Transitions?: Record<string, never>;
}

export interface MessageParticipantAction extends ActionBase {
Type: 'MessageParticipant';
Parameters: {
/**
* A prompt ID or prompt ARN to play to the participant along with gathering input. May not be specified if Text or SSML is also specified.
* Must be specified either statically or as a single valid JSONPath identifier
*/
PromptId?: string;
/**
* An optional string that defines text to send to the participant along with gathering input.
* May not be specified if PromptId or SSML is also specified. May be specified statically or dynamically.
*/
Text?: string;
/**
* An optional string that defines SSML to send to the participant along with gathering input. May not be specified if Text or
* PromptId is also specified May be specified statically or dynamically.
*/
SSML?: string;
media?: {
uri: string;
SourceType: 'S3';
MediaType: 'Audio';
};
};
Transitions: {
NextAction: string;
};
}

export type ContactFlowAction =
| MessageParticipantAction
| EndFlowExecutionAction;

export interface ContactFlowLanguage {
Version: '2019-10-30';
StartAction: string;
Actions: ContactFlowAction[];
}
40 changes: 40 additions & 0 deletions ts/pulumi/zemn.me/doorperson/doorperson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ComponentResource, ComponentResourceOptions, Input } from "@pulumi/pulumi";

import { ContactFlow } from "#root/ts/pulumi/lib/contact_flow.js";
import { compileContactFlow, ContactFlowAction } from "#root/ts/pulumi/lib/contact_flow_composer.js";
import { tagTrue } from "#root/ts/pulumi/lib/tags.js";


export interface Args {
zoneId: Input<string>;
domain: Input<string>
tags?: Input<Record<string, Input<string>>>;
}

export class Component extends ComponentResource {
constructor(
name: string,
args: Args,
opts?: ComponentResourceOptions
) {
super('ts:pulumi:zemn.me:doorperson', name, args, opts);
const tag = name;
const tags = mergeTags(args.tags, tagTrue(tag));

const begin: ContactFlowAction = {
Type: 'MessageParticipant',
Parameters: {
Text: "Enter a code now, or hold to contact the occupier.",
}
};


const flow = new ContactFlow(`${name}_contactFlow`, {
content: compileContactFlow(
begin
)
}, {parent: this})

}
}

0 comments on commit 5a31e87

Please sign in to comment.