"""
WikiPBX web GUI front-end for FreeSWITCH <www.freeswitch.org>
Copyright (C) 2007, Branch Cut <www.branchcut.com>
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 = ('<a href="http://%s:%s">login</a>' %
(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")