Skip to content

Voicemail

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.

{
    "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" : "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"
}
{
    "actions" :
    [
        {
            "redirect" :
            {
                "next_page" :
                {
                    "url" : "PlayMessage"
                }
            }
        }
    ],
    "token" : "0"
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Sorry, that password is not correct. Goodbye."
                    }
                ]
            }
        }
    ],
    "token" : "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"
                        }
                    }
                ]
            }
        }
    ],
    "token" : "0"
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "End of messages. Goodbye."
                    }
                ]
            }
        }
    ],
    "token" : ""
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Playing the message again."
                    }
                ]
            }
        },
        {
            "redirect" :
            {
                "next_page" :
                {
                    "url" : "PlayMessage"
                }
            }
        }
    ],
    "token" : "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"
}
{
    "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" : ""
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Message saved."
                    },
                    {
                        "text_to_say" : "Next message."
                    }
                ]
            }
        },
        {
            "redirect" :
            {
                "next_page" :
                {
                    "url" : "PlayMessage"
                }
            }
        }
    ],
    "token" : "1"
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Message saved."
                    }
                ]
            }
        },
        {
            "redirect" :
            {
                "next_page" :
                {
                    "url" : "PlayMessage"
                }
            }
        }
    ],
    "token" : "1"
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Please leave a message after the beep. Press hash to end the recording."
                    }
                ]
            }
        },
        {
            "record" :
            {
                "beep_on_start" : true,
                "milliseconds_max_silence" : 5000,
                "barge_in_digits" : "#",
                "next_page" :
                {
                    "url" : "RecordComplete"
                }
            }
        }
    ],
    "token" : ""
}
{
    "actions" :
    [
        {
            "play" :
            {
                "play_list" :
                [
                    {
                        "text_to_say" : "Thanks for leaving a message. Goodbye."
                    }
                ]
            }
        }
    ],
    "token" : ""
}
{
    [
    ],
    "token" : "Error for Action: xxxx  ActionIndex: xxxx  Result: xxxx"
}
{
}

Implemented as ASP.Net Web Forms:

using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }

        // 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>();
        menuOptions.Add(new MenuOption('1', new WebPageRequest("RecordMessage.aspx")));
        menuOptions.Add(new MenuOption('2', new WebPageRequest("GetPasswordNumber.aspx")));
        RunMenu runMenuAction = new RunMenu(menuPrompt, menuOptions);
        actions.Add(runMenuAction);

        // And add a final message
        actions.Add(Play.SayText("Goodbye."));

        // Respond
        String token = "0"; // Set to first message index
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        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(prompt);
        getNumberAction.EndDigit = '#';
        getNumberAction.NextPage = new WebPageRequest("CheckPasswordNumber.aspx");
        actions.Add(getNumberAction);

        actions.Add(Play.SayText("Goodbye."));

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        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.CompareTo(myPassword) == 0)
        {
            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);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;
        int messageIndex = -1;
        messageIndex = Convert.ToInt32(token);

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.GetMessageFilename(messageIndex);
        if (filename != null)
        {
            actions.Add(Play.PlayFile(filename));

            List<MenuOption> menuOptions = new List<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")));
            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 = messageIndex.ToString();
        }
        else
        {
            actions.Add(Play.SayText("End of messages. Goodbye."));
            token = "";
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();
        actions.Add(Play.SayText("Playing the message again."));
        actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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 index of the message file to delete
        TelephonyRequest ourRequest = new TelephonyRequest(Request);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;
        int messageIndex = -1;
        messageIndex = Convert.ToInt32(token);

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.GetMessageFilename(messageIndex);

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();

        if (filename != null)
        {
            actions.Add(new DeleteFile(filename));
            db.DeleteMessageFilename(messageIndex);

            Play msg = Play.SayText("Message deleted");
            if (messageIndex < db.Size())
            {
                msg.AddText("Next message.");
                actions.Add(msg);
                token = messageIndex.ToString();
            }
            else
            {
                actions.Add(msg);
                token = "";
            }

            actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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 index of the message file to keep
        TelephonyRequest ourRequest = new TelephonyRequest(Request);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;
        int messageIndex = -1;
        messageIndex = Convert.ToInt32(token);

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.GetMessageFilename(messageIndex);

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();
        if (filename != null)
        {
            actions.Add(Play.SayText("Message saved."));

            if (++messageIndex < db.Size())
            {
                actions.Add(Play.SayText("Next message."));
                actions.Add(new Redirect(new WebPageRequest("PlayMessage.aspx")));
                token = messageIndex.ToString();
            }
            else
            {
                actions.Add(Play.SayText("End of messages. Goodbye."));
                token = "";
            }
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();

        actions.Add(Play.SayText("Please leave a message after the beep. Press hash to end the recording."));

        Record recordAction = new Record(new WebPageRequest("RecordComplete.aspx"));
        recordAction.BeepOnStart = true;
        recordAction.BargeInDigits = "#";
        recordAction.MillisecondsMaxSilence = 5000;
        actions.Add(recordAction);

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        String token = ourRequest.InstanceInfo.Token;
        RecordResult result = (RecordResult)ourRequest.InstanceInfo.ActionResult;

        // Setup the actions
        List<TelephonyAction> actions = new List<TelephonyAction>();

        if (result.ContainsSound)
        {
            // Store the filename in our message file
            String filename = result.Filename;

            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."));
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.ToHttpResponse(Response);
    }
}
using System;
using System.IO;
using System.Collections.Generic;

public class MessageFilenameDatabase
{
    public MessageFilenameDatabase()
    {
        dbFilename = Path.GetTempPath() + "voicemailMessages.tmp";
    }

    public int Size()
    {
        if (!File.Exists(dbFilename))
        {
            return 0;
        }
        String[] messageFilenames = File.ReadAllLines(dbFilename);
        return messageFilenames.Length;
    }

    public String GetMessageFilename(int index)
    {
        if (!File.Exists(dbFilename))
        {
            return null;
        }

        String[] messageFilenames = File.ReadAllLines(dbFilename);
        try
        {
            return messageFilenames[index];
        }
        catch (IndexOutOfRangeException)
        {
            return null;
        }
    }

    public void AppendMessageFilename(String filename)
    {
        List<String> messageFilenames;
        if (File.Exists(dbFilename))
        {
            messageFilenames = new List<String>(File.ReadAllLines(dbFilename));
        }
        else
        {
            messageFilenames = new List<String>();
        }
        messageFilenames.Add(filename);
        SaveMessageFilenames(messageFilenames);
    }

    public void DeleteMessageFilename(int index)
    {
        if (!File.Exists(dbFilename))
        {
            return;
        }

        List<String> messageFiles = new List<String>(File.ReadAllLines(dbFilename));
        try
        {
            messageFiles.RemoveAt(index);
        }
        catch (IndexOutOfRangeException)
        {
            return;
        }

        SaveMessageFilenames(messageFiles);
    }

    private void SaveMessageFilenames(List<String> messageFiles)
    {
        File.WriteAllLines(dbFilename, messageFiles.ToArray());
    }

    private String dbFilename;
}
using System;
using System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
        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 System.Collections.Generic;
using 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);
        if (!ourRequest.IsValid)
        {
            return;
        }
    }
}

