""" WikiPBX web GUI front-end for FreeSWITCH Copyright (C) 2007, Branch Cut License Version: MPL 1.1 """ import os os.environ['DJANGO_SETTINGS_MODULE']='wikipbx.settings' from freeswitch import * from wikipbx.wikipbxweb.models import * from wikipbx import mailutil reload(mailutil) import wikipbx.ivr.baseivr reload(wikipbx.ivr.baseivr) from wikipbx.ivr.baseivr import BaseIvr from pytz import timezone import datetime import time import md5 class VoicemailIvr(BaseIvr): def __init__(self, session): super(VoicemailIvr, self).__init__(session) self.mailbox_name = self.session.getVariable("mailbox") self.userprofile = None if self.mailbox_name and self.mailbox_name != "None": mbn = self.mailbox_name userprofs = UserProfile.objects.filter(account=self.account, user__email=mbn) if userprofs: self.userprofile = userprofs[0] self.uuid = self.session.getVariable("uuid") # the number dialed, we can use this to match it with an # existing endpoint, and then from there figure out what # userprofile to use for storing voicemail self.dest_num = self.session.getVariable("destination_number") if not self.dest_num or self.dest_num == "None": self.dest_num = None #----- VOICEMAIL PLAYER ---------------------------------------------------- class VoicemailPlayerIvr(VoicemailIvr): #--- INIT --------------- def __init__(self, session): super(VoicemailPlayerIvr, self).__init__(session) self.login_attempts = 0 #--- MAIN --------------- def main(self): logged_in = self.login() if not logged_in: console_log("INFO", "Not Logged In...\n") return self.browse_voicemails() #--- BROWSE VOICEMAILS --------------- def browse_voicemails(self): console_log("INFO", "Browsing Voicemails...\n") self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-hello.wav") if self.userprof: voicemails = Voicemail.objects.filter(account=self.account,userprofile=self.userprof) voicemails = voicemails.order_by("id") else: # account wide login voicemails = Voicemail.objects.filter(account=self.account,userprofile__isnull=True) #self.speak("There are %s voicemail messages" % len(voicemails)) console_log("INFO", "Num Voicemails: %s\n" % len(voicemails)) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-you_have.wav") numberfile="/usr/local/freeswitch/sounds/en/us/callie/digits/8000/" + str(len(voicemails)) + "." + "wav" self.session.streamFile(numberfile) self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-messages.wav") if not voicemails: self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodbye.wav") self.playbeep() return for voicemail in voicemails: self.play_voicemail(voicemail) #self.speak("There are no more voicemail messages. Goodbye") console_log("INFO", "No more voicemails...\n") self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodby.wav") self.playbeep() #--- PLAY VOICEMAIL --------------- def play_voicemail(self, voicemail): #self.speak("Going to play voicemail %s" % voicemail.id) console_log("INFO", "Playing VoiceMail: %d\n" % voicemail ) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-new.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-message.wav") self.session.streamFile(voicemail.get_path()) self.post_play_options(voicemail) #--- POST PLAY OPTIONS --------------- def post_play_options(self, voicemail): #thing2say = "Press 1 to replay voicemail. " self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-listen_to_recording_again.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-press.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/digits/8000/1.wav") #thing2say += "Press 2 to delete voicemail. " self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-delete_recording.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-press.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/digits/8000/2.wav") #tempfile = self.make_tts_file(thing2say) #in_rslt = self.session.playAndGetDigits(1,1,3,6000, # "*#",tempfile, # "", "","")[1] selection = self.session.getDigits("",5,10,"","",2000)[1] console_log("INFO","user input: %s\n" % str(in_rslt)) if not selection: #self.speak("Sorry, no input detected") console_log("INFO", "No Input destected...\n") else: if int(selection) == 1: self.play_voicemail(voicemail) elif int(selection) == 2: vmid = voicemail.id voicemail.delete() #self.speak("Voicemail %s has been deleted" % str(vmid)) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-deleted.wav") self.playbeep() else: #self.speak("%s is an invalid option. Goodbye" % in_rslt) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodby.wav") self.playbeep() #--- LOGIN --------------- def login(self): if self.login_attempts > 5: #self.speak("Sorry, maximum number of login attempts exceeded") self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-abort.wav") return False self.login_attempts += 1 #----- Get a mailbox id -------------------------------------------------------- # TODO: only prompt if ${sip_authorized} is not "true") #thing2say = "Welcome to voicemail player. Please enter mailbox i d followed by the pound sign" console_log("INFO", "In VoiceMailPlayerIvr...\n") numtries=3 trynum=0 while trynum < numtries: self.playbeep() #time.sleep(2) self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-listen_new.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-enter_id.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/digits/8000/pound.wav") user_id = self.session.getDigits("",10,10,"*#","#",4000)[1] # 4 second delay #*dtmf_buf,buflen,maxdigits,terminators,char *terminator,int timeout #tempfile = self.make_tts_file(thing2say) #in_rslt = self.session.playAndGetDigits(1,10,3,4000,"*#",tempfile,"","","")[1] #min_digits,max_digits,max_tries,timeout,*terminators,*audio_files,*bad_input_audio_files,*dtmf_buf,*digits_regex if user_id: # if something entered console_log("INFO","Checking For Mailbox ID: %s\n" % str(user_id)) #--- check if mailbox id exists in current account --- self.userprof = None userprofs = UserProfile.objects.filter(account=self.account, mailbox=user_id) if not userprofs: #speakable = " ".join(in_rslt) #self.speak("Sorry, no mailbox with id: %s" % speakable, stream=False) console_log("INFO", "No Mailbox For: %s\n" % str(user_id)) self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-fail_auth.wav") #return False dont end because first attempt failed else: console_log("INFO", "Mailbox Exists For: %s\n" % str(user_id)) self.userprof = userprofs[0] break # go get password trynum=trynum+1 #----- if after numtries we still dont have a valid id, exit ----- if not user_id: #self.speak("You did not enter anything. Goodbye") #time.sleep(1) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodbye.wav") time.sleep(1) console_log("INFO", "You Did NOT Enter Anything...\n") return False #----- Get a Password ------------------------------- #prompt them to enter password #thing2say = "Please enter mailbox password followed by the pound sign" self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-enter_pass.wav") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/digits/8000/pound.wav") in_passwd = self.session.getDigits("",10,10,"*#","#",4000)[1] #tempfile = self.make_tts_file(thing2say) #in_rslt = self.session.playAndGetDigits(1,10,3,4000,"*#",tempfile,"", "","")[1] console_log("INFO","Checking Password: %s\n" % str(in_passwd)) if not in_passwd: #self.speak("You did not enter anything. Goodbye", stream=False) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-choose_greeting_fail.wav") return False # no password entered, goodby if not self.userprof.get_vm_password() == in_passwd: #speakable = " ".join(in_rslt) #self.speak("Sorry %s is not the correct password" % speakable, stream=False) self.playbeep() self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/conference/8000/conf-bad-pin.wav") return self.login() return True #----- VOICEMAIL RECORDER ---------------------------------------------------- class VoicemailRecorderIvr(VoicemailIvr): def __init__(self, session): super(VoicemailRecorderIvr, self).__init__(session) def main(self): console_log("INFO", "Voicemail recorder starting ..\n") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-record_message.wav") #self.speak("Welcome to voicemail recorder.") #self.speak("Please start speaking after the beep. " # "Press any key when finished. ") self.playbeep() # if there is no userprofile specified, we are going to # drop the voicemail into _each_ account admin's vm box self.admin = None if not self.userprofile: # choose the first account admin self.admin = self.account.admins.all()[0] voicemail = Voicemail(uuid=self.uuid, account=self.account, userprofile=self.admin) voicemail.save() else: voicemail = Voicemail(uuid=self.uuid, account=self.account, userprofile=self.userprofile) voicemail.save() vm_path = voicemail.get_path() max_len = 600 # 10 mins silence_threshold = 500 silence_secs = 5 self.session.recordFile(vm_path, max_len, silence_threshold, silence_secs) # TODO: allow them to listen, re-record # check asterisk vmail features console_log("INFO", "Voicemail has been recorded ..\n") #self.speak("Thank You. Your voicemail has been recorded. Goodbye") self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodbye.wav") # make sure its non empty, if so, just delete it and # skip the email notifications if voicemail.get_audio_length() == 0: console_log("INFO", "voicemail audio is empty, deleting\n") voicemail.delete() return # If account-wide, copy it to all _other_ admins mailboxes if not self.userprofile: admins = self.account.admins.all() for otheradmin in admins: if otheradmin == self.admin: # skip the 1st admin we used earlier, already has vm continue voicemail_copy = Voicemail(uuid=self.uuid, account=self.account, userprofile=otheradmin) voicemail_copy.save() # copy actual file voicemail.copy_audio(voicemail_copy.get_path()) # TODO: add a direct link back to the webserver which displays all # details on the voicemail. currently links back to homepage. # use this approach until hangup hook works ... but will this code # get called if user hangs up abruptly? so far in testing, seems # to work. console_log("INFO","sending email, session: %s\n" % str(self.session)) caller_id_number = self.session.getVariable("caller_id_number") caller_id_name = self.session.getVariable("caller_id_name") login_link = ('login' % (self.account.server.fqdn, self.account.server.http_port)) msg_body = ("You have received a new voicemail (id=%s) " "from %s (%s). Please %s to listen to your message." % (voicemail.id, caller_id_number, caller_id_name, login_link)) # if a mailbox (web user) was explicitly specified, use email # associated with that web user. otherwise, send a notice # to all account admins if self.userprofile: recipients = [self.userprofile.user.email] else: admins = self.account.admins.all() recipients = [x.user.email for x in admins] mailutil.acct_send(recipients=recipients, subject="New voicemail: %s" % voicemail.id, msg_body=msg_body, account=self.account) console_log("INFO","sent email, session: %s\n" % str(self.session)) #self.session.streamFile("/usr/local/freeswitch/sounds/en/us/callie/voicemail/8000/vm-goodbye.wav") # TODO: run other voicemail triggers (listen to events) def handler(uuid): if not uuid: console_log("info", "\nNo uuid given\n") return session = PySession(uuid) try: vmaction = session.getVariable("vmaction") if vmaction == "play": #console_log("INFO", "Jumping to VoiceMailPlayerIvr...\n") vmplayer = VoicemailPlayerIvr(session) vmplayer.main() elif vmaction == "record": #console_log("INFO", "Jumping to VoiceMailRecorderIvr...\n") vmrecorder = VoicemailRecorderIvr(session) vmrecorder.main() else: console_log("error", "Invalid voicemail action: %s\n" % vmaction) #session.set_tts_parms("cepstral", "william") #session.speak("Sorry, the voicemail system had an error. " # "Error code 101") except Exception, e: console_log("error", "Error running voicemail IVR: %s\n" % e) #session.set_tts_parms("cepstral", "william") #session.speak("Sorry, the voicemail system had an error. " # "Error code 102")