VoiceXML & Instant Messaging
by Moshe Yudkowsky


Listing One
<var name="flight.city"/>
<var name="flight.timeofday"/>
(a)
<var name="callerid" expr="session.telephone.ani"/>
<form id="flight_information">
    <field name="cityName">
        <prompt>
            What city did you want to fly to?
        </prompt>
        <grammar>
            [ chicago (new york) pittsburgh (san francisco) ]
        </grammar>
        <!-- User/ASR Errors -->
        <nomatch>
           <prompt>
              Choices are Chicago, New York, Pittsburgh, and San Francisco.
           </prompt>
           <reprompt/>
        </nomatch>
        <noinput>
           <reprompt/>
        </noinput>
       <filled>
            <assign name="flight.city" expr="cityName" />
        </filled>
    </field>
    <filled>
        <goto next="#sendFlightInformationAnnounce"/>
    </filled>
</form>

(b)
<form id="sendFlightInformationAnnounce">
    <block>
        <prompt>
            One moment please while I send you choices for flights
            to <value expr="flight.city"/>
            leaving in the <value expr="flight.timeofday"/>.
        </prompt>
    </block>
    <field name="scratch" type="digits?minlength=22">
        <prompt timeout="1"><break msecs="1"/></prompt>
        <catch event="noinput nomatch filled">
            <goto next="#sendFlightInformation"/>
        </catch>
    </field>
</form>

(c)
<form id="sendFlightInformation">
    <subdialog name="flightInfo"
                        src="http://disaggregate.com/cgi/flightInfo.cgi"
            namelist="callerid flight.city flight.timeofday" method="post">
        <error count="1">
        </error>
        <error count="2">
            <assign name="FlightInfo.message" expr="'Actually, we couldn't
                                           retrieve the data. Fake it.'"/>
            <goto nextitem="sendInfo"/>
        </error>
        <catch event="normal">
                <goto nextitem="sendInfo"/>
        </catch>
    </subdialog>
    <subdialog name="sendInfo"
                       src="http:http://disaggregate.com/cgi/sendInfo.cgi"
            namelist="callerid flight.city flight.
                             timeofday flightInfo.message" method="post">
        <error count="1">
            <prompt>I had trouble sending to you. Let me try again.</prompt>
        </error>
        <error count="2">
            <goto next="#readFlightInformation"/>
        </error>
        <catch event="normal">
            <goto next="#getChoice"/>
        </catch>
    </subdialog>
</form>


Listing Two
<form id="getChoice">
    <var name="noDialogProblems" expr="0"/>
    <field name="choiceVoice" type="number">
        <prompt count="1" timeout="4s">
            Please look at the list of flights.
            From that list of flights, what is the flight number you prefer?
        </prompt>
        <prompt count="2" timeout="4s">
            Please take your time. I will wait for up to a minute for you
            to make up your mind. If I don't hear you, just speak again.
        </prompt>
        <prompt count="3" timeout="4s">
            Waiting:
        </prompt>
        <catch event="nomatch noinput">
           <goto nextitem="resultIM"/>
        </catch>
        <catch event="noinput nomatch" count="11">
            <goto next="#noChoice"/>
        </catch>
        <help>
            <prompt>
                Please say the flight number, or write the flight number,
                of the flight you prefer.
             </prompt>
        </help>
        <filled>
            <prompt>
                Thank you for choosing
                          flight <value class="digits" expr="choiceVoice"/>.
            </prompt>
            <goto next="#topMenu"/>
        </filled>
    </field>
    <subdialog cond="noDialogProblems==0" name="resultIM"
            src="http://disaggregate.com/cgi/rcvInfo.cgi"
                               namelist="callerid" method="post">
        <error>
            <reprompt/>
            <goto nextitem="choiceVoice"/>
        </error>
        <error count="2">
            <reprompt/>
            <assign name="noDialogProblems" expr="1"/>
            <goto nextitem="choiceVoice"/>
        </error>
        <catch event="normal">
                <reprompt/>
                <goto nextitem="choiceVoice"/>
        </catch>
        <filled>
            <if cond="resultIM.flag != 0">
                <prompt>
                    Thank you for choosing flight <value class="digits"
                                               expr="resultIM.message"/>.
                </prompt>
                <goto next="#topMenu"/>
            </if>
        </filled>
    </subdialog>
</form>


Listing Three
(a)
def rcvIM (address):
    """receive IM message: log in, check for message, log out"""
    con = imLogin(receive,rcvObj=receiveMessageCB)
    con.process(0.5)
    con.disconnect()
    return [ x for x in messageList if x[0].getStripped() == address ]

(b)
quote="" ; tick""; space=" "
def endProgram(messageList="", failed=0, eventname=None) :
    """End program by printing out VoiceXML
    """
    if failed :
        if eventname is None :
            eventname = "error.com.disaggregate.cgi.failed"
        else :
            eventname = "error.com.disaggregate." + eventname
    print "Content-type: text/plain"
    print ""
    print """<?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE vxml PUBLIC '-//Nuance/DTD VoiceXML 1.0//EN'
     'http://voicexml.nuance.com/dtd/nuancevoicexml-1-3.dtd' >
    <vxml version="1.0">
    <form>
    """
    # Tell VoiceXML script that called us to throw an exception if,
    # for some reason, we were unable to send the IM
    if failed :
        print '<block><return event="' + eventname + '"/></block>'
    else :
        if messageList :        # only if there are messages
            # assign return text to variable message, return message variable
            stringList = [ x[1] for x in messageList ]  # list of just strings
            messageString = " ".join(stringList)       # into one long message
                                                       # separated by spaces
            # create variable message with value
            retval = '<var name=' + quote + 'message' + quote + space
            retval += 'expr=' + quote + tick
            retval += messageString + tick + quote
            retval += '/>'
            print retval
            # flag if message has actual info
            retval = '<var name=' + quote + 'flag' + quote + space
            retval += 'expr=' + quote
            retval += str(len(messageString)) + quote
            retval += '/>'
            print retval
            print '<block><return namelist="flag message"/></block>'
        # if there is no input, throw innocuous event
        else :
            print '<block><return event="normal"/></block>'
    print """</form></vxml>"""
   sys.exit()          # "successful" exit