Implemented as ASP.Net Web Forms:

Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If

        ' 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)
        menuOptions.Add(New MenuOption("1", New WebPageRequest("RecordMessage.aspx")))
        menuOptions.Add(New MenuOption("2", New WebPageRequest("GetPasswordNumber.aspx")))
        Dim runMenuAction As RunMenu = New RunMenu(menuPrompt, menuOptions)
        actions.Add(runMenuAction)

        ' And add a final message
        actions.Add(Play.SayText("Goodbye."))

        ' Set to first message index
        Dim token As String = "0"
        ' Respond
        Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
        ourResponse.ToHttpResponse(Response)
    End Sub
End Class
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
        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(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
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If

        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
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
        Dim token As String = ourRequest.InstanceInfo.Token
        Dim messageIndex As Integer = -1
        messageIndex = Convert.ToInt32(token)

        Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
        Dim filename As String = db.GetMessageFilename(messageIndex)

        ' 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")))
            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 = messageIndex.ToString()
        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
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
        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
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If

        Dim token As String = ourRequest.InstanceInfo.Token
        Dim messageIndex As Integer = -1
        messageIndex = Convert.ToInt32(token)

        Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
        Dim filename As String = db.GetMessageFilename(messageIndex)

        ' Setup the actions
        Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)

        If filename IsNot Nothing Then
            actions.Add(New DeleteFile(filename))
            db.DeleteMessageFilename(messageIndex)

            Dim msg As Play = Play.SayText("Message deleted")
            If messageIndex < db.Size() Then
                msg.AddText("Next message.")
                actions.Add(msg)
                token = messageIndex.ToString()
            Else
                actions.Add(msg)
                token = ""
            End If

            actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
        End If

        ' Respond
        Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
        ourResponse.ToHttpResponse(Response)
    End Sub
End Class
Imports System
Imports System.Collections.Generic
Imports 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 index of the message file to keep
        Dim ourRequest As TelephonyRequest = New TelephonyRequest(Request)
        If Not ourRequest.IsValid Then
            Return
        End If
        Dim token As String = ourRequest.InstanceInfo.Token
        Dim messageIndex As Integer = -1
        messageIndex = Convert.ToInt32(token)

        Dim db As MessageFilenameDatabase = New MessageFilenameDatabase()
        Dim filename As String = db.GetMessageFilename(messageIndex)

        ' Setup the actions
        Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)
        If filename IsNot Nothing Then
            actions.Add(Play.SayText("Message saved."))

            If ++messageIndex < db.Size() Then
                actions.Add(Play.SayText("Next message."))
                actions.Add(New Redirect(New WebPageRequest("PlayMessage.aspx")))
                token = messageIndex.ToString()
            Else
                actions.Add(Play.SayText("End of messages. Goodbye."))
                token = ""
            End If
        End If

        ' Respond
        Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
        ourResponse.ToHttpResponse(Response)
    End Sub
