right  Talk To Us!

voicemail Sample

An inbound application that handles answered inbound calls and offers the choice of recording a message or playing existing messages. An identity number is used to prevent unauthorised access to recorded messages. The recorded messages can be repeated, deleted or saved for later.

Uses actions: Run Menu, Play, Get Number, Redirect, Record, Delete File

    • {
          "actions" :
          [
              {
                  "run_menu" :
                  {
                      "prompt" :
                      {
                          "play" :
                          {
                              "play_list" :
                              [
                                  {
                                      "text_to_say" : "Press 1 to leave a message. Press 2 to listen to all messages."
                                  }
                              ]
                          }
                      },
                      "menu_options" :
                      [
                          {
                              "digit" : "1",
                              "next_page" :
                              {
                                  "url" : "RecordMessage"
                              }
                          },
                          {
                              "digit" : "2",
                              "next_page" :
                              {
                                  "url" : "GetPasswordNumber"
                              }
                          }
                      ]
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "-1",
          "api_version": "2.0"
      }
      
      
      
      
    • {
          "actions" :
          [
              {
                  "get_number":
                  {
                      "prompt" :
                      {
                          "play" :
                          {
                              "play_list" :
                              [
                                  {
                                      "text_to_say" : "Please enter your password number followed by the hash key."
                                  }
                              ]
                          }
                      },
                      "end_digit" : "#",
                      "next_page" :
                      {
                          "url" : "CheckPasswordNumber"
                      }
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "0",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "redirect" :
                  {
                      "next_page" :
                      {
                          "url" : "PlayMessage"
                      }
                  }
              }
          ],
          "token" : "0",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Sorry, that password is not correct. Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "0",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "file_to_play" : "<message file name>"
                          }
                      ]
                  }
              },
              {
                  "run_menu" :
                  {
                      "prompt" :
                      {
                          "play" :
                          {
                              "play_list" :
                              [
                                  {
                                      "text_to_say" : "Press 1 to hear the message again. Press 2 to delete it, or press 3 to save it."
                                  }
                              ]
                          }
                      },
                      "menu_options" :
                      [
                          {
                              "digit" : "1",
                              "next_page" :
                              {
                                  "url" : "MessageReplay"
                              }
                          },
                          {
                              "digit" : "2",
                              "next_page" :
                              {
                                  "url" : "MessageDelete"
                              }
                          },
                          {
                              "digit" : "3",
                              "next_page" :
                              {
                                  "url" : "MessageKeep"
                              }
                          }
                      ]
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "0",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "End of messages. Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Playing the message again."
                          }
                      ]
                  }
              },
              {
                  "redirect" :
                  {
                      "next_page" :
                      {
                          "url" : "PlayMessage"
                      }
                  }
              }
          ],
          "token" : "0",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "delete_file" :
                  {
                      "filename" : "/2014/08/12/12_30_01_04f01fb92e8913a8.65433.wav"
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Message deleted."
                          },
                          {
                              "text_to_say" : "Next message."
                          }
                      ]
                  }
              },
              {
                  "redirect" :
                  {
                      "next_page" :
                      {
                          "url" : "PlayMessage"
                      }
                  }
              }
          ],
          "token" : "1",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "delete_file" :
                  {
                      "filename" : "/2013/08/12/12_30_01_04f01fb92e8913a8.65433.wav"
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Message deleted."
                          }
                      ]
                  }
              },
              {
                  "redirect" :
                  {
                      "next_page" :
                      {
                          "url" : "PlayMessage"
                      }
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Message saved."
                          }
                      ]
                  }
              },
              {
                  "play" :
                  {
                      "play_list":
                      [
                          {
                              "text_to_say" : "Next message."
                          }
                      ]
                  }
              },
              {
                  "redirect" :
                  {
                      "next_page" :
                      {
                          "url" : "PlayMessage"
                      }
                  }
              }
          ],
          "token" : "1",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Message saved."
                          }
                      ]
                  }
              },
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "End of messages. Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Please leave a message after the beep. Press hash to end the recording or press star to cancel."
                          }
                      ]
                  }
              },
              {
                  "record" :
                  {
                      "beep_on_start" : true,
                      "milliseconds_max_silence" : 5000,
                      "barge_in_digits" : "#*",
                      "next_page" :
                      {
                          "url" : "RecordComplete"
                      }
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Thanks for leaving a message. Goodbye."
                          }
                      ]
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "Message recording cancelled. Goodbye."
                          }
                      ]
                  }
              },
              {
                  "delete_file":
                  {
                      "filename": "/rest_api/recordings/2018/10/06/rest_16_39_23_058d242936dcc5f9.4460.wav"
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          "actions" :
          [
              {
                  "play" :
                  {
                      "play_list" :
                      [
                          {
                              "text_to_say" : "There was no message recorded. Goodbye."
                          }
                      ]
                  }
              },
              {
                  "delete_file":
                  {
                      "filename": "/rest_api/recordings/2018/10/06/rest_16_39_23_058d242936dcc5f9.4460.wav"
                  }
              }
          ],
          "token" : "",
          "api_version": "2.0"
      }
      
    • {
          [
          ],
          "token" : "Error for Action: xxxx  ActionIndex: xxxx  Result: xxxx",
          "api_version": "2.0"
      }
      
    • {
          "api_version": "2.0"
      }
      
      
    • Implementing this sample as an ASP.Net Web application:

      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class Voicemail : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
        
                // Create the menu action
                Play menuPrompt = Play.SayText("Press 1 to leave a message. " + 
                                               "Press 2 to listen to all messages.");
                List<MenuOption> menuOptions = new List<MenuOption>
                {
                    new MenuOption('1', new WebPageRequest("RecordMessage.aspx")),
                    new MenuOption('2', new WebPageRequest("GetPasswordNumber.aspx"))
                };
                RunMenu runMenuAction = new RunMenu(menuOptions, menuPrompt);
                actions.Add(runMenuAction);
        
                // And add a final message
                actions.Add(Play.SayText("Goodbye."));
        
                // Respond
                // Set the first message to play if there is one
                string messageId = "-1";
                MessageFilenameDatabase db = new MessageFilenameDatabase();
                var ids = db.GetIds();
                if (ids.Count > 0)
                {
                    messageId = ids[0].ToString();
                }
                TelephonyResponse ourResponse = new TelephonyResponse(actions, messageId);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // GetPasswordNumber page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class GetPasswordNumber : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
        
                Play prompt = Play.SayText("Please enter your password number followed by the hash key.");
                GetNumber getNumberAction = new GetNumber(new WebPageRequest("CheckPasswordNumber.aspx"), prompt)
                {
                    EndDigit = '#'
                };
                actions.Add(getNumberAction);
        
                actions.Add(Play.SayText("Goodbye."));
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // CheckPasswordNumber page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class CheckPasswordNumber : System.Web.UI.Page
        {
            private static String myPassword = "1234";
        
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
                GetNumberResult getNumberResult = (GetNumberResult)ourRequest.InstanceInfo.ActionResult;
        
                // Set up the actions, depending on the entered password
                List<TelephonyAction> actions = new List<TelephonyAction>();
                if (getNumberResult.EnteredNumber.Equals(myPassword))
                {
                    actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));
                }
                else
                {
                    actions.Add(Play.SayText("Sorry, that password is not correct. Goodbye."));
                }
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // PlayMessage
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class PlayMessage : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                string token = ourRequest.InstanceInfo.Token;
                int messageId = Convert.ToInt32(token);
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
        
                MessageFilenameDatabase db = new MessageFilenameDatabase();
                string filename = db.GetMessageFilename(messageId);
                if (filename != null)
                {
                    actions.Add(Play.PlayFile(filename));
        
                    List<MenuOption> menuOptions = new List<MenuOption>
                    {
                        new MenuOption('1', new WebPageRequest("MessageReplay.aspx")),
                        new MenuOption('2', new WebPageRequest("MessageDelete.aspx")),
                        new MenuOption('3', new WebPageRequest("MessageKeep.aspx"))
                    };
                    actions.Add(new RunMenu(menuOptions, Play.SayText("Press 1 to hear the message again. " + 
                                                         "Press 2 to delete it, " + 
                                                         "or press 3 to save it.")
                                                         ));
                    actions.Add(Play.SayText("Goodbye."));
                }
                else
                {
                    actions.Add(Play.SayText("End of messages. Goodbye."));
                    token = "";
                }
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // MessageReplay page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class MessageReplay : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>
                {
                    Play.SayText("Playing the message again."),
                    new Redirect(new WebPageRequest("PlayMessage.aspx"))
                };
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // MessageDelete page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class MessageDelete : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                // The token should be the ID of the message file to delete
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
                int messageId = Convert.ToInt32(token);
        
                MessageFilenameDatabase db = new MessageFilenameDatabase();
                String filename = db.GetMessageFilename(messageId);
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
        
                int nextMessageId = -1;
                if (filename != null)
                {
                    // Delete action
                    actions.Add(new DeleteFile(filename));
                    Play msg = Play.SayText("Message deleted.");
        
                    // Get the next message ID
                    List<int> ids = db.GetIds();
                    for (int index = 0; index < ids.Count - 1; index++)
                    {
                        if (ids[index] == messageId)
                        {
                            nextMessageId = ids[index + 1];
                            msg.AddText("Next message.");
                            actions.Add(msg);
                            actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));
                            break;
                        }
                    }
        
                    if (nextMessageId == -1)
                    {
                        msg.AddText("End of messages. Goodbye.");
                        actions.Add(msg);
                    }
        
                    // Remove the entry from the DB
                    db.DeleteMessageFilename(messageId);
                }
        
                // Respond
                token = nextMessageId.ToString();
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // MessageKeep page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class MessageKeep : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                // The token should be the id of the message file to keep
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
                int messageId = Convert.ToInt32(token);
        
                MessageFilenameDatabase db = new MessageFilenameDatabase();
                String filename = db.GetMessageFilename(messageId);
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
                int nextMessageId = -1;
                if (filename != null)
                {
                    actions.Add(Play.SayText("Message saved."));
        
                    // Get the next message ID
                    List<int> ids = db.GetIds();
                    for (int index = 0; index < ids.Count - 1; index++)
                    {
                        if (ids[index] == messageId)
                        {
                            nextMessageId = ids[index + 1];
                            Play msg = Play.SayText("Next message.");
                            actions.Add(msg);
                            actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));
                            break;
                        }
                    }
        
                    if (nextMessageId == -1)
                    {
                        actions.Add(Play.SayText("End of messages. Goodbye."));
                    }
                }
        
                // Respond
                token = nextMessageId.ToString();
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // This prompts the caller to leave a message and starts a record action.
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class RecordMessage : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>
                {
                    Play.SayText("Please leave a message after the beep. Press hash to end the " +
                                 "recording or press star to cancel.")
                };
        
                Record recordAction = new Record(new WebPageRequest("RecordComplete.aspx"))
                {
                    BeepOnStart = true,
                    BargeInDigits = "#*",
                    MillisecondsMaxSilence = 5000
                };
                actions.Add(recordAction);
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • // CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // RecordComplete page
        
        using System;
        using System.Collections.Generic;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class RecordComplete : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                String token = ourRequest.InstanceInfo.Token;
                RecordResult result = (RecordResult)ourRequest.InstanceInfo.ActionResult;
        
                // Setup the actions
                List<TelephonyAction> actions = new List<TelephonyAction>();
        
                if (result.Reason.Equals("bargein") && result.BargeInDigit.Equals('*'))
                {
                    actions.Add(Play.SayText("Message recording cancelled. Goodbye."));
                    actions.Add(new DeleteFile(result.Filename));
                }
                else if (result.ContainsSound)
                {
                    // Store the filename in our message file
                    MessageFilenameDatabase db = new MessageFilenameDatabase();
                    int newMessageId = db.AppendMessageFilename(result.Filename);
                    actions.Add(Play.SayText("Thanks for leaving a message. Goodbye."));
                }
                else
                {
                    actions.Add(Play.SayText("There was no message recorded. Goodbye."));
                    actions.Add(new DeleteFile(result.Filename));
                }
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • using System;
        using System.IO;
        using System.Collections.Generic;
        using System.Linq;
        
        // File DB of voicemail message filenames
        //
        // Each row:  int Id, string Filename
        //
        public class MessageFilenameDatabase
        {
            private int nextId = 1;
        
            public MessageFilenameDatabase()
            {
                DbFilename = Path.GetTempPath() + "CSharpVoicemailMessages.tmp";
        
                // Initialise the id counter to the next highest int
                Dictionary<int, string> rows = GetRows();
                if (rows.Count > 0)
                {
                    nextId = (new List<int>(rows.Keys)).Max() + 1;
                }
            }
        
            public int Size()
            {
                if (!File.Exists(DbFilename))
                {
                    return 0;
                }
                String[] messageLines = File.ReadAllLines(DbFilename);
                return messageLines.Length;
            }
        
            public List<int> GetIds()
            {
                if (!File.Exists(DbFilename))
                {
                    return new List<int>();
                }
        
                Dictionary<int, string> rows = GetRows();
                return new List<int>(rows.Keys);
            }
        
            public String GetMessageFilename(int id)
            {
                if (!File.Exists(DbFilename))
                {
                    return null;
                }
        
                Dictionary<int, string> rows = GetRows();
                try
                {
                    string filename = rows[id];
                    return filename;
                }
                catch (KeyNotFoundException)
                {
                    return null;
                }
            }
        
            public int AppendMessageFilename(String filename)
            {
                Dictionary<int, string> rows;
                if (File.Exists(DbFilename))
                {
                    rows = GetRows();
                }
                else
                {
                    rows = new Dictionary<int, string>();
                }
        
                int newId = nextId++;
                rows.Add(newId, filename);
                SaveDatabaseFile(rows);
        
                return newId;
            }
        
            public void DeleteMessageFilename(int id)
            {
                if (!File.Exists(DbFilename))
                {
                    return;
                }
        
                Dictionary<int, string> rows = GetRows();
                try
                {
                    rows.Remove(id);
                }
                catch (KeyNotFoundException)
                {
                    return;
                }
        
                SaveDatabaseFile(rows);
            }
        
            private void SaveDatabaseFile(Dictionary<int, String> rows)
            {
                List<string> lines = new List<string>(rows.Count);
                foreach (KeyValuePair<int, string> entry in rows)
                {
                    lines.Add(String.Format("{0},{1}", entry.Key, entry.Value));
                }
                File.WriteAllLines(DbFilename, lines.ToArray());
            }
        
            public String DbFilename
            {
                get
                {
                    return dbFilename;
                }
                private set
                {
                    dbFilename = value;
                }
            }
        
            public Dictionary<int, string> GetRows()
            {
                Dictionary<int, string> rows = new Dictionary<int, string>();
        
                if (File.Exists(DbFilename))
                {
                    String[] messageLines = File.ReadAllLines(DbFilename);
                    foreach (string line in messageLines)
                    {
                        string[] splits = line.Split(',');
                        int id = Int32.Parse(splits[0]);
                        string filename = splits[1].Trim();
                        rows.Add(id, filename);
                    }
                }
                return rows;
            }
        
            private String dbFilename;
        }
        
        
        
      • using System;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class ErrorPage : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
                ErrorResult result = ourRequest.InstanceInfo.ErrorResult;
        
                String token = String.Format("Action: {0}\nActionIndex: {1}\nResult: {2}",
                    result.Action, result.ActionIndex, result.Result);
        
                // Respond
                TelephonyResponse ourResponse = new TelephonyResponse(null, token);
                ourResponse.ToHttpResponse(Response);
            }
        }
        
        
      • using System;
        using Aculab.Cloud.RestAPIWrapper;
        
        public partial class FinalPage : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                // Unpack the request
                TelephonyRequest ourRequest = new TelephonyRequest(Request);
            }
        }
        
        
    • Implementing this sample as an ASP.Net Core Web application:

      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
            {
                private static readonly String myPassword = "1234";
                // Process the GET or POST request, set up the actions and construct the json response.
                [Route("FirstPage")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> Voicemail()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>();
        
                        // Create the menu action
                        Play menuPrompt = Play.SayText("Press 1 to leave a message. " +
                                                       "Press 2 to listen to all messages.");
                        List<MenuOption> menuOptions = new List<MenuOption>()
                        {
                            new MenuOption('1', new WebPageRequest("Voicemail/RecordMessage")),
                            new MenuOption('2', new WebPageRequest("Voicemail/GetPasswordNumber"))
                        };
                        RunMenu runMenuAction = new RunMenu(menuOptions, menuPrompt);
                        actions.Add(runMenuAction);
        
                        // And add a final message
                        actions.Add(Play.SayText("Goodbye."));
        
                        // Create response
                        // Set the first message to play if there is one
                        string messageId = "-1";
                        MessageFilenameDatabase db = new MessageFilenameDatabase();
                        var ids = db.GetIds();
                        if (ids.Count > 0)
                        {
                            messageId = ids[0].ToString();
                        }
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, messageId);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
            {
                private static readonly String myPassword = "1234";
                // Process the GET or POST request, extract the transcription results and write to a file
                [Route("GetPasswordNumber")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> GetPasswordNumber()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>();
        
                        var prompt = Play.SayText("Please enter your password number followed by the hash key.");
                        var nextPage = new WebPageRequest("Voicemail/CheckPasswordNumber");
                        var getNumberAction = new GetNumber(nextPage, prompt)
                        {
                            EndDigit = '#'
                        };
                        actions.Add(getNumberAction);
        
                        actions.Add(Play.SayText("Goodbye."));
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
            {
                private static readonly String myPassword = "1234";
                // Process the GET or POST request, set up the actions and construct the json response.
                [Route("CheckPasswordNumber")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> CheckPasswordNumber()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
                        GetNumberResult getNumberResult = (GetNumberResult)telephonyRequest.InstanceInfo.ActionResult;
        
                        // Set up the actions, depending on the entered password
                        List<TelephonyAction> actions = new List<TelephonyAction>();
                        if (getNumberResult.EnteredNumber.Equals(myPassword))
                        {
                            actions.Add(new Redirect(new WebPageRequest("Voicemail/PlayMessage")));
                        }
                        else
                        {
                            actions.Add(Play.SayText("Sorry, that password is not correct. Goodbye."));
                        }
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
            {
                private static readonly String myPassword = "1234";
                [Route("PlayMessage")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> PlayMessage()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        string token = telephonyRequest.InstanceInfo.Token;
                        int messageId = Convert.ToInt32(token);
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>();
        
                        MessageFilenameDatabase db = new MessageFilenameDatabase();
                        string filename = db.GetMessageFilename(messageId);
                        if (filename != null)
                        {
                            actions.Add(Play.PlayFile(filename));
        
                            List<MenuOption> menuOptions = new List<MenuOption>
                            {
                                new MenuOption('1', new WebPageRequest("Voicemail/MessageReplay")),
                                new MenuOption('2', new WebPageRequest("Voicemail/MessageDelete")),
                                new MenuOption('3', new WebPageRequest("Voicemail/MessageKeep"))
                            };
                            actions.Add(new RunMenu(menuOptions, Play.SayText("Press 1 to hear the message again. " +
                                                                              "Press 2 to delete it, " +
                                                                              "or press 3 to save it.")));
                            actions.Add(Play.SayText("Goodbye."));
                        }
                        else
                        {
                            actions.Add(Play.SayText("End of messages. Goodbye."));
                            token = "";
                        }
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
            {
                [Route("MessageReplay")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> MessageReplay()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>()
                        {
                            Play.SayText("Playing the message again."),
                            new Redirect(new WebPageRequest("Voicemail/PlayMessage"))
                        };
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
            public class VoicemailController : ControllerBase
                [Route("MessageDelete")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> MessageDelete()
                {
                    try
                    {
                        // Unpack the request
                        // The token should be the ID of the message file to delete
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
                        int messageId = Convert.ToInt32(token);
        
                        var db = new MessageFilenameDatabase();
                        String filename = db.GetMessageFilename(messageId);
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>();
        
                        int nextMessageId = -1;
                        if (filename != null)
                        {
                            // Delete action
                            actions.Add(new DeleteFile(filename));
                            Play msg = Play.SayText("Message deleted.");
        
                            // Get the next message ID
                            List<int> ids = db.GetIds();
                            for (int index = 0; index < ids.Count - 1; index++)
                            {
                                if (ids[index] == messageId)
                                {
                                    nextMessageId = ids[index + 1];
                                    msg.AddText("Next message.");
                                    actions.Add(msg);
                                    actions.Add(new Redirect(new WebPageRequest("Voicemail/PlayMessage")));
                                    break;
                                }
                            }
        
                            if (nextMessageId == -1)
                            {
                                msg.AddText("End of messages. Goodbye.");
                                actions.Add(msg);
                            }
        
                            // Remove the entry from the DB
                            db.DeleteMessageFilename(messageId);
                        }
        
                        // Create response
                        token = nextMessageId.ToString();
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            [Route("Voicemail")]
                [Route("MessageKeep")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> MessageKeep()
                {
                    try
                    {
                        // Unpack the request
                        // The token should be the id of the message file to keep
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
                        int messageId = Convert.ToInt32(token);
        
                        MessageFilenameDatabase db = new MessageFilenameDatabase();
                        String filename = db.GetMessageFilename(messageId);
        
                        // Setup the actions
                        List<TelephonyAction> actions = new List<TelephonyAction>();
                        int nextMessageId = -1;
                        if (filename != null)
                        {
                            actions.Add(Play.SayText("Message saved."));
        
                            // Get the next message ID
                            List<int> ids = db.GetIds();
                            for (int index = 0; index < ids.Count - 1; index++)
                            {
                                if (ids[index] == messageId)
                                {
                                    nextMessageId = ids[index + 1];
                                    Play msg = Play.SayText("Next message.");
                                    actions.Add(msg);
                                    actions.Add(new Redirect(new WebPageRequest("Voicemail/PlayMessage")));
                                    break;
                                }
                            }
        
                            if (nextMessageId == -1)
                            {
                                actions.Add(Play.SayText("End of messages. Goodbye."));
                            }
                        }
        
                        // Create response
                        token = nextMessageId.ToString();
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
                        return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
                [Route("RecordMessage")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> RecordMessage()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>()
                        {
                            Play.SayText("Please leave a message after the beep. Press hash to end the " +
                                                 "recording or press star to cancel.")
                        };
        
                        Record recordAction = new Record(new WebPageRequest("Voicemail/RecordComplete"))
                        {
                            BeepOnStart = true,
                            BargeInDigits = "#*",
                            MillisecondsMaxSilence = 5000
                        };
                        actions.Add(recordAction);
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
                        return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
                    }
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        //
        // Voicemail:
        // An application that responds to inbound calls by prompting either
        // to leave a message or listen to all messages.
        // Recorded messages are saved to a simple file database.
        // Listening to messages requires a numeric password to be entered.
        using System;
        using System.Collections.Generic;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
                [Route("RecordComplete")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> RecordComplete()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
                        RecordResult result = (RecordResult)telephonyRequest.InstanceInfo.ActionResult;
        
                        // Setup the actions required
                        List<TelephonyAction> actions = new List<TelephonyAction>();
        
                        if (result.Reason.Equals("bargein") && result.BargeInDigit.Equals('*'))
                        {
                            actions.Add(Play.SayText("Message recording cancelled. Goodbye."));
                            actions.Add(new DeleteFile(result.Filename));
                        }
                        else if (result.ContainsSound)
                        {
                            // Store the filename in our message file
                            MessageFilenameDatabase db = new MessageFilenameDatabase();
                            int newMessageId = db.AppendMessageFilename(result.Filename);
                            actions.Add(Play.SayText("Thanks for leaving a message. Goodbye."));
                        }
                        else
                        {
                            actions.Add(Play.SayText("There was no message recorded. Goodbye."));
                            actions.Add(new DeleteFile(result.Filename));
                        }
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
                        return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
                    }
                }
            }
        }
        
      • using System;
        using System.IO;
        using System.Collections.Generic;
        using System.Linq;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples
        {
            // File DB of voicemail message filenames
            //
            // Each row:  int Id, string Filename
            //
            public class MessageFilenameDatabase
            {
                private int nextId = 1;
        
                public MessageFilenameDatabase()
                {
                    DbFilename = Path.GetTempPath() + "CSharpNetCoreVoicemailMessages.tmp";
        
                    // Initialise the id counter to the next highest int
                    Dictionary<int, string> rows = GetRows();
                    if (rows.Count > 0)
                    {
                        nextId = (new List<int>(rows.Keys)).Max() + 1;
                    }
                }
        
                public int Size()
                {
                    if (!File.Exists(DbFilename))
                    {
                        return 0;
                    }
                    String[] messageLines = File.ReadAllLines(DbFilename);
                    return messageLines.Length;
                }
        
                public List<int> GetIds()
                {
                    if (!File.Exists(DbFilename))
                    {
                        return new List<int>();
                    }
        
                    Dictionary<int, string> rows = GetRows();
                    return new List<int>(rows.Keys);
                }
        
                public String GetMessageFilename(int id)
                {
                    if (!File.Exists(DbFilename))
                    {
                        return null;
                    }
        
                    Dictionary<int, string> rows = GetRows();
                    try
                    {
                        string filename = rows[id];
                        return filename;
                    }
                    catch (KeyNotFoundException)
                    {
                        return null;
                    }
                }
        
                public int AppendMessageFilename(String filename)
                {
                    Dictionary<int, string> rows;
                    if (File.Exists(DbFilename))
                    {
                        rows = GetRows();
                    }
                    else
                    {
                        rows = new Dictionary<int, string>();
                    }
        
                    int newId = nextId++;
                    rows.Add(newId, filename);
                    SaveDatabaseFile(rows);
        
                    return newId;
                }
        
                public void DeleteMessageFilename(int id)
                {
                    if (!File.Exists(DbFilename))
                    {
                        return;
                    }
        
                    Dictionary<int, string> rows = GetRows();
                    try
                    {
                        rows.Remove(id);
                    }
                    catch (KeyNotFoundException)
                    {
                        return;
                    }
        
                    SaveDatabaseFile(rows);
                }
        
                private void SaveDatabaseFile(Dictionary<int, String> rows)
                {
                    List<string> lines = new List<string>(rows.Count);
                    foreach (KeyValuePair<int, string> entry in rows)
                    {
                        lines.Add(String.Format("{0},{1}", entry.Key, entry.Value));
                    }
                    File.WriteAllLines(DbFilename, lines);
                }
        
                public String DbFilename
                {
                    get
                    {
                        return dbFilename;
                    }
                    private set
                    {
                        dbFilename = value;
                    }
                }
        
                public Dictionary<int, string> GetRows()
                {
                    Dictionary<int, string> rows = new Dictionary<int, string>();
        
                    if (File.Exists(DbFilename))
                    {
                        String[] messageLines = File.ReadAllLines(DbFilename);
                        foreach (string line in messageLines)
                        {
                            string[] splits = line.Split(',');
                            int id = Int32.Parse(splits[0]);
                            string filename = splits[1].Trim();
                            rows.Add(id, filename);
                        }
                    }
                    return rows;
                }
        
                private String dbFilename;
            }
        }
        
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        
        using System;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            public class RESTSampleController : ControllerBase
            {
                // Process the GET or POST request for the Error condition
                [Route("ErrorPage")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> ErrorPage()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        ErrorResult result = telephonyRequest.InstanceInfo.ErrorResult;
        
                        String token = String.Format("Action: {0}\nActionIndex: {1}\nResult: {2}",
                            result.Action, result.ActionIndex, result.Result);
        
                        // Create response
                        TelephonyResponse ourResponse = new TelephonyResponse(null, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
                        return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
                    }
                }
            }
        }
        
      • // ASP.NET Core CSharp Wrapper sample for the Aculab Telephony REST API.
        
        using System;
        using Microsoft.AspNetCore.Mvc;
        using Aculab.Cloud.RestAPIWrapper;
        using System.Net;
        using System.Threading.Tasks;
        
        namespace Aculab.Cloud.RESTAPI.NETCoreCSharpSamples.Controllers
        {
            public class RESTSampleController : ControllerBase
            {
                // Process the GET or POST request for the Final Page
                [Route("FinalPage")]
                [HttpGet]
                [HttpPost]
                [ProducesResponseType(200)]
                [ProducesResponseType(400)]
                [ProducesResponseType(500)]
                public async Task<IActionResult> FinalPage()
                {
                    try
                    {
                        // Unpack the request
                        var telephonyRequest = await TelephonyRequest.UnpackRequestAsync(Request);
                        String token = telephonyRequest.InstanceInfo.Token;
        
                        // Create response
                        // Only very limited actions can be returned here
                        TelephonyResponse ourResponse = new TelephonyResponse(null, token);
                        return new OkObjectResult(ourResponse.ToJson(this));
                    }
                    catch (ArgumentException)
                    {
                        return BadRequest();
                    }
                    catch (Exception e)
                    {
                        return StatusCode((int)HttpStatusCode.InternalServerError, e.Message);
                    }
                }
            }
        }
        
  • Implemented as ASP.Net Web Forms:

    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' The first page for the Voicemail sample:
      ' An application that responds to inbound calls by prompting either
      ' to leave a message or listen to all messages.
      ' Recorded messages are saved to a simple file database.
      ' Listening to messages requires a numeric password to be entered.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class Voicemail
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
      
              ' Create the menu action
              Dim menuPrompt As Play = Play.SayText("Press 1 to leave a message. " +
                                                    "Press 2 to listen to all messages.")
      
              Dim menuOptions As List(Of MenuOption) = New List(Of MenuOption) From {
                  New MenuOption("1", New WebPageRequest("RecordMessage.aspx")),
                  New MenuOption("2", New WebPageRequest("GetPasswordNumber.aspx"))
              }
              Dim runMenuAction As RunMenu = New RunMenu(menuOptions, menuPrompt)
              actions.Add(runMenuAction)
      
              ' And add a final message
              actions.Add(Play.SayText("Goodbye."))
      
              ' Set the first message to play if there Is one
              Dim messageId As String = "-1"
              Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
              Dim ids = db.GetIds()
              If (ids.Count > 0) Then
                  messageId = ids(0).ToString()
              End If
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, messageId)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This prompts the caller for a password number.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class GetPasswordNumber
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
      
              Dim prompt As Play = Play.SayText("Please enter your password number followed by the hash key.")
              Dim getNumberAction As GetNumber = New GetNumber(New WebPageRequest("CheckPasswordNumber.aspx"), prompt)
              getNumberAction.EndDigit = "#"
              getNumberAction.NextPage = New WebPageRequest("CheckPasswordNumber.aspx")
              actions.Add(getNumberAction)
      
              actions.Add(Play.SayText("Goodbye."))
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This checks the password that has been entered.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class CheckPasswordNumber
          Inherits System.Web.UI.Page
      
          Shared myPassword As String = "1234"
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
      
              Dim token As String = ourRequest.InstanceInfo.Token
              Dim result As GetNumberResult = ourRequest.InstanceInfo.ActionResult
      
              ' Set up the actions, depending on the entered password
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
              If result.EnteredNumber.CompareTo(myPassword) = 0 Then
                  actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
              Else
                  actions.Add(Play.SayText("Sorry, that password is not correct. Goodbye."))
              End If
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This plays the message then prompts the caller for a further option.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class PlayMessage
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
              Dim messageId As Integer = Convert.ToInt32(token)
      
              Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
              Dim filename As String = db.GetMessageFilename(messageId)
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
              If filename IsNot Nothing Then
                  actions.Add(Play.PlayFile(filename))
      
                  Dim menuOptions As List(Of MenuOption) = New List(Of MenuOption)
                  menuOptions.Add(New MenuOption("1", New WebPageRequest("MessageReplay.aspx")))
                  menuOptions.Add(New MenuOption("2", New WebPageRequest("MessageDelete.aspx")))
                  menuOptions.Add(New MenuOption("3", New WebPageRequest("MessageKeep.aspx")))
                  Dim prompt As Play = Play.SayText("Press 1 to hear the message again. " +
                                                    "Press 2 to delete it, " +
                                                    "or press 3 to save it.")
                  actions.Add(New RunMenu(menuOptions, prompt))
                  actions.Add(Play.SayText("Goodbye."))
              Else
                  actions.Add(Play.SayText("End of messages. Goodbye."))
                  token = ""
              End If
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This replays the selected message.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class MessageReplay
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
              actions.Add(Play.SayText("Playing the message again."))
              actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Simple Play With Interrupt sample:
      ' This acknowledges the interrupt to play by saying some text
      ' before the call is hung up.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class MessageDelete
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              ' The token should be the index of the message file to delete
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
      
              Dim token As String = ourRequest.InstanceInfo.Token
              Dim messageId As Integer = -1
              messageId = Convert.ToInt32(token)
      
              Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
              Dim filename As String = db.GetMessageFilename(messageId)
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
      
              Dim nextMessageId As Integer = -1
              If filename IsNot Nothing Then
                  ' Delete action
                  actions.Add(New DeleteFile(filename))
                  Dim msg As Play = Play.SayText("Message deleted.")
      
                  ' Get the next message ID
                  Dim ids As List(Of Integer) = db.GetIds()
                  For index As Integer = 0 To (ids.Count - 2)
                      If ids(index) = messageId Then
                          nextMessageId = ids(index + 1)
                          msg.AddText("Next message.")
                          actions.Add(msg)
                          actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
                          Exit For
                      End If
                  Next
      
                  If nextMessageId = -1 Then
                      msg.AddText("End of messages. Goodbye.")
                      actions.Add(msg)
                  End If
      
                  ' Remove the entry from the DB
                  db.DeleteMessageFilename(messageId)
              End If
      
              ' Respond
              token = nextMessageId.ToString()
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This saves the selected message.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class MessageKeep
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              ' The token should be the id of the message file to keep
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
              Dim messageId As Integer = Convert.ToInt32(token)
      
              Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
              Dim filename As String = db.GetMessageFilename(messageId)
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
              Dim nextMessageId As Integer = -1
              If filename IsNot Nothing Then
                  actions.Add(Play.SayText("Message saved."))
      
                  ' Get the next message ID
                  Dim ids As List(Of Integer) = db.GetIds()
                  For index As Integer = 0 To (ids.Count - 2)
                      If ids(index) = messageId Then
                          nextMessageId = ids(index + 1)
                          Dim msg As Play = Play.SayText("Next message.")
                          actions.Add(msg)
                          actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
                          Exit For
                      End If
                  Next
      
                  If nextMessageId = -1 Then
                      actions.Add(Play.SayText("End of messages. Goodbye."))
                  End If
              End If
      
              ' Respond
              token = nextMessageId.ToString()
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This prompts the caller to leave a message and starts a record action.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class RecordMessage
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction) From
              {
                  Play.SayText("Please leave a message after the beep. Press hash to end the " +
                               "recording or press star to cancel.")
              }
      
              Dim recordAction As Record = New Record(New WebPageRequest("RecordComplete.aspx")) With {
                  .BeepOnStart = True,
                  .BargeInDigits = "#*",
                  .MillisecondsMaxSilence = 5000
              }
              actions.Add(recordAction)
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A page from the Voicemail sample:
      ' This is called when recording completes. It plays one of two messages to
      ' the caller depending on whether the recording contains significant sound.
      Imports System.Collections.Generic
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class RecordComplete
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim token As String = ourRequest.InstanceInfo.Token
              Dim result As RecordResult = ourRequest.InstanceInfo.ActionResult
      
              ' Setup the actions
              Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
      
              Dim helpDigit As Char = "*"
              If result.Reason.Equals("bargein") And result.BargeInDigit.Equals(helpDigit) Then
                  actions.Add(Play.SayText("Message recording cancelled. Goodbye."))
                  actions.Add(New DeleteFile(result.Filename))
              ElseIf result.ContainsSound Then
                  ' Store the filename in our message file
                  Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
                  Dim newMessageId As Integer = db.AppendMessageFilename(result.Filename)
                  actions.Add(Play.SayText("Thanks for leaving a message. Goodbye."))
              Else
                  actions.Add(Play.SayText("There was no message recorded. Goodbye."))
                  actions.Add(New DeleteFile(result.Filename))
              End If
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • Imports System.IO
      Imports System.Collections.Generic
      
      ' File DB of voicemail message filenames
      '
      ' Each row:  int Id, string Filename
      '
      Public Class MessageFilenameDatabase
      
          Private nextId As Integer = 1
      
          Public Sub New()
              dbFilename = Path.GetTempPath() + "VBVoicemailMessages.tmp"
      
              ' Initialise the id counter to the next highest int
              Dim rows As Dictionary(Of Integer, String) = GetRows()
              If rows.Count > 0 Then
                  nextId = (New List(Of Integer)(rows.Keys)).Max() + 1
              End If
          End Sub
      
          Public Function Size() As Integer
              If Not File.Exists(dbFilename) Then
                  Return 0
              End If
      
              Dim lines As Array = File.ReadAllLines(dbFilename)
              Return lines.Length
          End Function
      
          Public Function GetIds() As List(Of Integer)
              If Not File.Exists(dbFilename) Then
                  Return New List(Of Integer)
              End If
      
              Dim rows As Dictionary(Of Integer, String) = GetRows()
              Return New List(of integer)(rows.Keys)
          End Function
      
          Public Function GetMessageFilename(id As Integer) As String
              If Not File.Exists(dbFilename) Then
                  Return Nothing
              End If
      
              Dim rows As Dictionary(Of Integer, String) = GetRows()
              Try
                  Return rows(id)
              Catch ex As KeyNotFoundException
                  Return Nothing
              End Try
          End Function
      
          Public Function AppendMessageFilename(filename As String) As Integer
              Dim rows As Dictionary(Of Integer, String)
              If File.Exists(dbFilename) Then
                  rows = GetRows()
              Else
                  rows = New Dictionary(Of Integer, String)
              End If
      
              Dim newId As Integer = nextId
              nextId += 1
              rows.Add(newId, filename)
              SaveDatabaseFile(rows)
              Return nextId
          End Function
      
          Public Sub DeleteMessageFilename(id As Integer)
              If Not File.Exists(dbFilename) Then
                  Return
              End If
      
              Dim rows As Dictionary(Of Integer, String) = GetRows()
              Try
                  rows.Remove(id)
              Catch ex As KeyNotFoundException
                  Return
              End Try
      
              SaveDatabaseFile(rows)
          End Sub
      
          Private Sub SaveDatabaseFile(rows As Dictionary(Of Integer, String))
              Dim lines As List(Of String) = New List(Of String)(rows.Count)
              For Each entry As KeyValuePair(Of Integer, String) In rows
                  lines.Add(String.Format("{0},{1}", entry.Key, entry.Value))
              Next
              File.WriteAllLines(dbFilename, lines)
          End Sub
      
          Public Function GetRows() As Dictionary(Of Integer, String)
              Dim rows As Dictionary(Of Integer, String) = New Dictionary(Of Integer, String)
      
              If File.Exists(dbFilename) Then
                  Dim messageLines As String() = File.ReadAllLines(dbFilename)
                  For Each line As String In messageLines
                      Dim splits As String() = line.Split(",")
                      Dim id As Integer = Int32.Parse(splits(0))
                      Dim filename As String = splits(1).Trim()
                      rows.Add(id, filename)
                  Next
              End If
              Return rows
          End Function
      
          Private dbFilename As String
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A generic error page for all the samples.
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class ErrorPage
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
              Dim result As ErrorResult = ourRequest.InstanceInfo.ErrorResult
      
              Dim token As String = String.Format("Action: {0}\nActionIndex: {1}\nResult: {2}", _
                  result.Action, result.ActionIndex, result.Result)
      
              ' Respond
              Dim ourResponse As TelephonyResponse = New TelephonyResponse(token)
              ourResponse.ToHttpResponse(Response)
          End Sub
      End Class
      
      
    • ' Visual Basic Wrapper sample for the Aculab Telephony REST API.
      '
      ' A generic final page for all the samples:
      Imports Aculab.Cloud.RestAPIWrapper
      
      Partial Class FinalPage
          Inherits System.Web.UI.Page
      
          Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
      
              ' Unpack the request
              Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
      
              ' Do application tidying up
              ' ...
          End Sub
      End Class
      
      
  • Implemented as Java Servlets:

    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      // Voicemail:
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class Voicemail extends HttpServlet
      {
          private static final long serialVersionUID = -216367273425731462L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
      
              // Create the menu action
              Play menuPrompt = Play.sayText("Press 1 to leave a message. " + 
                                             "Press 2 to listen to all messages.");
              List<MenuOption> menuOptions = new ArrayList<MenuOption>();
              menuOptions.add(new MenuOption('1', new WebPageRequest("RecordMessage")));
              menuOptions.add(new MenuOption('2', new WebPageRequest("GetPasswordNumber")));
              RunMenu runMenuAction = new RunMenu(menuPrompt, menuOptions);
              actions.add(runMenuAction);
      
              // And add a final message
              actions.add(Play.sayText("Goodbye."));
      
              //Get the first message id in the filename database
              MessageFilenameDatabase db = new MessageFilenameDatabase();
              String token = Integer.toString(db.getFirstMessageId());
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class GetPasswordNumber extends HttpServlet
      {
          private static final long serialVersionUID = -7217763794925626580L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
              
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
      
              Play prompt = Play.sayText("Please enter your password number followed by the hash key.");
              GetNumber getNumberAction = new GetNumber(new WebPageRequest("CheckPasswordNumber"));
              getNumberAction.setPrompt(prompt);
              getNumberAction.setEndDigit('#');
              actions.add(getNumberAction);
      
              actions.add(Play.sayText("Goodbye."));
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class CheckPasswordNumber extends HttpServlet
      {
          private static final long serialVersionUID = 2185118085479932134L;
      
          private static String myPassword = "1234";
          
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
              GetNumberResult getNumberResult = (GetNumberResult)ourRequest.getInstanceInfo().getActionResult();
      
              // Set up the actions, depending on the entered password
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              if (getNumberResult.getEnteredNumber().compareTo(myPassword) == 0)
              {
                  actions.add(new Redirect(new WebPageRequest("PlayMessage")));
              }
              else
              {
                  actions.add(Play.sayText("Sorry, that password is not correct. Goodbye."));
              }
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class PlayMessage extends HttpServlet
      {
          private static final long serialVersionUID = 6018322048224034139L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
      
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
      
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              // The token should be the index of the next message file to play
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              MessageFilenameDatabase db = new MessageFilenameDatabase();
              String token = ourRequest.getInstanceInfo().getToken();
      
              int messageId = Integer.parseInt(token);
      
              String filename = db.getMessageFilename(messageId);
              if (filename != null)
              {
                  actions.add(Play.playFile(filename));
      
                  List<MenuOption> menuOptions = new ArrayList<MenuOption>();
                  menuOptions.add(new MenuOption('1', new WebPageRequest("MessageReplay")));
                  menuOptions.add(new MenuOption('2', new WebPageRequest("MessageDelete")));
                  menuOptions.add(new MenuOption('3', new WebPageRequest("MessageKeep")));
                  actions.add(new RunMenu(Play.sayText("Press 1 to hear the message again. " +
                                                       "Press 2 to delete it, " +
                                                       "or press 3 to save it."),
                                                       menuOptions));
                  actions.add(Play.sayText("Goodbye."));
      
                  token = Integer.toString(messageId);
              }
              else
              {
                  actions.add(Play.sayText("End of messages. Goodbye."));
                  token = "";
              }
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class MessageReplay extends HttpServlet
      {
          private static final long serialVersionUID = -6227827216303408130L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
      
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              actions.add(Play.sayText("Playing the message again."));
              actions.add(new Redirect(new WebPageRequest("PlayMessage")));
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class MessageDelete extends HttpServlet
      {
          private static final long serialVersionUID = 5011613038036857392L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              // The token should be the index of the message file to delete
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
              int messageId = Integer.parseInt(token);
              MessageFilenameDatabase db = new MessageFilenameDatabase();
              String filename = db.getMessageFilename(messageId);
      
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              int nextMessageId = -1;
              if (filename != null)
              {
                  actions.add(new DeleteFile(filename));
                  Play msg = Play.sayText("Message deleted.");
                  
                  nextMessageId = db.getNextMessageId(messageId);
                  
                  if (nextMessageId != -1)
                  {
                      msg.addText("Next message.");
                      actions.add(msg);
                      actions.add(new Redirect(new WebPageRequest("PlayMessage")));
                  }
                  else
                  {
                      msg.addText("End of messages. Goodbye.");
                      actions.add(msg);
                  }
                  db.deleteMessageFilename(messageId);
              }
              
              // Respond
              token = Integer.toString(nextMessageId);
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class MessageKeep extends HttpServlet
      {
          private static final long serialVersionUID = 4847733899330443860L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              // The token should be the index of the message file to keep
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
              int messageId = Integer.parseInt(token);
              MessageFilenameDatabase db = new MessageFilenameDatabase();
              String filename = db.getMessageFilename(messageId);
              
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              int nextMessageId = -1;
              if (filename != null)
              {
                  actions.add(Play.sayText("Message saved."));
                  
                  nextMessageId = db.getNextMessageId(messageId);
                  
                  if (nextMessageId != -1)
                  {
                      actions.add(Play.sayText("Next message."));
                      actions.add(new Redirect(new WebPageRequest("PlayMessage")));
                  }
                  else
                  {
                      actions.add(Play.sayText("End of messages. Goodbye."));
                  }
              }
              
              // Respond
              token = Integer.toString(nextMessageId);
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class RecordMessage extends HttpServlet
      {
          private static final long serialVersionUID = -3436973162929428486L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
      
              // Setup the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
      
              actions.add(Play.sayText("Please leave a message after the beep. Press hash to end the recording or press star to cancel."));
      
              Record recordAction = new Record(new WebPageRequest("RecordComplete"));
              recordAction.setBeepOnStart(true);
              recordAction.setBargeInDigits("#*");
              recordAction.setMillisecondsMaxSilence(5000);
              actions.add(recordAction);
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class RecordComplete extends HttpServlet
      {
          private static final long serialVersionUID = 3418571655744931314L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              String token = ourRequest.getInstanceInfo().getToken();
              RecordResult result = (RecordResult)ourRequest.getInstanceInfo().getActionResult();
              
              // Set up the actions
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
      
              if ( result.getReason().equals("bargein") && result.getBargeInDigit().equals("*"))
              {
                  actions.add(Play.sayText("Message recording cancelled. Goodbye."));
                  actions.add(new DeleteFile(result.getFilename()));
              }
              else if (result.containsSound())
              {
                  // Store the filename in our message file
                  String filename = result.getFilename();
      
                  MessageFilenameDatabase db = new MessageFilenameDatabase();
                  db.appendMessageFilename(filename);
      
                  actions.add(Play.sayText("Thanks for leaving a message. Goodbye."));
              }
              else
              {
                  actions.add(Play.sayText("There was no message recorded. Goodbye."));
                  actions.add(new DeleteFile(result.getFilename()));
              }
      
              // Respond
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • package com.aculab.telephonyrestapi.samples;
      
      import java.io.BufferedWriter;
      import java.io.File;
      import java.io.FileWriter;
      import java.io.IOException;
      import java.nio.charset.Charset;
      import java.nio.file.Files;
      import java.util.Iterator;
      import java.util.LinkedHashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.Map.Entry;
      
      
      public class MessageFilenameDatabase
      {
          public MessageFilenameDatabase() throws IOException
          {
              File temp = File.createTempFile("temp-file", ".tmp");
              String absolutePath = temp.getAbsolutePath();
              String tempFilePath = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator) + 1);
              temp.delete();
      
              dbFile = new File(tempFilePath + "JavaVoicemailMessages.tmp");
              if (dbFile.exists())
              {
                  LinkedHashMap<Integer, String> rows = getRows();
      
                  for (Entry<Integer, String> row : rows.entrySet())
                  {
                      int id = row.getKey();
                      if (id >= nextId)
                      {
                          nextId = id + 1;
                      }
                  }
              }
          }
      
          public Integer getFirstMessageId() throws IOException
          {
              LinkedHashMap<Integer, String> rows = getRows();
              
              Iterator<Entry<Integer, String>> it = rows.entrySet().iterator();
              
              if(it.hasNext())
              {
                  Map.Entry<Integer, String> row = (Map.Entry<Integer, String>)it.next();
                  return row.getKey();
              }
      
              return -1;
          }
          
          public Integer getNextMessageId(Integer id) throws IOException
          {
              LinkedHashMap<Integer, String> rows = getRows();
      
              Iterator<Entry<Integer, String>> it = rows.entrySet().iterator();
      
              while(it.hasNext())
              {
                  Map.Entry<Integer, String> row;
      
                  row = (Map.Entry<Integer, String>)it.next();
                  if (row.getKey() == id)
                  {
                      if (it.hasNext())
                      {
                          row = (Map.Entry<Integer, String>)it.next();
                          return row.getKey();
                      }
                  }
              }
      
              return -1;
          }
      
          public String getMessageFilename(int id) throws IOException
          {
              LinkedHashMap<Integer, String> rows = getRows();
              
              for (Entry<Integer, String> row : rows.entrySet())
              {
                  if (id == row.getKey())
                  {
                      return row.getValue();
                  }
              }
              
              return null;
          }
          
          public void appendMessageFilename(String filename) throws IOException
          {    	
              LinkedHashMap<Integer, String> rows = getRows();
              
              rows.put(nextId, filename);
              nextId++;
              saveDatabaseFile(rows);
          }
      
          public void deleteMessageFilename(int id) throws IOException
          {
              LinkedHashMap<Integer, String> rows = getRows();
              
              if (rows.remove(id) != null)
              {
                  saveDatabaseFile(rows);
              }
          }
         
          private void saveDatabaseFile(LinkedHashMap<Integer, String> rows) throws IOException
          {
              BufferedWriter writer = new BufferedWriter(new FileWriter(dbFile, false));
              
              for (Entry<Integer, String> row : rows.entrySet())
              {
                  writer.write(row.getKey() + "," + row.getValue());
                  writer.newLine();
              }
              writer.close();
          }
          
          public LinkedHashMap<Integer, String> getRows() throws IOException
          {
              LinkedHashMap<Integer, String> rows = new LinkedHashMap<Integer, String>();
      
              if (dbFile.exists())
              {
                  List<String> messageLines;
      
                  messageLines = Files.readAllLines(dbFile.toPath(), Charset.defaultCharset());
      
                  for(String line : messageLines)
                  {
                      String[] splits = line.split(",");
                      int id = Integer.parseInt(splits[0]);
                      String filename = splits[1].trim();
                      rows.put(id, filename);
                  }
              }
              return rows;
          }
      
          private int nextId = 1;
          private File dbFile;
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.aculab.telephonyrestapi.*;
      
      public class ErrorPage extends HttpServlet
      {
          private static final long serialVersionUID = -4842873371047361437L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
      
              ErrorResult result = ourRequest.getInstanceInfo().getErrorResult();
      
              String token = String.format("Action: %s\nActionIndex: %d\nResult: %s", result.getAction(), result.getActionIndex(), result.getResult());
              
              // Respond
              List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
              TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
              ourResponse.setHttpServletResponse(response);
          }
      }
      
      
    • // Java Servlet sample for the Aculab Telephony REST API.
      //
      
      package com.aculab.telephonyrestapi.samples;
      
      import javax.servlet.http.*;
      import javax.servlet.ServletException;
      import java.io.IOException;
      import com.aculab.telephonyrestapi.*;
      
      public class FinalPage extends HttpServlet
      {
          private static final long serialVersionUID = 5940620014313056844L;
      
          @Override
          public void doGet(HttpServletRequest request,
                            HttpServletResponse response)
              throws IOException, ServletException
          {
             	handleRequest(request, response);
          }
          
          @Override
          public void doPost(HttpServletRequest request,
                  HttpServletResponse response)
                          throws IOException, ServletException
          {
          	handleRequest(request, response);
          }
          
          private void handleRequest(HttpServletRequest request,
                                     HttpServletResponse response) throws IOException
          {
              // Unpack the request
              TelephonyRequest ourRequest = new TelephonyRequest(request);
          }
      }
      
      
  • Implemented as a Flask web application:

    • @app.route('/Voicemail', methods=['GET','POST'])
      def handle_Voicemail():
      
          # Here we begin to create our action list in response to the query
          my_request = TelephonyRequest(request)
          app_inst_id = my_request.get_application_instance_id()
          print("Voicemail: app_inst_id='{}'".format(app_inst_id))
      
          db = MessageFilenameDatabase()
      
          # Set a next_page for each of the options
          menu_options = []
          menu_options.append(MenuOption('1', WebPage(url='RecordMessage')))
          menu_options.append(MenuOption('2', WebPage(url='GetPasswordNumber')))
      
          # Create the menu action
          my_menu = RunMenu(menu_options)
          my_menu.set_prompt(Play(text_to_say= ('Press 1 to leave a message. Press 2 to listen to all messages.')))
      
          list_of_actions = []
      
          # Append the menu action to the action list.
          list_of_actions.append(my_menu)
          list_of_actions.append(Play(text_to_say="Goodbye."))
      
          # Get the first message id in the filename database
          db = MessageFilenameDatabase()
          msg_id = db.getFirstMessageId()
      
          my_response = TelephonyResponse(list_of_actions, str(msg_id))
          return my_response.get_json()
      
      
    • @app.route('/GetPasswordNumber', methods=['GET','POST'])
      def handle_GetPasswordNumber():
      
          my_request = TelephonyRequest(request)
          my_token = my_request.get_token()
      
          # Option 2 is to listen to all the recorded messages. 
          # First we need to check that the caller is authorised to do this.
          # We configure an IVR to ask for a PIN, we use GetNumber to do this.
      
          my_number = GetNumber(WebPage(url='CheckPasswordNumber'))
          my_number.set_end_digit('#')
          # As with RunMenu, we provide an initial prompt.
          my_number.set_prompt(Play(text_to_say='Please enter your password number followed by the hash key.'))
      
          list_of_actions = []
          list_of_actions.append(my_number)
          list_of_actions.append(Play(text_to_say="Goodbye."))
      
          my_response = TelephonyResponse(list_of_actions, my_token)
          return my_response.get_json()
      
      
    • @app.route('/CheckPasswordNumber', methods=['GET','POST'])
      def handle_CheckPasswordNumber():
      
          my_request = TelephonyRequest(request)
          action_result = my_request.get_action_result()
          my_token = my_request.get_token()
      
          id_digits = ""
          if(action_result.get('action') == 'get_number'):
              id_digits = action_result.get('result').get('entered_number')
      
          list_of_actions = []
      
          # For our purposes the PIN is hard-coded to 1234
          if id_digits == '1234':
              # Redirect to the PlayMessage page, where the first message will be played.
              list_of_actions.append(Redirect(next_page=WebPage(url='PlayMessage')))
          else:
              # The PIN is not correct, say sorry and hang up. The application will
              # automatically hang up after this action since there is no redirection
              # to a next page.
              list_of_actions.append(Play(text_to_say='Sorry, that password is not correct. Goodbye.'))
      
          my_response = TelephonyResponse(list_of_actions, my_token)
          return my_response.get_json()
      
      
    • @app.route('/PlayMessage', methods=['GET','POST'])
      def handle_PlayMessage():
      
          my_request = TelephonyRequest(request)
          msg_id = int(my_request.get_token())
      
          db = MessageFilenameDatabase()
          filename = db.getMessageFilename(msg_id)
      
          list_of_actions = []
      
          if filename != "":
              list_of_actions.append(Play(file_to_play=filename))
      
              # Here we set a next_page for each of the three options
              menu_options = []
              menu_options.append(MenuOption('1', WebPage(url='MessageReplay')))
              menu_options.append(MenuOption('2', WebPage(url='MessageDelete')))
              menu_options.append(MenuOption('3', WebPage(url='MessageKeep')))
      
              my_menu = RunMenu(menu_options)
              my_menu.set_prompt(Play(text_to_say= ('Press 1 to hear the message again. '
                                                        'Press 2 to delete it, '
                                                        'or press 3 to save it.')))
      
              list_of_actions.append(my_menu)
      
              list_of_actions.append(Play(text_to_say="Goodbye."))
      
          else:
              list_of_actions.append(Play(text_to_say='End of messages. Goodbye.'))
      
          my_response = TelephonyResponse(list_of_actions, token=str(msg_id)) 
          return my_response.get_json()
      
      
    • @app.route('/MessageReplay', methods=['GET','POST'])
      def handle_MessageReplay():
      
          my_request = TelephonyRequest(request)
      
          my_token = my_request.get_token()
      
          list_of_actions = []
      
          list_of_actions.append(Play(text_to_say='Playing the message again.'))
          list_of_actions.append(Redirect(next_page=WebPage(url='PlayMessage')))
      
          my_response = TelephonyResponse(list_of_actions, my_token)
          return my_response.get_json()
      
      
    • @app.route('/MessageDelete', methods=['GET','POST'])
      def handle_MessageDelete():
      
          my_request = TelephonyRequest(request)
          msg_id = int(my_request.get_token())
      
          db = MessageFilenameDatabase()
          msg_filename =  db.getMessageFilename(msg_id)
          next_msg_id = db.getNextMessageId(msg_id)
          db.deleteMessage(msg_id)
      
          list_of_actions = []
      
          list_of_actions.append(DeleteFile(msg_filename))
      
          play_action = Play(text_to_say='Message deleted.')
      
          if next_msg_id != -1:
              play_action.append_text('Next message.')
              list_of_actions.append(play_action)
              list_of_actions.append(Redirect(next_page=WebPage(url='PlayMessage')))
          else:
              play_action.append_text('End of messages. Goodbye.')
              list_of_actions.append(play_action)
      
          my_response = TelephonyResponse(list_of_actions, token=str(next_msg_id)) 
          return my_response.get_json()
      
    • @app.route('/MessageKeep', methods=['GET','POST'])
      def handle_MessageKeep():
      
          my_request = TelephonyRequest(request)
          msg_id = int(my_request.get_token())
      
          db = MessageFilenameDatabase()
          next_msg_id = db.getNextMessageId(msg_id)
      
          list_of_actions = []
      
          list_of_actions.append(Play(text_to_say='Message saved.'))
          if next_msg_id != -1:
              list_of_actions.append(Play(text_to_say='Next message.'))
              list_of_actions.append(Redirect(next_page=WebPage(url='PlayMessage')))
          else:
              list_of_actions.append(Play(text_to_say='End of messages. Goodbye.'))
      
          my_response = TelephonyResponse(list_of_actions, token=str(next_msg_id)) 
          return my_response.get_json()
      
      
    • @app.route('/RecordMessage', methods=['GET','POST'])
      def handle_RecordMessage():
      
          my_request = TelephonyRequest(request)
          my_token = my_request.get_token()
      
          list_of_actions = []
          
          # Option 1 is to leave a message. We create two actions, the first is to use TTS to
          # ask the caller to begin the message after a beep, and to press # to end the recording.
          list_of_actions.append(Play(text_to_say='Please leave a message after the beep. Press hash to end the recording or press star to cancel.'))
      
          # The next action it to start recording. When the recording has completed, the application
          # will be directed to the my_recorded_file_page.
          list_of_actions.append(Record(barge_in_digits="#*",             # pressing # will stop the recording
                                milliseconds_max_silence=5000,            # five seconds of silence will stop the recording
                                next_page=WebPage(url='RecordComplete'),  # when recording completes, go to this page
                                beep_on_start=True))                      # before recording begins, play a beep
      
          my_response = TelephonyResponse(list_of_actions, my_token)
          return my_response.get_json()
      
      
    • @app.route('/RecordComplete', methods=['GET','POST'])
      def handle_RecordComplete():
      
          my_request = TelephonyRequest(request)
          my_token = my_request.get_token()
          action_result = my_request.get_action_result()
          record_result = action_result.get('result')
      
          list_of_actions = []
      
          if (record_result.get("reason") == "bargein") and (record_result.get("barge_in_digit") == "*"):
      
              list_of_actions.append(Play(text_to_say='Message recording cancelled. Goodbye.'))
              list_of_actions.append(DeleteFile(record_result.get("filename")))
      
          elif record_result.get("contains_sound"):
      
              filename = record_result.get("filename")
              print ("Recorded file is {0}".format(filename))
      
              # Store the filename in our messages file
              db = MessageFilenameDatabase()
              db.appendMessageFilename(filename)
      
              list_of_actions.append(Play(text_to_say='Thanks for leaving a message. Goodbye.'))
      
          else:
      
              list_of_actions.append(Play(text_to_say='There was no message recorded. Goodbye.'))
              list_of_actions.append(DeleteFile(record_result.get("filename")))
      
          my_response = TelephonyResponse(list_of_actions, my_token)
          return my_response.get_json()
      
      
    • class MessageFilenameDatabase:
      
          # Class to store message entries that are read from the database file.
          class Row:
              def __init__(self, id, filename):
                  self.id = id
                  self.filename = filename
      
          # Create the database file if it does not already exist
          def __init__(self):
              self.db_filename = tempfile.gettempdir() + '/' + "PythonVoicemailMessages.tmp"
              fh = open(self.db_filename, "a")
              fh.close()
      
          # Read the database file, parse each line into
          # a list of 'Row' classes
          def getRows(self):
              fh = open(self.db_filename, "r")
              rows = []
              for x in fh:
                  id_and_filename = x.split(",")
                  id = int(id_and_filename[0])
                  filename = id_and_filename[1].strip()
                  rows.append(self.Row(id,filename))
              fh.close()
              return rows
      
          # Return the id of the first (top most) message that
          # is stored in the database file.
          # Returns -1 if the first message id could not be found.
          def getFirstMessageId(self):
              rows = self.getRows()
              if len(rows) > 0:
                  return rows[0].id
              return -1
      
          # Return the id of the message that is stored below this_id in 
          # the database file.
          # Returns -1 if the next message id could not be found.
          def getNextMessageId(self, this_id):
              rows = self.getRows()
              return_next_id = False
              for row in rows:
                  if return_next_id == True:
                      return row.id
                  elif row.id == this_id:
                      return_next_id = True
              return -1
      
          # Return a message filename given its id.
          def getMessageFilename(self, id):
              rows = self.getRows()
              for row in rows:
                  if row.id == id:
                      return row.filename
              return ""
      
          # Add another message entry to the database file
          def appendMessageFilename(self, filename):
              new_id = 1
              rows = self.getRows()
              
              for row in rows:
                  if new_id <= row.id:
                      new_id = row.id + 1
              
              fh = open(self.db_filename, "a")
              fh.write("{0},{1}\n".format(new_id, filename))
              fh.close()
      
          # Delete a message from the database file given its id.
          def deleteMessage(self, id):
              rows = self.getRows()
              new_rows = []
      
              # Clear the file contents. Re-write the entries but
              # miss out the one we want to delete.
              fh = open(self.db_filename, "w")
              for row in rows:
                  if id != row.id:
                      fh.write("{0},{1}\n".format(row.id, row.filename))
              fh.close()
      
    • @app.route('/ErrorPage', methods=['GET','POST'])
      def handle_ErrorPage():
          
          my_request = TelephonyRequest(request)
          token = my_request.get_token()
          app_inst_id = my_request.get_application_instance_id()
          error_result_dict = my_request.get_error_result()
          action_string = error_result_dict.get('action', "?")
          result_string = error_result_dict.get('result', "?")
          print("ErrorPage: app_inst_id='{}' token='{}' action='{}' result='{}'".format(app_inst_id, token, action_string, result_string))
          
          my_response = TelephonyResponse([Play(text_to_say='An error has occurred')])
          return my_response.get_json()
      
      
    • @app.route('/FinalPage', methods=['GET','POST'])
      def handle_FinalPage():
          # The FinalPage handler follows the guidelines on:
          # https://www.aculab.com/cloud/voice-and-fax-apis/rest-api/rest-api-version-2/rest-api-version-2/writing-a-rest-application
          # The guidelines are:
          #   "Your final page should return an empty response, a 204 is preferable, but empty JSON is acceptable."
          my_request = TelephonyRequest(request)
          token = my_request.get_token()
          app_inst_id = my_request.get_application_instance_id()
          print("FinalPage: app_inst_id='{}' token='{}'".format(app_inst_id, token))
          empty_json = '{}'.encode('utf-8')
          return empty_json
          
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      require __DIR__ . "/MessageFilenameDatabase.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\RunMenu;
      
      $resp = new Response();
      $resp->setToken( (string)getFirstMessageId() );
      
      // Create the menu action
      $menuPrompt = Play::sayText("Press 1 to leave a message. Press 2 to listen to all messages.");
      $menu = new RunMenu();
      $menu->setPrompt($menuPrompt);
      $menu->addMenuOption('1', 'RecordMessage.php');
      $menu->addMenuOption('2', 'GetPasswordNumber.php');
      
      $resp->addAction($menu);
      
      $resp->addAction(Play::sayText('Goodbye.'));
      
      print $resp;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\GetNumber;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      // Create the get number action
      $prompt = Play::sayText("Please enter your password number followed by the hash key.");
      $getNumberAction = new GetNumber("CheckPasswordNumber.php");
      $getNumberAction->setPrompt($prompt);
      $getNumberAction->setEndDigit('#');
      
      $response->addAction($getNumberAction);
      
      
      $response->addAction(Play::sayText('Goodbye.'));
      
      print $response;
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\Redirect;
      
      $info = InstanceInfo::getInstanceInfo();
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      $enteredNumber = '';
      // Get the result of the run_menu action
      $result = $info->getActionResult();
      if ($result != null && is_a($result, '\Aculab\TelephonyRestAPI\GetNumberResult')) {
          $enteredNumber = $result->getEnteredNumber();
      }
      
      if ($enteredNumber == '1234') {
          $response->addAction(new Redirect('PlayMessage.php'));
      } else {
          $response->addAction(Play::sayText('Sorry, that password is not correct. Goodbye.'));
      }
      
      print $response;
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      require __DIR__ . "/MessageFilenameDatabase.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\RunMenu;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      $midstr = $info->getToken();
      $mid = (int)$midstr;
      $fname = getMessageFilename($mid);
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      if (is_null($fname)) {
          $response->addAction(Play::sayText('End of messages. Goodbye.'));
      } else {
          $response->addAction(Play::playFile($fname));
          
          // Create the menu action
          $menuPrompt = Play::sayText("Press 1 to hear the message again. Press 2 to delete it, or press 3 to save it.");
          $menu = new RunMenu();
          $menu->setPrompt($menuPrompt);
          $menu->addMenuOption('1', 'MessageReplay.php');
          $menu->addMenuOption('2', 'MessageDelete.php');
          $menu->addMenuOption('3', 'MessageKeep.php');
      
          $response->addAction($menu);
      
          $response->addAction(Play::sayText('Goodbye.'));
      }
      
      print $response;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\Redirect;
      
      $info = InstanceInfo::getInstanceInfo();
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      $response->addAction(Play::sayText('Playing the message again.'));
      $response->addAction(new Redirect('PlayMessage.php'));
      
      print $response;
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      require __DIR__ . "/MessageFilenameDatabase.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\DeleteFile;
      use \Aculab\TelephonyRestAPI\Redirect;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      $midstr = $info->getToken();
      $mid = (int)$midstr;
      $next = getNextMessageId($mid);
      
      $response = new Response();
      
      $response->addAction(Play::sayText('Message saved.'));
      
      if ($next != -1) {
          $response->addAction(Play::sayText('Next message.'));
          $response->addAction(new Redirect('PlayMessage.php'));
      } else {
          $response->addAction(Play::sayText('End of messages. Goodbye.'));
      }
      
      $response->setToken((string)$next);
      
      
      print $response;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      require __DIR__ . "/MessageFilenameDatabase.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\DeleteFile;
      use \Aculab\TelephonyRestAPI\Redirect;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      $midstr = $info->getToken();
      $mid = (int)$midstr;
      
      // get file to delete
      $fname = getMessageFilename($mid);
      // get next before delete, otherwise it can't find the current one
      $next = getNextMessageId($mid);
      deleteMessageId($mid);
      
      $response = new Response();
      if (!is_null($fname)) {
          $response->addAction(new DeleteFile($fname));
      }
      
      $play = Play::sayText('Message deleted.');
      
      if ($next != -1) {
          $play->addText('Next message.');
          $response->addAction($play);
          $response->addAction(new Redirect('PlayMessage.php'));
      } else {
          $play->addText('End of messages. Goodbye.');
          $response->addAction($play);
      }
      
      $response->setToken((string) $next);
      
      print $response;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\Record;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      $response->addAction(Play::sayText("Please leave a message after the beep. Press hash to end the recording or press star to cancel."));
      
      $record = new Record('RecordComplete.php');
      $record->setBeepOnStart(true);
      $record->setBargeInDigits('#*');
      $record->setMillisecondsMaxSilence(5000);
      $response->addAction($record);
      
      print $response;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      require __DIR__ . "/MessageFilenameDatabase.php";
      
      header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
      header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
      header("Content-Type: application/json; charset=UTF-8");
      
      use \Aculab\TelephonyRestAPI\Response;
      use \Aculab\TelephonyRestAPI\DeleteFile;
      use \Aculab\TelephonyRestAPI\Play;
      use \Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      $recordResult = $info->getActionResult();
      $fname = $recordResult->getFilename();
      
      $response = new Response();
      $response->setToken($info->getToken()); // NB not really needed as we are not changing the token
      
      if ($recordResult->getReason() == "bargein" and $recordResult->getBargeInDigit() == "*") {
          $response->addAction(Play::sayText('Message recording cancelled. Goodbye.'));
          $response->addAction(new DeleteFile($fname));
      } else if ($recordResult->getContainsSound()) {
          appendMessageFilename($fname);
          $response->addAction(Play::sayText('Thanks for leaving a message. Goodbye.'));
      } else {
          $response->addAction(Play::sayText('There was no message recorded. Goodbye.'));
          $response->addAction(new DeleteFile($fname));
      }
          
      print $response;
      
      
    • <?php
      function loadMessageDatabase() {
          $message_list_filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "PHPVoicemailMessages.tmp";
          $msgs = [];
          if (file_exists($message_list_filename)) {
              $messagelist = file($message_list_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
              if ($messagelist) {
                  foreach($messagelist as $mline) {
                      list($id, $fname) = explode(',', $mline, 2);
                      $msgs[(int)$id] = $fname;
                  }
              }
          }
          return $msgs;
      }
      
      function saveMessageDatabase($msgs) {
          $messagelist = [];
          foreach($msgs as $id => $fname) {
              $messagelist[] = $id . ',' . $fname;
          }
          $message_list_filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "PHPVoicemailMessages.tmp";
          $f = fopen($message_list_filename, 'w');
          if ($f !== false) {
              fwrite($f, implode("\n", $messagelist));
              fclose($f);
          }
      }
      
      function getFirstMessageId() {
          $msgs = loadMessageDatabase();
          if (count($msgs) > 0) {
              return array_keys($msgs)[0];
          }
          return -1;
      }
      
      function getMessageFilename($msg_id) {
          $msgs = loadMessageDatabase();
          if (isset($msgs[$msg_id])) {
              return $msgs[$msg_id];
          }
          return null;
      }
      
      function getNextMessageId($msg_id) {
          $msgs = loadMessageDatabase();
          $return_next = false;
          foreach($msgs as $id => $fname) {
              if ($return_next) {
                  return $id;
              }
              if ($id == $msg_id) {
                  $return_next = true;
              }
          }
          return -1;
      }
      
      function appendMessageFilename($fname) {
          $msgs = loadMessageDatabase();
          $msgs[] = $fname;
          saveMessageDatabase($msgs);
      }
      
      function deleteMessageId($msg_id) {
          $msgs = loadMessageDatabase();
          if (isset($msgs[$msg_id])) {
              unset($msgs[$msg_id]);
              saveMessageDatabase($msgs);
          }
      }
      
      
    • <?php
      header("Content-Type: application/json; charset=UTF-8");
      
      require __DIR__ . "/../../autoload.php";
      
      use Aculab\TelephonyRestAPI\Play;
      use Aculab\TelephonyRestAPI\Response;
      use Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      
      $error = $info->getErrorResult();
      $action = $error->getAction();
      $desc = $error->getResult();
      if (!is_null($action)) {
          error_log("Error from action \"$action\" with result:" . PHP_EOL . "$desc" . PHP_EOL);
      } else {
          error_log("Error result:" . PHP_EOL . "$desc" . PHP_EOL);
      }
      
      $response = new Response();
      $response->setToken('Error');
      
      $play = new Play();
      $play->addText('An error has occurred.');
      $response->addAction($play);
      
      print $response;
      
      
    • <?php
      require __DIR__ . "/../../autoload.php";
      
      http_response_code(204);
      header("Content-Type: application/json; charset=UTF-8");
      
      use Aculab\TelephonyRestAPI\InstanceInfo;
      
      $info = InstanceInfo::getInstanceInfo();
      $call = $info->getThisCallInfo();
      $callid = $call->getCallId();
      $duration = $call->getSecondsCallDuration();
      error_log("This call id: $callid" . PHP_EOL . "This call duration: $duration" . PHP_EOL);