__uas_identify__ = "application" __uas_version__ = "1.0b1" from prosody.uas import Hangup, Error, PlayableMedia from prosody.uas.highlevel import HighLevelCallChannel, HighLevelGrammar, HighLevelDigitInputOptions """ An inbound application that prompts the user to select a target to be transferred to. The target names and addresses - or phone numbers - are provided in application_parameters. These are set, during service registration, on the inbound service registration page at cloud.aculab.com. The application_parameters must be a delimited string in the format: ,
;,
For example: "Fred,sip:fred@place.com;Jack,sip:jack@place.com" The target names are used to create an automatic speech recognition (ASR) grammar. ASR is used to get the caller's choice and the call is then connected to the target address. A digit is associated with each name, and this can be entered on the telephone keypad instead of speaking. At application start, the target names are read out along with the associated digit. This application requires 1 extra channel. Actions: - wait for an inbound call - generate the transfer options menu - speak the options using TTS - listen for the caller's selection using ASR and DTMF - transfer the call """ def transfer_menu(application_parameters, my_log): # Split the application_parameters up into transfer options # (split with semicolon), and then again with commas. Return the # data as a dictionary try: return dict(tuple(a.split(',')) for a in application_parameters.split(';')) except Exception as exc: my_log.error("The application parameters could not be parsed correctly: {0}".format(exc)) return {} def get_menu_selection(channel, transfer_list, my_log): channel.DTMFDetector.clear_digits() my_log.info("transfer_list: {0}".format(transfer_list)) # create a speech recognition grammar of the IVR options my_grammar = HighLevelGrammar() my_grammar.create_from_alternatives(*transfer_list.keys()) valid_digits = range(len(transfer_list)) my_digit_options = HighLevelDigitInputOptions(valid_digits=''.join(map(str, valid_digits))) prompt_text = 'Please say the name of the person you want to call. Or press ' for digit in valid_digits: # associate digits with the names prompt_text = prompt_text + "{0} for {1}, ".format(digit, list(transfer_list.keys())[digit]) prompt = PlayableMedia(text_to_say=prompt_text, channel=channel) response = channel.capture_input(prompt, speech_recognition_grammar=my_grammar, digit_input_options=my_digit_options) # if response is None, no valid input was detected if response is not None: # check whether we got speech or digits if response.type == response.Type.SPEECH: # return the name return response.input else: # return the name associated with the digit return transfer_list.keys()[int(response.input)] return None def main(channel, application_instance_id, file_man, my_log, application_parameters): my_log.info("Transfer menu started") return_code = 0 try: channel.ring(1) channel.answer() my_log.info("Call answered") # in this application, we will using the high level API wrapper # for the channel object high_level_channel = HighLevelCallChannel(channel, my_log) try: # an extra channel is required, the number of extra channels # available is set on the service page out_channel = channel.ExtraChannel[0] except: raise Error("You need to register an extra channel for this application.") # Convert the application_parameters into a transfer menu list for later use transfer_list = transfer_menu(application_parameters, my_log) if not transfer_list: raise Error("Invalid transfer menu") # Prompt for digit channel.FilePlayer.say("Hello. ") target = get_menu_selection(high_level_channel, transfer_list, my_log) if not target: channel.FilePlayer.say("There is nobody to call.") else: # we will use the high level channel to place an outbound call and connect # the inbound and outbound calls together. If the target is a PSTN call # you will have to supply a call_from as well - please see the online documentation # on placing outbound PSTN calls. print("Calling {0}".format(target)) if high_level_channel.call_and_connect(out_channel, call_to=transfer_list[target]) is False: channel.FilePlayer.say("I wasn't able to transfer you. Please try again later.") channel.hang_up() channel.wait_for_idle() except Hangup as exc: my_log.info("Got Hangup") return_code = 100 except Error as exc: my_log.error("Got Error: {0}".format(exc)) return_code = -101 except Exception as exc: my_log.exception("Got unexpected exception: {0}".format(exc)) return_code = -102 finally: if channel.state() != channel.State.IDLE: channel.hang_up() return return_code