End Class
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
        Dim token As String = ourRequest.InstanceInfo.Token

        ' Setup the actions
        Dim actions As List(Of TelephonyAction) = New List(Of TelephonyAction)

        actions.Add(Play.SayText("Please leave a message after the beep. Press hash to end the recording."))

        Dim recordAction As Record = New Record(New WebPageRequest("RecordComplete.aspx"))
        recordAction.BeepOnStart = True
        recordAction.BargeInDigits = "#"
        recordAction.MillisecondsMaxSilence = 5000
        actions.Add(recordAction)

        ' Respond
        Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
        ourResponse.ToHttpResponse(Response)
    End Sub
End Class
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If

        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)

        If result.ContainsSound Then
            ' Store the filename in our message file
            Dim filename As String = result.Filename

            Dim db As MessageFilenameDatabase = 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."))
        End If

        ' Respond
        Dim ourResponse As TelephonyResponse = New TelephonyResponse(actions, token)
        ourResponse.ToHttpResponse(Response)
    End Sub
End Class
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports Microsoft.VisualBasic

Public Class MessageFilenameDatabase

    Public Sub New()
        dbFilename = Path.GetTempPath() + "voicemailMessages.tmp"
    End Sub

    Public Function Size() As Integer
        If Not File.Exists(dbFilename) Then
            Return 0
        End If

        Dim messageFilenames As Array = File.ReadAllLines(dbFilename)
        Return messageFilenames.Length
    End Function

    Public Function GetMessageFilename(index As Integer) As String
        If Not File.Exists(dbFilename) Then
            Return Nothing
        End If

        Dim messageFilenames As Array = File.ReadAllLines(dbFilename)
        Try
            Return messageFilenames(index)
        Catch ex As IndexOutOfRangeException
            Return Nothing
        End Try
    End Function

    Public Sub AppendMessageFilename(filename As String)
        Dim messageFilenames As List(Of String)
        If File.Exists(dbFilename) Then
            messageFilenames = New List(Of String)(File.ReadAllLines(dbFilename))
        Else
            messageFilenames = New List(Of String)
        End If

        messageFilenames.Add(filename)
        SaveMessageFilenames(messageFilenames)
    End Sub

    Public Sub DeleteMessageFilename(index As Integer)
        If Not File.Exists(dbFilename) Then
            Return
        End If

        Dim messageFiles As List(Of String) = New List(Of String)(File.ReadAllLines(dbFilename))
        Try
            messageFiles.RemoveAt(index)
        Catch ex As IndexOutOfRangeException
            Return
        End Try

        SaveMessageFilenames(messageFiles)
    End Sub

    Private Sub SaveMessageFilenames(messageFiles As List(Of String))
        File.WriteAllLines(dbFilename, messageFiles.ToArray())
    End Sub

    Private dbFilename As String
End Class
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
        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
Imports System
Imports System.Collections.Generic
Imports 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)
        If Not ourRequest.IsValid Then
            Return
        End If
    End Sub
End Class

Implemented as Java Servlets:

package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class Voicemail extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }

        // 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('1', new WebPageRequest("RecordMessage"));
        menuOptions.add('2', new WebPageRequest("GetPasswordNumber"));
        RunMenu runMenuAction = new RunMenu(menuPrompt, menuOptions);
        actions.add(runMenuAction);

        // And add a final message
        actions.add(Play.sayText("Goodbye."));

        // Respond
        String token = "0"; // Set to first message index
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.setHttpServletResponse(response);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class GetPasswordNumber extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        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(prompt);
        getNumberAction.setEndDigit('#');
        getNumberAction.setNextPage(new WebPageRequest("CheckPasswordNumber"));
        actions.add(getNumberAction);

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.setHttpServletResponse(response);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class CheckPasswordNumber extends HttpServlet
{
    private static String myPassword = "1234";

    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        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);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class PlayMessage extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        String token = ourRequest.getInstanceInfo().getToken();
        int messageIndex = -1;
        messageIndex = Integer.parseInt(token);

        // Set up the actions
        List<TelephonyAction> actions = new ArrayList<TelephonyAction>();

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.getMessageFilename(messageIndex);
        if (filename != null)
        {
            actions.add(Play.playFile(filename));

            List<MenuOption> menuOptions = new ArrayList<MenuOption>();
            menuOptions.add('1', new WebPageRequest("MessageReplay"));
            menuOptions.add('2', new WebPageRequest("MessageDelete"));
            menuOptions.add('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(messageIndex);
        }
        else
        {
            actions.add(Play.sayText("End of messages. Goodbye."));
            token = "";
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.setHttpServletResponse(response);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class MessageReplay extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        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);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
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.nio.file.Path;
import java.util.List;
import com.aculab.telephonyrestapi.*;

public class MessageDelete extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        String token = ourRequest.getInstanceInfo().getToken();
        int messageIndex = -1;
        messageIndex = Integer.parseInt(token);

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.getMessageFilename(messageIndex);

        // Set up the actions
        List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
        if (filename != null)
        {
            actions.add(new DeleteFile(filename));
            db.deleteMessageFilename(messageIndex);

            actions.add(Play.sayText("Message deleted"));
            if (messageIndex < db.size())
            {
                actions.add(Play.sayText("Next message."));
                actions.add(new Redirect(new WebPageRequest("PlayMessage")));
                token = Integer.toString(messageIndex);
            }
            else
            {
                actions.add(Play.sayText("End of messages. Goodbye."));
                token = "";
            }
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.setHttpServletResponse(response);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
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.List;
import com.aculab.telephonyrestapi.*;

public class MessageKeep extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        String token = ourRequest.getInstanceInfo().getToken();
        int messageIndex = -1;
        messageIndex = Integer.parseInt(token);

        MessageFilenameDatabase db = new MessageFilenameDatabase();
        String filename = db.getMessageFilename(messageIndex);

        // Set up the actions
        List<TelephonyAction> actions = new ArrayList<TelephonyAction>();
        if (filename != null)
        {
            actions.add(Play.sayText("Message saved."));

            if (++messageIndex < db.size())
            {
                actions.add(Play.sayText("Next message."));
                actions.add(new Redirect(new WebPageRequest("PlayMessage")));
                token = Integer.toString(messageIndex);
            }
            else
            {
                actions.add(Play.sayText("End of messages. Goodbye."));
                token = "";
            }
        }

        // Respond
        TelephonyResponse ourResponse = new TelephonyResponse(actions, token);
        ourResponse.setHttpServletResponse(response);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class RecordMessage extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        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."));

        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);
    }
}
package com.aculab.telephonyrestapi.samples;

