Last active
July 20, 2020 11:02
-
-
Save raarts/de06767d21e8edc9ea530dbc0ba994f1 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const debug = console.log; | |
let neemopGuards; | |
const buildGuards = (a) => a; | |
let neemopActions; | |
const buildActions = (a) => a; | |
let neemopServices; | |
const buildServices = (a) => a; | |
let neemopDelays; | |
const buildDelays = (a) => a; | |
let neemopContext; | |
const buildContext = (a) => a; | |
let neemopConfig; | |
const buildConfig = (a) => a; | |
let neemopOptions; | |
const buildOptions = (a) => a; | |
const play = async (context, prompt) => { | |
debug(`${prompt} (${prompt.length*200/1000}s)`); | |
return new Promise(function (resolve) { | |
setTimeout(resolve.bind(null, context), prompt.length * 200); | |
}); | |
}; | |
// eslint-disable-next-line prefer-const | |
neemopGuards = { | |
noNumber: (context) => context.number === '', | |
invalidNumber: (context) => (context.number && context.number.length > 0 && context.number.length < 10) || false, | |
maxRetry: (context) => (context.retry && context.retry >= 3) || false, | |
isMorning: () => true, | |
}; | |
const guardList = buildGuards(neemopGuards); | |
// eslint-disable-next-line prefer-const | |
neemopActions = { | |
incRetry: assign({ retry: (context) => context.retry + 1 }), | |
clearRetry: assign({ retry: () => 0 }), | |
addDigit: assign({ number: (context, event) => context.number + event.value }), | |
clearNumber: assign({ number: () => '' }), | |
savePlaybackId: assign({ playbackId: (context, event) => event.value }), | |
clearPlaybackId: assign({ playbackId: () => '' }), | |
stopPlayback: (context) => { | |
if (context.playbackId !== '') { | |
ari.playbacks | |
.stop({ playbackId: context.playbackId || '' }) | |
.then(() => { | |
// ignore this | |
}) | |
.catch((e) => { | |
debug('canceling playback:', e); | |
}); | |
} | |
}, | |
hangupChannel: (context) => ari.channels.hangup({ channelId: context.channel?.id || '' }).then(), | |
onEntryOffline: (context) => { | |
context.channel?.on('ChannelDtmfReceived', ChannelDtmfReceived); | |
context.channel?.on('ChannelStateChange', ChannelStateChange); | |
context.channel?.on('ChannelHangupRequest', ChannelHangupRequest); | |
context.channel?.answer().then(); | |
}, | |
logDialing: (context) => debug('dialing:', context.number), | |
logEvent: (context, event) => debug('event:', event), | |
}; | |
const actionList = buildActions(neemopActions); | |
// eslint-disable-next-line prefer-const | |
neemopServices = { | |
playWelcome: (context) => play(context, 'neemop/Goedemorgen'), | |
playEnterNumberToDial: (context) => play(context, 'neemop/toets_het_telefoonnr_dat_u_wilt_bellen'), | |
playNoValidInputReceived: (context) => play(context, 'neemop/geen_geldige_invoer_ontvangen'), | |
playNumberCannotBeDialed: (context) => play(context, 'neemop/dit_nummer_kan_niet_worden_gebeld'), | |
playLineWillBeDisconnected: (context) => play(context, 'neemop/de_verbinding_wordt_nu_verbroken'), | |
}; | |
const serviceList = buildServices(neemopServices); | |
// eslint-disable-next-line prefer-const | |
neemopDelays = { | |
DIGIT_TIMEOUT: 200, | |
RESPONSE_TIMEOUT: 5000, | |
DIAL_TIMEOUT: 60000, | |
ERROR_TIMEOUT: 60000, | |
}; | |
const delayList = buildDelays(neemopDelays); | |
// eslint-disable-next-line prefer-const | |
neemopContext = { | |
channel: null, | |
args: null, | |
playbackId: '', | |
number: '', | |
retry: 0, | |
}; | |
const context = buildContext(neemopContext); | |
// eslint-disable-next-line prefer-const | |
neemopOptions = { | |
guards: guardList, | |
actions: actionList, | |
services: serviceList, | |
delays: delayList, | |
}; | |
const options = buildOptions(neemopOptions); | |
// eslint-disable-next-line prefer-const | |
neemopConfig = { | |
id: 'neemop', | |
context, | |
initial: 'offline', | |
states: { | |
offline: { | |
entry: ['onEntryOffline'], | |
on: { | |
ANSWER: 'online', | |
}, | |
}, | |
done: { | |
id: 'done', | |
type: 'final', | |
}, | |
online: { | |
initial: 'welcome', | |
states: { | |
welcome: { | |
invoke: { | |
src: 'playWelcome', | |
}, | |
on: { | |
PLAYBACK_FINISHED: { target: '#getnumbergroup', actions: 'clearPlaybackId' }, | |
DIGIT: { | |
actions: ['stopPlayback', 'addDigit'], | |
}, | |
HASH: { | |
actions: ['stopPlayback'], | |
}, | |
STAR: { | |
actions: ['stopPlayback'], | |
}, | |
}, | |
after: { | |
ERROR_TIMEOUT: '#telldisconnect', | |
}, | |
}, | |
getnumbergroup: { | |
id: 'getnumbergroup', | |
initial: 'getnumberwithprompt', | |
states: { | |
novalidinputreceived: { | |
id: 'novalidinputreceived', | |
entry: ['clearNumber'], | |
invoke: { src: 'playNoValidInputReceived' }, | |
on: { | |
DIGIT: { | |
actions: ['stopPlayback', 'addDigit'], | |
target: '#getnumberwithoutprompt', | |
}, | |
HASH: { | |
actions: ['stopPlayback'], | |
}, | |
STAR: { | |
actions: ['stopPlayback', 'clearNumber'], | |
}, | |
PLAYBACK_FINISHED: [ | |
{ | |
cond: 'maxRetry', | |
target: '#telldisconnect', | |
}, | |
{ | |
actions: 'clearPlaybackId', | |
target: '#getnumberwithprompt', | |
}, | |
], | |
}, | |
after: { | |
ERROR_TIMEOUT: '#telldisconnect', | |
}, | |
}, | |
thisnumbercannotbedialed: { | |
id: 'thisnumbercannotbedialed', | |
entry: ['clearNumber'], | |
invoke: { src: 'playNumberCannotBeDialed' }, | |
on: { | |
DIGIT: { | |
actions: ['stopPlayback', 'addDigit'], | |
target: '#getnumberwithoutprompt', | |
}, | |
HASH: { | |
actions: ['stopPlayback'], | |
}, | |
STAR: { | |
actions: ['stopPlayback', 'clearNumber'], | |
}, | |
PLAYBACK_FINISHED: [ | |
{ | |
cond: 'maxRetry', | |
target: '#telldisconnect', | |
}, | |
{ | |
actions: 'clearPlaybackId', | |
target: '#getnumberwithprompt', | |
}, | |
], | |
}, | |
after: { | |
ERROR_TIMEOUT: '#telldisconnect', | |
}, | |
}, | |
getnumberwithprompt: { | |
id: 'getnumberwithprompt', | |
invoke: { src: 'playEnterNumberToDial' }, | |
on: { | |
DIGIT: { | |
actions: ['stopPlayback', 'addDigit'], | |
target: '#getnumberwithoutprompt', | |
}, | |
HASH: { | |
actions: ['incRetry'], | |
target: '#novalidinputreceived', | |
}, | |
PLAYBACK_FINISHED: { target: '#getnumberwithoutprompt', actions: 'clearPlaybackId' }, | |
}, | |
after: { | |
ERROR_TIMEOUT: '#telldisconnect', | |
}, | |
}, | |
getnumberwithoutprompt: { | |
id: 'getnumberwithoutprompt', | |
on: { | |
DIGIT: { | |
actions: ['addDigit'], | |
target: '#getnumberwithoutprompt', | |
}, | |
HASH: [ | |
{ | |
cond: 'noNumber', | |
actions: ['incRetry'], | |
target: '#novalidinputreceived', | |
}, | |
{ | |
cond: 'invalidNumber', | |
actions: ['incRetry'], | |
target: '#thisnumbercannotbedialed', | |
}, | |
{ | |
target: '#dialing', | |
}, | |
], | |
STAR: { | |
actions: ['clearNumber'], | |
target: '#getnumberwithprompt', | |
}, | |
PLAYBACK_FINISHED: { target: '#getnumberwithoutprompt', actions: 'clearPlaybackId' }, | |
}, | |
after: { | |
RESPONSE_TIMEOUT: [ | |
{ | |
cond: 'maxRetry', | |
actions: ['playNoValidInputReceived'], | |
target: '#telldisconnect', | |
}, | |
{ | |
cond: 'noNumber', | |
actions: ['incRetry'], | |
target: '#novalidinputreceived', | |
}, | |
{ | |
cond: 'invalidNumber', | |
actions: ['incRetry'], | |
target: '#thisnumbercannotbedialed', | |
}, | |
{ | |
target: '#dialing', | |
}, | |
], | |
}, | |
}, | |
}, | |
}, | |
dialing: { | |
id: 'dialing', | |
entry: ['clearRetry', 'logDialing'], | |
on: { | |
ANSWER: 'incall', | |
UNREACHABLE: '#thisnumbercannotbedialed', | |
}, | |
after: { | |
DIAL_TIMEOUT: '#telldisconnect', | |
}, | |
}, | |
incall: { | |
initial: 'call', | |
states: { | |
call: { | |
on: { | |
LASTMINUTEWARN: 'lastminute', | |
}, | |
}, | |
lastminute: { | |
on: { | |
LAST30SECWARN: 'last30secs', | |
}, | |
}, | |
last30secs: { | |
on: { | |
NOMONEYLEFT: '#telldisconnect', | |
}, | |
}, | |
}, | |
}, | |
telldisconnect: { | |
id: 'telldisconnect', | |
invoke: { src: 'playLineWillBeDisconnected' }, | |
on: { | |
PLAYBACK_FINISHED: { actions: 'hangupChannel' }, | |
}, | |
after: { | |
ERROR_TIMEOUT: { actions: 'hangupChannel' }, | |
}, | |
}, | |
}, | |
on: { | |
PLAYBACK_STARTED: { actions: 'savePlaybackId' }, | |
HANGUP: '#done', | |
}, | |
}, | |
}, | |
}; | |
const config = buildConfig(neemopConfig); | |
const neemopIncomingMachine = Machine(config, options); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment