Voximplant. Blog

IVR module usage example: multi-level menu

Most of IVRs nowadays provide caller with the number of options that can be chosen in a multi-level menu. While this kind of IVR can be built using vanilla VoxEngine javascript code, it’s better to use helper module (Modules.IVR) we created to simplify the process. It lets developers build IVR menus in scenarios much faster and write less code for that. Let’s build the following IVR using the module:

IVR scheme

It’s rather simple, but have many input types: noinput, select, inputfixed and inputunknown. VoxEngine scenario for this IVR menu:

  1. require(Modules.IVR); // enable IVR module
  2.  
  3. var inboundCall,
  4. outboundCall,
  5. introState,
  6. menuState,
  7. timeState,
  8. extState,
  9. fwdState,
  10. fwdNumber = null;
  11.  
  12. // Splice function for String class
  13. String.prototype.splice = function (idx, rem, s) {
  14. return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
  15. };
  16.  
  17. function initIVR() {
  18. /**
  19. * State that just says current UTC time
  20. */
  21. timeState = new IVRState("time", {
  22. type: "noinput",
  23. prompt: {
  24. say: "Current time in UTC time zone is " + (new Date().getUTCHours()) + ":" + (new Date().getUTCMinutes()),
  25. lang: Language.US_ENGLISH_FEMALE
  26. }
  27. });
  28.  
  29. /**
  30. * State that waits for 3-digit extension number
  31. * If 100 was entered - make a call to some employee
  32. */
  33. extState = new IVRState("extension", {
  34. type: "inputfixed",
  35. inputLength: 3,
  36. prompt: {
  37. say: "Please enter the extension of the person you are trying to reach",
  38. lang: Language.US_ENGLISH_FEMALE
  39. }
  40. }, function (data) {
  41. // Extension has been entered
  42. if (data == "100") {
  43. inboundCall.say("Forwarding your call to John Connor, please wait", Language.US_ENGLISH_FEMALE);
  44. inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
  45. } else {
  46. inboundCall.say("There is no person with extension " + data + ".", Language.US_ENGLISH_FEMALE);
  47. inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished2);
  48. }
  49. }, function (data) {
  50. // Timeout
  51. extState.enter(inboundCall);
  52. });
  53.  
  54. /**
  55. * State that waits for US phone number and #
  56. * if valid US phone number was specified it forwards call to this number
  57. */
  58. fwdState = new IVRState("callforward", {
  59. type: "inputunknown",
  60. terminateOn: "#",
  61. prompt: {
  62. say: "Please specify US phone number in internation format and press pound",
  63. lang: Language.US_ENGLISH_FEMALE
  64. }
  65. }, function (data) {
  66. // Input finished
  67. var number = data.replace("#", "");
  68. // Check if the specified number is valid US phone number
  69. Net.httpRequest("http://api.phone-validator.net/api/v2/verify?PhoneNumber=" + number + "&CountryCode=us", function (e) {
  70. if (e.code == 200) {
  71. var result = JSON.parse(e.text);
  72. if (result.status == "VALID_CONFIRMED") {
  73. fwdNumber = number;
  74. inboundCall.say("Forwarding your call to specified phone number, please wait", Language.US_ENGLISH_FEMALE);
  75. inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
  76. } else {
  77. inboundCall.say("You have specified wrong phone number.", Language.US_ENGLISH_FEMALE);
  78. inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
  79. }
  80. } else {
  81. inboundCall.say("Something went wrong, please try again.", Language.US_ENGLISH_FEMALE);
  82. inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
  83. }
  84. });
  85. }, function (data) {
  86. // Timeout
  87. fwdState.enter(inboundCall);
  88. });
  89.  
  90. /**
  91. * Menu state - 3 options
  92. */
  93. menuState = new IVRState("menu", {
  94. type: "select",
  95. prompt: {
  96. say: "Press 1 to say time, press 2 enter extension number, press 3 to forward call to specified US number.",
  97. lang: Language.US_ENGLISH_FEMALE
  98. },
  99. nextStates: {
  100. "1": timeState,
  101. "2": extState,
  102. "3": fwdState
  103. },
  104. }, null, function () {
  105. // Timeout
  106. menuState.enter(inboundCall);
  107. });
  108.  
  109. /**
  110. * Intro state
  111. */
  112. introState = new IVRState("intro", {
  113. type: "noinput",
  114. prompt: {
  115. say: "Hello, welcome to VoxImplant demo!",
  116. lang: Language.US_ENGLISH_FEMALE
  117. },
  118. nextState: menuState
  119. });
  120.  
  121. timeState.settings.nextState = menuState;
  122.  
  123. }
  124.  
  125. // Forwards call to phone number
  126. function handleFwdPlaybackFinished(e) {
  127. inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
  128. if (fwdNumber == null) {
  129. // Calling John
  130. outboundCall = VoxEngine.callPSTN("John's number");
  131. } else {
  132. // Calling specified phone number
  133. outboundCall = VoxEngine.callPSTN(fwdNumber);
  134. }
  135. outboundCall.addEventListener(CallEvents.Connected, function (e) {
  136. VoxEngine.sendMediaBetween(e.call, inboundCall);
  137. });
  138. outboundCall.addEventListener(CallEvents.Failed, VoxEngine.terminate);
  139. outboundCall.addEventListener(CallEvents.Disconnected, VoxEngine.terminate);
  140. }
  141.  
  142. // Wrong input - return to extState
  143. function handleFwdPlaybackFinished2(e) {
  144. inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished2);
  145. extState.enter(inboundCall);
  146. }
  147.  
  148. // Wrong input - return to fwdState
  149. function handleFwdPlaybackFinished3(e) {
  150. inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
  151. fwdState.enter(inboundCall);
  152. }
  153.  
  154. // Init IVR states after the session start
  155. VoxEngine.addEventListener(AppEvents.Started, function (e) {
  156. initIVR();
  157. });
  158.  
  159. // Handle incoming call
  160. VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) {
  161. inboundCall = e.call;
  162. // add event listeners
  163. inboundCall.addEventListener(CallEvents.Connected, handleCallConnected);
  164. inboundCall.addEventListener(CallEvents.Disconnected, handleCallDisconnected);
  165. inboundCall.answer(); // answer the call
  166. });
  167.  
  168. // After call connected enter introState
  169. function handleCallConnected(e) {
  170. introState.enter(inboundCall);
  171. }
  172.  
  173. function handleCallDisconnected(e) {
  174. // Just finish the session
  175. VoxEngine.terminate();
  176. }

Save the scenario, create new or use some existing application and create the application rule to forward inbound calls to this scenario.

Tagged in , ,

Comments