import javax.servlet.http.*;
import javax.servlet.ServletException;
import java.io.IOException;
import com.aculab.telephonyrestapi.*;

public class RecordComplete extends HttpServlet
{
    @Override
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException
    {
        handleRequest(request, response);
    }

    @Override
    public void doGet(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);
        if (!ourRequest.isValid())
        {
            return;
        }
        String token = ourRequest.getInstanceInfo().getToken();
        RecordResult result = (RecordResult)ourRequest.getInstanceInfo().getActionResult();

        // Set up the actions
        List<TelephonyAction> actions = new ArrayList<TelephonyAction>();

        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."));
        }

        // 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.ArrayList;
import java.util.List;

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);
        messageFile = new File(tempFilePath + "voicemailMessages.tmp");
    }

    public int size() throws IOException
    {
        List<String> messageFiles;
        if (!messageFile.exists())
        {
            return 0;
        }

        messageFiles = Files.readAllLines(messageFile.toPath(), Charset.defaultCharset());
        return messageFiles.size();
    }

    public String getMessageFilename(int index) throws IOException
    {
        try
        {
            List<String> messageFiles = getMessageFiles();
            return messageFiles.get(index);
        }
        catch (IndexOutOfBoundsException e)
        {
            return null;
        }
    }

    public void appendMessageFilename(String filename) throws IOException
    {
        List<String> messageFiles = getMessageFiles();
        messageFiles.add(filename);
        saveMessageFiles(messageFiles);
    }

    public void deleteMessageFilename(int index) throws IOException
    {
        List<String> messageFiles = getMessageFiles();
        messageFiles.remove(index);
        saveMessageFiles(messageFiles);
    }

    private List<String> getMessageFiles() throws IOException
    {
        List<String> messageFiles;
        if (messageFile.exists())
        {
            messageFiles = Files.readAllLines(messageFile.toPath(), Charset.defaultCharset());
        }
        else
        {
            messageFiles = new ArrayList<String>();
        }
        return messageFiles;
    }

    private void saveMessageFiles(List<String> messageFiles) throws IOException
    {
        BufferedWriter writer = new BufferedWriter(new FileWriter(messageFile, false));
        for (String filename : messageFiles)
        {
            writer.write(filename);
            writer.newLine();
        }
        writer.close();
    }

    private File messageFile;
}
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);
        if (!ourRequest.isValid())
        {
            return;
        }
        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);
    }
}
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);
        if (!ourRequest.isValid())
        {
            return;
        }
    }
}

Implemented using a wrapper for Python's wsgiref.simple_server.

For the purposes of this sample, the first page is first_page, the final page is final_page and the error page is error_page.

The application base class.

from aculab.telephony_rest_api import Play

class ApplicationBase:

    def __init__(self, exit=None):
        self.exit = exit or [self.exit]


    def exit(self):
        pass


    def error_page(self, my_actions, query_info):
        try:
            error_result = query_info.ErrorResult
            action = error_result.get('action', 'none')
            print("\nError {0} : {1}\n".format(action, error_result['result']))
            my_actions.add(Play(text_to_say='I encountered an error.'))

        except Exception as exc:
            print("Error page exception: {0}".format(exc))
        return True


    def final_page(self, my_actions, query_info):
        try:
            tcall = query_info.ThisCall
            if tcall:
                print("This call ID         : {0}".format(tcall.get('call_id')))
                print("This call duration   : {0}".format(tcall.get('seconds_call_duration')))
            self.exit[0]()
        except Exception as exc:
            print("Final page exception: {0}".format(exc))
        return True


    def unknown_page(self, my_actions, query_info):
        try:
            my_actions.add(Play(text_to_say='I find myself on an unknown page.'))
        except Exception as exc:
            print("Unknown page exception: {0}".format(exc))
        return True

