class AMISpecifier(propertied.Propertied): """Manager interface setup/specifier""" username = common.StringLocaleProperty( "username", """Login username for the manager interface""", ) secret = common.StringLocaleProperty( "secret", """Login secret for the manager interface""", ) password = secret server = common.StringLocaleProperty( "server", """Server IP address to which to connect""", defaultValue='127.0.0.1', ) port = common.IntegerProperty( "port", """Server IP port to which to connect""", defaultValue=5038, ) timeout = common.FloatProperty( "timeout", """Timeout in seconds for an AMI connection timeout""", defaultValue=5.0, ) def login(self): """Login to the specified manager via the AMI""" theManager = manager.AMIFactory(self.username, self.secret) return theManager.login(self.server, self.port, timeout=self.timeout)
class Interaction(propertied.Propertied): """Base class for user-interaction operations""" ALL_DIGITS = '0123456789*#' timeout = common.FloatProperty( "timeout", """Duration to wait for response before repeating message""", defaultValue=5, ) maxRepetitions = common.IntegerProperty( "maxRepetitions", """Maximum number of times to play before failure""", defaultValue=5, ) onSuccess = basic.BasicProperty( "onSuccess", """Optional callback for success with signature method( result, runner )""", ) onFailure = basic.BasicProperty( "onFailure", """Optional callback for failure with signature method( result, runner )""", ) runnerClass = None def __call__(self, agi, *args, **named): """Initiate AGI-based interaction with the user""" return self.runnerClass(model=self, agi=agi)(*args, **named)
class CollectAudio(Interaction): """Collects audio file from the user""" prompt = common.ListProperty( "prompt", """(Set of) prompts to run, can be Prompt instances or filenames Used by the PromptRunner to produce prompt selections """, ) textPrompt = common.StringProperty( "textPrompt", """Textual prompt describing the option""", ) temporaryFile = common.StringLocaleProperty( "temporaryFile", """Temporary file into which to record the audio before moving to filename""", ) filename = common.StringLocaleProperty( "filename", """Final filename into which to record the file...""", ) deleteOnFail = common.BooleanProperty( "deleteOnFail", """Whether to delete failed attempts to record a file""", defaultValue=True) escapeDigits = common.StringLocaleProperty( "escapeDigits", """Set of digits which escape from recording the file""", defaultValue='#*0123456789', ) timeout = common.FloatProperty( "timeout", """Duration to wait for recording (maximum record time)""", defaultValue=60, ) silence = common.FloatProperty( "silence", """Duration to wait for recording (maximum record time)""", defaultValue=5, ) beep = common.BooleanProperty( "beep", """Whether to play a "beep" sound at beginning of recording""", defaultValue=True, ) runnerClass = CollectAudioRunner
class PromptRunner(propertied.Propertied): """Prompt formed from list of sub-prompts """ elements = common.ListProperty( "elements", """Sub-elements of the prompt to be presented""", ) agi = basic.BasicProperty( "agi", """The FastAGI instance we're controlling""", ) escapeDigits = common.StringLocaleProperty( "escapeDigits", """Set of digits which escape from playing the prompt""", ) timeout = common.FloatProperty( "timeout", """Timeout on data-entry after completed reading""", ) def __call__(self): """Return a deferred that chains all of the sub-prompts in order Returns from the first of the sub-prompts that recevies a selection returns str(digit) for the key the user pressed """ return self.onNext(None) def onNext(self, result, index=0): """Process the next operation""" if result is not None: return result try: element = self.elements[index] except IndexError, err: # okay, do a waitForDigit from timeout seconds... return self.agi.waitForDigit(self.timeout).addCallback( self.processKey).addCallback(self.processLast) else:
class PromptRunner(propertied.Propertied): """Prompt formed from list of sub-prompts """ elements = common.ListProperty( "elements", """Sub-elements of the prompt to be presented""", ) agi = basic.BasicProperty( "agi", """The FastAGI instance we're controlling""", ) escapeDigits = common.StringLocaleProperty( "escapeDigits", """Set of digits which escape from playing the prompt""", ) timeout = common.FloatProperty( "timeout", """Timeout on data-entry after completed reading""", ) def __call__(self): """Return a deferred that chains all of the sub-prompts in order Returns from the first of the sub-prompts that recevies a selection returns str(digit) for the key the user pressed """ return self.onNext(None) def onNext(self, result, index=0): """Process the next operation""" if result is not None: return result try: element = self.elements[index] except IndexError as err: # okay, do a waitForDigit from timeout seconds... return self.agi.waitForDigit(self.timeout).addCallback( self.processKey).addCallback(self.processLast) else: df = element.read(self.agi, self.escapeDigits) df.addCallback(self.processKey) df.addCallback(self.onNext, index=index + 1) return df def processKey(self, result): """Does the pressed key belong to escapeDigits?""" if isinstance(result, tuple): # getOption result... if result[1] == 0: # failure during load of the file... log.warn("Apparent failure during load of audio file: %s", self.value) result = 0 else: result = result[0] if isinstance(result, str): if result: result = ord(result) else: result = 0 if result: # None or 0 # User pressed a key during the reading... key = chr(result) if key in self.escapeDigits: log.info('Exiting early due to user press of: %r', key) return key else: # we don't warn user in this menu if they press an unrecognised key! log.info( 'Ignoring user keypress because not in escapeDigits: %r', key) # completed reading without any escape digits, continue reading return None def processLast(self, result): if result is None: result = '' return result