The application code.

import os, sys
import json
from getpass import getpass

# append paths to the various wrappers
sys.path.append(os.path.abspath('../..'))

# import the wrappers for the web services API
# these are used to access media files stored on the cloud
from aculab.web_services import ws_connect
from aculab.web_services import ws_command

# import the wrappers for the REST API, these are used to create and send actions
from aculab.telephony_rest_api import *
from aculab.simple_server import *
from aculab.base_application import ApplicationBase

if sys.version > '3':
    def raw_input(text):
        return input(text)


# The web services API for media file access is used to implement a simple database. The database class is shown below::
class MyVoiceMailDatabase():
    def __init__(self, database_name, username, password, target):
        self._my_database_entries = []         # Runtime list of voicemail entries
        self._target   = target                # Aculab Cloud ID or Rapide IP address
        self._username = username              # Aculab Cloud username
        self._password = password              # Aculab Cloud password
        self._database_name = database_name    # Name of the voicemail box - local file of voicemail entries

        # Read the local copy of the voicemail box into the runtime list
        self._read_database()
        # Synchronise the database entries with what's currently on Aculab Cloud
        # (some files may have been deleted)
        connection, headers = ws_connect(self._username, self._password, self._target)
        response = ws_command(connection, headers, 'GET', "/media_list?filename=*")
        if response is None:
            print("Failed to list files on server.")
        else:
            if sys.version > '3':
                data = response.read().decode('utf-8')
            else:
                data = response.read()
            file_list = json.loads(data)
            files_on_server = list(file_list.keys())
            for file_name in self._my_database_entries[:]:
                if file_name not in files_on_server:
                    self._my_database_entries.remove(file_name)
        self._rewrite_database()
        connection.close()


    def _read_database(self):
        # If a database file exists, read the entries into the runtime list
        if os.path.isfile(self._database_name):
            with open(self._database_name, 'r') as db:
                self._my_database_entries = [line.strip() for line in db]


    def _rewrite_database(self):
        # Rewrite the local database file, using the runtime list
        with open(self._database_name, 'w') as db:
            for file_name in self._my_database_entries:
                db.write(file_name + '\n')


    def add_entry(self, file_name):
        # Add an entry to the runtime list and the local database file
        self._my_database_entries.append(file_name)
        with open(self._database_name, 'a') as db:
            db.write(file_name + '\n')


    def remove_entry(self, file_name):
        # Remove an entry from the runtime list, the local database file
        # and from Aculab Cloud storage
        self._my_database_entries.remove(file_name)

        connection, headers = ws_connect(self._username, self._password, self._target)
        response = ws_command(connection, headers, 'DELETE', "/media_delete?filename={0}".format(file_name))
        if response is None:
            print("Failed to delete {0}.".format(file_name))
        self._rewrite_database()
        connection.close()


    def get_all_entries(self):
        # Return a copy of the runtime voicemail list
        return self._my_database_entries[:]


# Now on to the application itself. The primary application class inherits from a base class.
# The primary application class is passed to our wrapper for Python's simple HTTP server which
# expects a ``responder`` function. We implement ``responder()`` in our class. It is in the 
# ``responder`` function that we implement the actions::

class Application(ApplicationBase):

    # The constructor expects the name of the voicemail box, our username,
    # password and the ID / IP address of the cloud or Rapide we want to connect to. 
    # These are not required by the REST API but are required to implement the database.
    def __init__(self, voicemail_box, username, password, target):
        ApplicationBase.__init__(self)
        # Instantiate the voicemail database
        self._voicemail_database = MyVoiceMailDatabase(voicemail_box, username, password, target)
        self._voicemails_to_read = []

    # This function is called by Python's simple HTTP server. 
    # It is in this function that we create our actions.
    def responder(self, query, start_response):

        query_info = RESTQuery(query)
        page = query_info.Page

        print("Page: {0}".format(page))

        # The instance information might contain an action_result
        # object. Some actions require a return value, this will be
        # contained in the action_result object.
        action_result = query_info.ActionResult
        ivr_digit = 0
        id_digits = ''

        # This application implements a couple of simple IVRs. 
        # If the IVR is successful an action_result object is
        # returned.
        if action_result:
            # In this application, the action_result object will 
            # contain either a single digit, or a digit string.
            if action_result['action'] == 'run_menu':
                ivr_digit = int(action_result['result']['selected_digit'])
            elif action_result['action'] == 'get_number':
                id_digits = action_result['result']['entered_number']

        # Here we begin to create our action list in response to the query
        my_actions = Actions(token='Voicemail demo application')

        # Every application must have a first page, this is where the 
        # application begins. The first page name is one of the settings
        # of the inbound service that invokes this application. Here we 
        # name it first_page. This page is called in response to an 
        # incoming telephone call.
        if 'first_page' == page:

            # The first page of the voicemail application is going to
            # ask the caller whether they want to leave a message or
            # listen to messages. We will use the RunMenu() wrapper 
            # to configure this IVR action
            my_menu = RunMenu()

            # The IVR prompt is a Play Action which should provide the caller
            # with all the information they need to provide an appropriate response.
            my_menu.on_prompt_play(Play(text_to_say= ('Press 1 to leave a message.'
                                                      'Press 2 to listen to all messages.')))

            # There are two options to thie menu, digit 1 and digit 2. Each digit can
            # be linked to its own next page. Here both digits will go to the caller_choice page.
            # Setting a page for each digit is demonstrated further down in this application.
            my_menu.set_menu_options('12', WebPage(url='caller_choice'))

            # Now we append the IVR action to the action list.
            my_actions.add(my_menu)

            # The final action for this page is a redirection to the final page. This
            # is here in case the IVR dialogue fails. If, for instance, the caller
            # does not press a valid key, the application will drop through to this
            # action and the final page will be called.
            my_actions.add(Redirect(next_page=WebPage(url='/final_page')))

        # This page is called as the result of a successful response to the IVR in the 
        # first page. The caller will have responded with 1 or 2.
        elif 'caller_choice' == page:

            if ivr_digit == 1:
                # 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.
                my_actions.add(Play(text_to_say='Please leave a message after the beep. Press hash to end the recording.'))

                # The next action it to start recording. When the recording has completed, the application
                # will be directed to the my_recorded_file_page.
                my_actions.add(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='recorded_file_page'), # when recording completes, go to this page
                                      beep_on_start=True))               # before recording begins, play a beep

            elif ivr_digit == 2:

                # 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()
                my_number.set_end_digit('#')
                # As with RunMenu, we provide an initial prompt.
                my_number.on_prompt_play(Play(text_to_say='Please enter your identification number followed by the hash key.'))

                # If the caller successfully enters a number, the next_page (check_id_digits) will be called.
                my_number.set_next_page(next_page=WebPage(url='check_id_digits'))

                # Now we add the action to the actions list. 
                my_actions.add(my_number)

        # This page is called after a successful IVR to gather the caller's PIN.
        elif 'check_id_digits' == page:
            # For our purposes the PIN is hard-coded to 1234
            if id_digits == '1234':
                # The PIN is correct so gather the list of recorded messages
                self._voicemails_to_read = self._voicemail_database.get_all_entries()
                try:
                    self._currently_reading = self._voicemails_to_read.pop(0)
                except:
                    self._currently_reading = None

                # We have created a list of the recorded messages and have set
                # a variable to the first one, now use a redirect action to move
                # the application to the my_play_recording_page page.
                my_actions.add(Redirect(next_page=WebPage(url='play_recording_page/')))

            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.
                my_actions.add(Play(text_to_say='Sorry, that ID is not correct. Goodbye.'))

        # This is the page for playing recorded messages. The application will come
        # here if the caller has successfully authorised himself to listen to the
        # messages in his voicemail box.
        elif 'play_recording_page' == page:
            if self._currently_reading is not None:

                # We have a message to play, set the action to play the
                # message and then redirect to the keep or delete page 
                # on which the caller can choose to save or delete the message.
                my_actions.add(Play(file_to_play=self._currently_reading))
                my_actions.add(Redirect(next_page=WebPage(url='replay_keep_or_delete/')))

            else:
                # There are no more messages to play, so say goodbye and hang up.
                my_actions.add(Play(text_to_say='End of messages. Goodbye.'))

        # This page asks the caller whether he wants to keep or delete the
        # recorded message that has just been played.
        elif 'play_recording_page/replay_keep_or_delete' == page:

            # We use a simple IVR menu which gives the caller three choices:
            # Hear the message again, delete the message, keep (save) the message.
            # If the IVR is successful, the application redirects to the process message
            # page on which the choice is processed.
            my_menu = RunMenu()
            my_menu.on_prompt_play(Play(text_to_say= ('Press 1 to hear the message again.'
                                                      'Press 2 to delete it, '
                                                      'or press 3 to save it.')))

            # Here we set a next_page for each of the three options
            my_menu.append_menu_option('1', WebPage(url='play_again'))
            my_menu.append_menu_option('2', WebPage(url='delete'))
            my_menu.append_menu_option('3', WebPage(url='save'))

            # And now add the action to the list
            my_actions.add(my_menu)

            # As before, if the IVR fails to get a valid response, the application
            # will drop through to a redirect action that goes to the final page.
            my_actions.add(Redirect(next_page=WebPage(url='/final_page')))

        # This page is called to process the caller's decision to play the message again.
        elif 'play_recording_page/replay_keep_or_delete/play_again' == page:

            my_actions.add(Play(text_to_say='Playing the message again.'))
            # redirect back to the base page for listening to recorded messages
            my_actions.add(Redirect(next_page=WebPage(url='/play_recording_page/')))

        # This page is called to process the caller's decision to delete the message.
        elif 'play_recording_page/replay_keep_or_delete/delete' == page:

            self._voicemail_database.remove_entry(self._currently_reading)
            my_actions.add(Play(text_to_say='Message deleted.'))

            # Move to the next message in the list.
            try:
                self._currently_reading = self._voicemails_to_read.pop(0)
                my_actions.add(Play(text_to_say='Next message.'))
            except:
                self._currently_reading = None
            # redirect back to the base page for listening to recorded messages
            my_actions.add(Redirect(next_page=WebPage(url='/play_recording_page/')))

        # This page is called to process the caller's decision to save the message.
        elif 'play_recording_page/replay_keep_or_delete/save' == page:

            my_actions.add(Play(text_to_say='Message saved.'))

            # Move to the next message in the list.
            try:
                self._currently_reading = self._voicemails_to_read.pop(0)
                my_actions.add(Play(text_to_say='Next message.'))
            except:
                self._currently_reading = None
            # redirect back to the base page for listening to recorded messages
            my_actions.add(Redirect(next_page=WebPage(url='/play_recording_page/')))

        # We come to this page after recording a new message. Say thank you
        # and then hang up.
        elif 'recorded_file_page' == page:
            print("Recorded file is {0}".format(action_result['result']['filename']))
            self._voicemail_database.add_entry(action_result['result']['filename'])
            my_actions.add(Play(text_to_say='Thanks for leaving the recording. Goodbye.'))

        # The error handling page and the final page are supplied by the
        # application base class.
        elif 'final_page' == page:
            self.final_page(my_actions, query_info)

        elif 'error_page' == page:
            self.error_page(my_actions, query_info)

        else:
            self.unknown_page(my_actions, query_info)

        response_body = my_actions.get_json()
        response_headers = [('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', str(len(response_body)))]
        start_response('200 OK', response_headers)
        return [response_body]


if __name__ == "__main__":
    username = raw_input('Your cloud or Rapide username:')
    password = getpass('Your cloud or Rapide password:')
    target = raw_input('The cloud region, e.g. 1-2-0, or Rapide IP address:')

    application = Application('test_vm_box.txt', username, password, target)
    # Set the host and port you want to use in the rest_simple_server.py file.
    # To use SSL also set the key and certificate file.
    simple_server = SimpleServer(application, simple_server_host, simple_server_port, simple_server_keyfile, simple_server_certfile)
    simple_server.start()
    print("Hit ctl-break to quit.")
declare(encoding='UTF-8');
spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\RunMenu;

$resp = new Actions();
$resp->setToken('0');

// Create the menu action
$menuPrompt = Play::sayText("Press 1 to leave a message. Press 2 to listen to all messages.");
$menu = new RunMenu($menuPrompt);
$menu->addMenuOption('1', 'RecordMessage.php');
$menu->addMenuOption('2', 'GetPasswordNumber.php');

$resp->add($menu);

$resp->add(Play::sayText('Goodbye.'));

print $resp;
declare(encoding='UTF-8');
spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\GetNumber;

$response = new Actions();
$response->setToken('0');

// Create the get number action
$prompt = Play::sayText("Please enter your password number followed by the hash key.");
$getNumberAction = new GetNumber($prompt);
$getNumberAction->setEndDigit('#');
$getNumberAction->setNextPage("CheckPasswordNumber.php");

$response->add($getNumberAction);


$response->add(Play::sayText('Goodbye.'));

print $response;
declare(encoding='UTF-8');
spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\Redirect;

$info = InstanceInfo::getInstanceInfo();

$response = new Actions();
$enteredNumber = '';
if ($info != null) {
    // 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->add(new Redirect('PlayMessage.php'));
} else {
    $response->add(Play::sayText('Sorry, that password is not correct. Goodbye.'));
}

print $response;
declare(encoding='UTF-8');

include './Config.php';

spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\RunMenu;
use \Aculab\TelephonyRestAPI\InstanceInfo;

$fidx = 0;
$info = InstanceInfo::getInstanceInfo();
if ($info != null) {
    $fidxstr = $info->getToken();
    if ($fidxstr != null) {
        $fidx = $fidxstr + 0;
    }
}

$response = new Actions();

$messagelist = file($message_list_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($messagelist === false) {
    $messagelist = array();
}
if ($fidx < count($messagelist)) {
    $response->add(Play::playFile($messagelist[$fidx]));
    $response->setToken( (string) $fidx );

    // 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($menuPrompt);
    $menu->addMenuOption('1', 'MessageReplay.php');
    $menu->addMenuOption('2', 'MessageDelete.php');
    $menu->addMenuOption('3', 'MessageKeep.php');

    $response->add($menu);

    $response->add(Play::sayText('Goodbye.'));
} else {
    $response->add(Play::sayText('End of messages. Goodbye.'));
}

print $response;
declare(encoding='UTF-8');
spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\Redirect;

$info = InstanceInfo::getInstanceInfo();

$response = new Actions();

$response->add(Play::sayText('Playing the message again.'));
$response->add(new Redirect('PlayMessage.php'));

print $response;
declare(encoding='UTF-8');

include './Config.php';

spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\DeleteFile;
use \Aculab\TelephonyRestAPI\Redirect;
use \Aculab\TelephonyRestAPI\InstanceInfo;

$fidx = 0;
$info = InstanceInfo::getInstanceInfo();
if ($info != null) {
    $fidxstr = $info->getToken();
    if ($fidxstr != null) {
        $fidx = $fidxstr + 0;
    }
}

$response = new Actions();

$messagelist = file($message_list_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($messagelist === false) {
    $messagelist = array();
}

$play = Play::sayText('Message saved.');

if (++$fidx < count($messagelist)) {
    $play->addText('Next message.');
}
$response->add($play);

$response->setToken($fidx);

$response->add(new Redirect('PlayMessage.php'));

print $response;
declare(encoding='UTF-8');

include './Config.php';

spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\DeleteFile;
use \Aculab\TelephonyRestAPI\Redirect;
use \Aculab\TelephonyRestAPI\InstanceInfo;

$fidx = 0;
$info = InstanceInfo::getInstanceInfo();
if ($info != null) {
    $fidxstr = $info->getToken();
    if ($fidxstr != null) {
        $fidx = $fidxstr + 0;
    }
}

$response = new Actions();

$messagelist = file($message_list_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($messagelist === false) {
    $messagelist = array();
}
if ($fidx < count($messagelist)) {
    $response->add(new DeleteFile($messagelist[$fidx]));

    array_splice($messagelist, $fidx, 1);

    // rewrite the file
    $f = fopen($message_list_filename, 'w');
    if ($f !== false) {
        fwrite($f, implode("\n", $messagelist));
        fclose($f);
    }
}
$play = Play::sayText('Message deleted.');

if ($fidx < count($messagelist)) {
    $play->addText('Next message.');
}
$response->add($play);

$response->setToken($fidx);

$response->add(new Redirect('PlayMessage.php'));

print $response;
declare(encoding='UTF-8');
spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\Record;

$resp = new Actions();

$resp->add(Play::sayText("Please leave a message after the beep. Press hash to end the recording."));

$record = new Record();
$record->setNextPage('RecordComplete.php');
$record->setBeepOnStart(true);
$record->setBargeInDigits('#');
$record->setMillisecondsMaxSilence(5000);
$resp->add($record);

print $resp;
declare(encoding='UTF-8');

include './Config.php';

spl_autoload_register();
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\Actions;
use \Aculab\TelephonyRestAPI\Play;
use \Aculab\TelephonyRestAPI\InstanceInfo;

$fname = '';
$info = InstanceInfo::getInstanceInfo();
if ($info != null) {
    $recordResult = $info->getActionResult();
    if ($recordResult != null && $recordResult->getContainsSound()) {
        $fname = $recordResult->getFilename();
    }
}

$response = new Actions();

if ($fname != '') {
    $messagelist = file($message_list_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if ($messagelist === false) {
        $messagelist = array();
    }

    $messagelist[] = $fname;

    // rewrite the file
    $f = fopen($message_list_filename, 'w');
    if ($f !== false) {
        fwrite($f, implode("\n", $messagelist));
        fclose($f);
    }
    $response->add(Play::sayText('Thanks for leaving a message. Goodbye.'));
} else {
    $response->add(Play::sayText('There was no message recorded. Goodbye.'));
}

print $response;
declare(encoding='UTF-8');

// this is the name of the file used to store the recorded message filenames
// the file must be readable and writable by the web server process
$message_list_filename = '/var/www/voicemail/db/message_files.txt';
declare(encoding='UTF-8');
spl_autoload_register();
header("Content-Type: application/json; charset=UTF-8");

$info = \Aculab\TelephonyRestAPI\InstanceInfo::getInstanceInfo();

$error = $info->getErrorResult();
$action = $error->getAction();
$desc = $error->getResult();
if (!is_null($action)) {
    error_log("Error from action \"$action\" with result:\n$desc\n");
} else {
    error_log("Error result:\n$desc\n");
}

$response = new \Aculab\TelephonyRestAPI\Actions();
$response->setToken('Error');

$play = new \Aculab\TelephonyRestAPI\Play();
$play->addText('An error has occurred.');
$response->add($play);

print $response;
declare(encoding='UTF-8');
spl_autoload_register();
header("Content-Type: application/json; charset=UTF-8");

$info = \Aculab\TelephonyRestAPI\InstanceInfo::getInstanceInfo();
$call = $info->getThisCallInfo();
$callid = $call->getCallId();
$duration = $call->getSecondsCallDuration();
error_log("This all id: $callid\nThis call duration: $duration\n");

print '';