|
|
Zeile 91: |
Zeile 91: |
|
| |
|
| === File: ''/usr/lib/capisuite/incoming_adv.py'' === | | === File: ''/usr/lib/capisuite/incoming_adv.py'' === |
| <pre>
| | [[incoming_adv.py|Hier]] ist das geänderte File. |
| # incoming_adv.py - advanced incoming script for capisuite
| |
| # --------------------------------------------------------
| |
| # copyright : (c) 2007 by Neobiker
| |
| #
| |
| # original script:
| |
| # copyright : (C) 2002 by Gernot Hillier
| |
| # email : gernot@hillier.de
| |
| # version : $Revision: 1.9.2.1 $
| |
| #
| |
| # This program is free software; you can redistribute it and/or modify
| |
| # it under the terms of the GNU General Public License as published by
| |
| # the Free Software Foundation; either version 2 of the License, or
| |
| # (at your option) any later version.
| |
| #
| |
| | |
| # general imports
| |
| import datetime,time,os,re,string,pwd
| |
| # CapiSuite imports
| |
| import capisuite,cs_helpers
| |
| | |
| # @brief check if user program date fits actual date
| |
| #
| |
| # @param pdate user program date
| |
| # @param adate actual date
| |
| | |
| def check_date (pdate,adate):
| |
| """check_date() check if actual date fits user program date"""
| |
| if pdate == '*':
| |
| return True
| |
| # set day/month/year from actual date if field is not defined
| |
| idate=pdate.split('.')
| |
| pdate=adate[:]
| |
| # set pdate fields day/month/year as defined in user program
| |
| for i in range(len(idate)):
| |
| if idate[i] and idate[i] != '*': pdate[i] = int(idate[i])
| |
| if pdate == adate:
| |
| if adv_debug:
| |
| print "check_date(): " , pdate , " / " , adate
| |
| return True
| |
| return False
| |
| | |
| # @brief check if date is listed in date section
| |
| #
| |
| # @param dsect date section list of dates
| |
| | |
| def check_date_section (dsect,adate):
| |
| """check_date_section () check if date is listed in date section"""
| |
| for i in range(len(config.items(dsect))):
| |
| for pdate in config.items(dsect)[i][1].split(','):
| |
| if check_date(pdate,adate):
| |
| if adv_debug:
| |
| print "check_date_Section(): found"
| |
| return True
| |
| return False
| |
| | |
| # @brief check if actual time fits user program time interval
| |
| #
| |
| # @param ptime program time intervall
| |
| # @param atime actual time
| |
| | |
| def prog_time (ptime,atime):
| |
| """prog_time() check if actual time fits user program time interval"""
| |
| if ptime == '*':
| |
| return True
| |
| # From: time intervall start
| |
| f0=ptime.split('-')[0] + ':00'
| |
| f=[int(f0.split(':')[0]), int(f0.split(':')[1])]
| |
| # To: time intervall end
| |
| t0=ptime.split('-')[1] + ':00'
| |
| t=[int(t0.split(':')[0]), int(t0.split(':')[1])]
| |
| # actual time is between From - To Intervall?
| |
| if adv_debug:
| |
| print "Time test: ", f, " <= ", atime, " <= ", t, " ?"
| |
| # 1.st test: f < t (means: t < 23:59)
| |
| # 2.nd test: f > t (means: t >= 00:00 -> on next day!)
| |
| if f < t:
| |
| return f <= atime <= t
| |
| else:
| |
| return not (t <= atime <= f)
| |
| | |
| # @brief check if weekday is listed in user program
| |
| #
| |
| # @param pwday program weekday
| |
| # @param wday actual weekday
| |
| | |
| def prog_wday (pwday,wday):
| |
| """prog_wday() check if weekday is listed in user program"""
| |
| if pwday == '*':
| |
| return True
| |
| wd={'MO': 0, 'DI': 1, 'MI': 2, 'DO': 3, 'FR': 4, 'SA': 5, 'SO': 6, \
| |
| 'TU': 1, 'WE': 2, 'TH': 3, 'SU': 6}
| |
| return wday==wd[pwday.upper()]
| |
| | |
| # @brief check if call_from is listed in callers section
| |
| #
| |
| # @param callers list of numbers or sections
| |
| | |
| def check_caller_section (csect):
| |
| """check_caller_section () check if call_from is listed in callers section"""
| |
| for i in range(len(config.items(csect))):
| |
| for j in config.items(csect)[i][1].split(','):
| |
| if call_from == re.sub('[\s+()-]','',j):
| |
| return True
| |
| return False
| |
| | |
| # @brief check if call_from is listed in callers list/section
| |
| #
| |
| # @param callers list of numbers or sections
| |
| | |
| def check_caller (callers):
| |
| """prog_caller () check if caller_from matches caller entries/section"""
| |
| if callers == '*':
| |
| return True
| |
| for i in range(len(callers.split(','))):
| |
| pcaller=re.sub('[\s+()-]','',callers.split(',')[i])
| |
| if pcaller in config.sections():
| |
| if check_caller_section(pcaller):
| |
| return True
| |
| elif call_from == pcaller:
| |
| return True
| |
| return False
| |
| | |
| # @brief check if given user program is active
| |
| #
| |
| # Check if Date/Time/Weekday fits actual date/time
| |
| # to see if user program is activ
| |
| #
| |
| # @param dates program dates
| |
| # @param times program time intervals
| |
| # @param wdays program week days
| |
| # @param d actual date/time
| |
| | |
| def prog_active (dates, times, wdays, d):
| |
| """prog_active() check if given user program is active"""
| |
| #
| |
| # check the dates in user program
| |
| found=False
| |
| for i in range(len(dates.split(','))):
| |
| pdate=dates.split(',')[i]
| |
| if pdate in config.sections():
| |
| if check_date_section(pdate,[d.day, d.month, d.year]):
| |
| found=True
| |
| break
| |
| elif check_date(pdate,[d.day, d.month, d.year]):
| |
| found=True
| |
| break
| |
| # date didn't fit
| |
| if not found: return False
| |
| #
| |
| # check the times in user program
| |
| found=False
| |
| for i in range(len(times.split(','))):
| |
| ptime=times.split(',')[i]
| |
| if prog_time(ptime,[d.hour, d.minute]):
| |
| found=True
| |
| break
| |
| # time intervall didn't fit
| |
| if not found: return False
| |
| #
| |
| # check the weekdays in user program
| |
| found=False
| |
| for i in range(len(wdays.split(','))):
| |
| pwday=wdays.split(',')[i]
| |
| if prog_wday(pwday,d.weekday()):
| |
| return True
| |
| #
| |
| # weekdays didn't fit
| |
| return False
| |
| | |
| # @brief read user specific program for vbox
| |
| # --- prog[dates, times, weekdays, message, delay, length, callers] ---
| |
| #
| |
| # It will search for a valid user program (prog#) in the user section
| |
| # and reads corresponding definitions for
| |
| # - delay the delay of vbox activation
| |
| # - message the specific message to play
| |
| #
| |
| # @param (user-)section in config file to read
| |
| # @return True/False if valid programm found or not
| |
| # @user_prog['delay': xx, 'message': yy]
| |
| | |
| def read_prog (section):
| |
| """read_prog(section) read user specific program for vbox"""
| |
| prog="prog1"
| |
| d=datetime.datetime.now()
| |
| i=1
| |
| while config.has_option(section,prog):
| |
| prog="prog"+str(i)
| |
| # p[dates, times, weekdays, message, delay, length, callers]
| |
| p=config.get(section,prog).split()
| |
| # check program dates/times/weekdays
| |
| if prog_active(p[0], p[1], p[2] ,d):
| |
| if adv_debug:
| |
| print "prog active: "+prog+" ("+section+")"
| |
| if check_caller(re.sub('[\s+()-]','',p[6])):
| |
| user_prog['user']=section
| |
| user_prog['prog']=i
| |
| user_prog['dates']=p[0]
| |
| user_prog['times']=p[1]
| |
| user_prog['wdays']=p[2]
| |
| user_prog['message']=p[3]
| |
| user_prog['delay']=p[4]
| |
| user_prog['length']=p[5]
| |
| user_prog['callers']=p[6]
| |
| if adv_debug:
| |
| print "checked: caller("+call_from+") in ", p[6]
| |
| print user_prog
| |
| return True
| |
| i=i+1
| |
| return False
| |
| | |
| # @brief main function called by CapiSuite when an incoming call is received
| |
| #
| |
| # It will decide if this call should be accepted, with which service and for
| |
| # which user. The real call handling is done in faxIncoming and voiceIncoming.
| |
| #
| |
| # @param call reference to the call. Needed by all capisuite functions
| |
| # @param service one of SERVICE_FAXG3, SERVICE_VOICE, SERVICE_OTHER
| |
| # @param call_from string containing the number of the calling party
| |
| # @param call_to string containing the number of the called party
| |
| | |
| def callIncoming(call,service,call_from,call_to):
| |
| # read sections in config file
| |
| try:
| |
| config=cs_helpers.readConfig()
| |
| userlist=config.sections()
| |
| userlist.remove('GLOBAL')
| |
| user_prog={}
| |
| # debug messages for adv. features
| |
| adv_debug=False
| |
| # search for call_to in the user sections
| |
| curr_user=""
| |
| for u in userlist:
| |
| if config.has_option(u,'voice_numbers'):
| |
| numbers=config.get(u,'voice_numbers')
| |
| if (call_to in numbers.split(',') or numbers=="*"):
| |
| if (service==capisuite.SERVICE_VOICE):
| |
| curr_user=u
| |
| curr_service=capisuite.SERVICE_VOICE
| |
| break
| |
| if (service==capisuite.SERVICE_FAXG3):
| |
| curr_user=u
| |
| curr_service=capisuite.SERVICE_FAXG3
| |
| break
| |
| | |
| if config.has_option(u,'fax_numbers'):
| |
| numbers=config.get(u,'fax_numbers')
| |
| if (call_to in numbers.split(',') or numbers=="*"):
| |
| if (service in (capisuite.SERVICE_FAXG3,capisuite.SERVICE_VOICE)):
| |
| curr_user=u
| |
| curr_service=capisuite.SERVICE_FAXG3
| |
| break
| |
| | |
| except IOError,e:
| |
| capisuite.error("Error occured during config file reading: "+e+" Disconnecting...")
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| # answer the call with the right service
| |
| if (curr_user==""):
| |
| capisuite.log("call from "+call_from+" to "+call_to+" ignoring",1,call)
| |
| capisuite.reject(call,1)
| |
| return
| |
| try:
| |
| if (curr_service==capisuite.SERVICE_VOICE):
| |
| delay=cs_helpers.getOption(config,curr_user,"voice_delay")
| |
| active_user_prog=read_prog(curr_user)
| |
| if active_user_prog:
| |
| delay=user_prog['delay']
| |
| if (delay==None):
| |
| capisuite.error("voice_delay not found for user "+curr_user+"! -> rejecting call")
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| capisuite.log("call from "+call_from+" to "+call_to+" for "+curr_user+" connecting with voice",1,call)
| |
| capisuite.connect_voice(call,int(delay))
| |
| voiceIncoming(call,call_from,call_to,curr_user,config)
| |
| elif (curr_service==capisuite.SERVICE_FAXG3):
| |
| faxIncoming(call,call_from,call_to,curr_user,config,0)
| |
| except capisuite.CallGoneError: # catch exceptions from connect_*
| |
| (cause,causeB3)=capisuite.disconnect(call)
| |
| capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| |
| | |
| # @brief called by callIncoming when an incoming fax call is received
| |
| #
| |
| # @param call reference to the call. Needed by all capisuite functions
| |
| # @param call_from string containing the number of the calling party
| |
| # @param call_to string containing the number of the called party
| |
| # @param curr_user name of the user who is responsible for this
| |
| # @param config ConfigParser instance holding the config data
| |
| # @param already_connected 1 if we're already connected (that means we must switch to fax mode)
| |
| def faxIncoming(call,call_from,call_to,curr_user,config,already_connected):
| |
| try:
| |
| udir=cs_helpers.getOption(config,"","fax_user_dir")
| |
| if (udir==None):
| |
| capisuite.error("global option fax_user_dir not found! -> rejecting call")
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| udir=os.path.join(udir,curr_user)+"/"
| |
| if (not os.access(udir,os.F_OK)):
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.mkdir(udir,0700)
| |
| os.chown(udir,userdata[2],userdata[3])
| |
| if (not os.access(udir+"received/",os.F_OK)):
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.mkdir(udir+"received/",0700)
| |
| os.chown(udir+"received/",userdata[2],userdata[3])
| |
| except KeyError:
| |
| capisuite.error("user "+curr_user+" is not a valid system user. Disconnecting",call)
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| filename="" # assure the variable is defined...
| |
| try:
| |
| stationID=cs_helpers.getOption(config,curr_user,"fax_stationID")
| |
| if (stationID==None):
| |
| capisuite.error("Warning: fax_stationID not found for user "+curr_user+" -> using empty string")
| |
| stationID=""
| |
| headline=cs_helpers.getOption(config,curr_user,"fax_headline","") # empty string is no problem here
| |
| capisuite.log("call from "+call_from+" to "+call_to+" for "+curr_user+" connecting with fax",1,call)
| |
| if (already_connected):
| |
| faxInfo=capisuite.switch_to_faxG3(call,stationID,headline)
| |
| else:
| |
| faxInfo=capisuite.connect_faxG3(call,stationID,headline,0)
| |
| if (faxInfo!=None and faxInfo[3]==1):
| |
| faxFormat="cff" # color fax
| |
| else:
| |
| faxFormat="sff" # normal b&w fax
| |
| filename=cs_helpers.uniqueName(udir+"received/","fax",faxFormat)
| |
| capisuite.fax_receive(call,filename)
| |
| (cause,causeB3)=capisuite.disconnect(call)
| |
| capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| |
| | |
| except capisuite.CallGoneError: # catch this here to get the cause info in the mail
| |
| (cause,causeB3)=capisuite.disconnect(call)
| |
| capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| |
| | |
| if (os.access(filename,os.R_OK)):
| |
| cs_helpers.writeDescription(filename,
| |
| "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\""
| |
| +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3))
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.chmod(filename,0600)
| |
| os.chown(filename,userdata[2],userdata[3])
| |
| os.chmod(filename[:-3]+"txt",0600)
| |
| os.chown(filename[:-3]+"txt",userdata[2],userdata[3])
| |
| | |
| fromaddress=cs_helpers.getOption(config,curr_user,"fax_email_from","")
| |
| if (fromaddress==""):
| |
| fromaddress=curr_user
| |
| mailaddress=cs_helpers.getOption(config,curr_user,"fax_email","")
| |
| if (mailaddress==""):
| |
| mailaddress=curr_user
| |
| action=cs_helpers.getOption(config,curr_user,"fax_action","").lower()
| |
| if (action not in ("mailandsave","saveonly")):
| |
| capisuite.error("Warning: No valid fax_action definition found for user "+curr_user+" -> assuming SaveOnly")
| |
| action="saveonly"
| |
| if (action=="mailandsave"):
| |
| cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Fax received from "+call_from+" to "+call_to, faxFormat,
| |
| "You got a fax from "+call_from+" to "+call_to+"\nDate: "+time.ctime()+"\n\n"
| |
| +"See attached file.\nThe original file was saved to file://"+filename+"\n\n", filename)
| |
| | |
| # @brief called by callIncoming when an incoming voice call is received
| |
| #
| |
| # @param call reference to the call. Needed by all capisuite functions
| |
| # @param call_from string containing the number of the calling party
| |
| # @param call_to string containing the number of the called party
| |
| # @param curr_user name of the user who is responsible for this
| |
| # @param config ConfigParser instance holding the config data
| |
| def voiceIncoming(call,call_from,call_to,curr_user,config):
| |
| try:
| |
| udir=cs_helpers.getOption(config,"","voice_user_dir")
| |
| if (udir==None):
| |
| capisuite.error("global option voice_user_dir not found! -> rejecting call")
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| udir=os.path.join(udir,curr_user)+"/"
| |
| if (not os.access(udir,os.F_OK)):
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.mkdir(udir,0700)
| |
| os.chown(udir,userdata[2],userdata[3])
| |
| if (not os.access(udir+"received/",os.F_OK)):
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.mkdir(udir+"received/",0700)
| |
| os.chown(udir+"received/",userdata[2],userdata[3])
| |
| except KeyError:
| |
| capisuite.error("user "+curr_user+" is not a valid system user. Disconnecting",call)
| |
| capisuite.reject(call,0x34A9)
| |
| return
| |
| filename=cs_helpers.uniqueName(udir+"received/","voice","la")
| |
| action=cs_helpers.getOption(config,curr_user,"voice_action","").lower()
| |
| if (action not in ("mailandsave","saveonly","none")):
| |
| capisuite.error("Warning: No valid voice_action definition found for user "+curr_user+" -> assuming SaveOnly")
| |
| action="saveonly"
| |
| try:
| |
| capisuite.enable_DTMF(call)
| |
| if not active_user_prog:
| |
| userannouncement=udir+cs_helpers.getOption(config,curr_user,"announcement","announcement.la")
| |
| else:
| |
| userannouncement=udir+user_prog['message']
| |
| pin=cs_helpers.getOption(config,curr_user,"pin","")
| |
| if (os.access(userannouncement,os.R_OK)):
| |
| capisuite.audio_send(call,userannouncement,1)
| |
| else:
| |
| if (call_to!="-"):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"anrufbeantworter-von.la"),1)
| |
| cs_helpers.sayNumber(call,call_to,curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-nachricht.la"),1)
| |
| | |
| if (action!="none"):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"),1)
| |
| length=cs_helpers.getOption(config,curr_user,"record_length","60")
| |
| silence_timeout=cs_helpers.getOption(config,curr_user,"record_silence_timeout","5")
| |
| capisuite.audio_receive(call,filename,int(length), int(silence_timeout),1)
| |
| | |
| dtmf_list=capisuite.read_DTMF(call,0)
| |
| if (dtmf_list=="X"):
| |
| if (os.access(filename,os.R_OK)):
| |
| os.unlink(filename)
| |
| faxIncoming(call,call_from,call_to,curr_user,config,1)
| |
| elif (dtmf_list!="" and pin!=""):
| |
| dtmf_list+=capisuite.read_DTMF(call,3) # wait 5 seconds for input
| |
| count=1
| |
| while (count<3 and pin!=dtmf_list): # try again if input was wrong
| |
| capisuite.log("wrong PIN entered...",1,call)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
| |
| dtmf_list=capisuite.read_DTMF(call,3)
| |
| count+=1
| |
| if (pin==dtmf_list):
| |
| if (os.access(filename,os.R_OK)):
| |
| os.unlink(filename)
| |
| capisuite.log("Starting remote inquiry...",1,call)
| |
| remoteInquiry(call,udir,curr_user,config)
| |
| | |
| (cause,causeB3)=capisuite.disconnect(call)
| |
| capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| |
| | |
| except capisuite.CallGoneError: # catch this here to get the cause info in the mail
| |
| (cause,causeB3)=capisuite.disconnect(call)
| |
| capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| |
| | |
| if (os.access(filename,os.R_OK)):
| |
| cs_helpers.writeDescription(filename,
| |
| "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\""
| |
| +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3))
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.chmod(filename,0600)
| |
| os.chown(filename,userdata[2],userdata[3])
| |
| os.chmod(filename[:-2]+"txt",0600)
| |
| os.chown(filename[:-2]+"txt",userdata[2],userdata[3])
| |
| | |
| fromaddress=cs_helpers.getOption(config,curr_user,"voice_email_from","")
| |
| if (fromaddress==""):
| |
| fromaddress=curr_user
| |
| mailaddress=cs_helpers.getOption(config,curr_user,"voice_email","")
| |
| if (mailaddress==""):
| |
| mailaddress=curr_user
| |
| if (action=="mailandsave"):
| |
| cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Voice call received from "+call_from+" to "+call_to, "la",
| |
| "You got a voice call from "+call_from+" to "+call_to+"\nDate: "+time.ctime()+"\n\n"
| |
| +"See attached file.\nThe original file was saved to file://"+filename+"\n\n", filename)
| |
| | |
| | |
| # @brief remote inquiry function (uses german wave snippets!)
| |
| #
| |
| # commands for remote inquiry
| |
| # delete message - 1
| |
| # next message - 4
| |
| # last message - 5
| |
| # repeat current message - 6
| |
| #
| |
| # @param call reference to the call. Needed by all capisuite functions
| |
| # @param userdir spool_dir of the current_user
| |
| # @param curr_user name of the user who is responsible for this
| |
| # @param config ConfigParser instance holding the config data
| |
| def remoteInquiry(call,userdir,curr_user,config):
| |
| import time,fcntl,errno,os
| |
| # acquire lock
| |
| lockfile=open(userdir+"received/inquiry_lock","w")
| |
| try:
| |
| fcntl.lockf(lockfile,fcntl.LOCK_EX | fcntl.LOCK_NB) # only one inquiry at a time!
| |
| | |
| except IOError,err: # can't get the lock
| |
| if (err.errno in (errno.EACCES,errno.EAGAIN)):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fernabfrage-aktiv.la"))
| |
| lockfile.close()
| |
| return
| |
| | |
| try:
| |
| # read directory contents
| |
| messages=os.listdir(userdir+"received/")
| |
| messages=filter (lambda s: re.match("voice-.*\.la",s),messages) # only use voice-* files
| |
| messages=map(lambda s: int(re.match("voice-([0-9]+)\.la",s).group(1)),messages) # filter out numbers
| |
| messages.sort()
| |
| | |
| # read the number of the message heard last at the last inquiry
| |
| lastinquiry=-1
| |
| if (os.access(userdir+"received/last_inquiry",os.W_OK)):
| |
| lastfile=open(userdir+"received/last_inquiry","r")
| |
| lastinquiry=int(lastfile.readline())
| |
| lastfile.close()
| |
| | |
| # sort out old messages
| |
| oldmessages=[]
| |
| i=0
| |
| while (i<len(messages)):
| |
| if (messages[i]<=lastinquiry):
| |
| oldmessages.append(messages[i])
| |
| del messages[i]
| |
| else:
| |
| i+=1
| |
| | |
| cs_helpers.sayNumber(call,str(len(messages)),curr_user,config)
| |
| if (len(messages)==1):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
| |
| else:
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
| |
| | |
| # menu for record new announcement
| |
| cmd=""
| |
| while (cmd not in ("1","9")):
| |
| if (len(messages)+len(oldmessages)):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"zum-abhoeren-1.la"),1)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fuer-neue-ansage-9.la"),1)
| |
| cmd=capisuite.read_DTMF(call,0,1)
| |
| if (cmd=="9"):
| |
| newAnnouncement(call,userdir,curr_user,config)
| |
| return
| |
| | |
| # start inquiry
| |
| for curr_msgs in (messages,oldmessages):
| |
| cs_helpers.sayNumber(call,str(len(curr_msgs)),curr_user,config)
| |
| if (curr_msgs==messages):
| |
| if (len(curr_msgs)==1):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
| |
| else:
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
| |
| else:
| |
| if (len(curr_msgs)==1):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht.la"),1)
| |
| else:
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachrichten.la"),1)
| |
| | |
| i=0
| |
| while (i<len(curr_msgs)):
| |
| filename=userdir+"received/voice-"+str(curr_msgs[i])+".la"
| |
| descr=cs_helpers.readConfig(filename[:-2]+"txt")
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht.la"),1)
| |
| cs_helpers.sayNumber(call,str(i+1),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"von.la"),1)
| |
| cs_helpers.sayNumber(call,descr.get('GLOBAL','call_from'),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fuer.la"),1)
| |
| cs_helpers.sayNumber(call,descr.get('GLOBAL','call_to'),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"am.la"),1)
| |
| calltime=time.strptime(descr.get('GLOBAL','time'))
| |
| cs_helpers.sayNumber(call,str(calltime[2]),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
| |
| cs_helpers.sayNumber(call,str(calltime[1]),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"um.la"),1)
| |
| cs_helpers.sayNumber(call,str(calltime[3]),curr_user,config)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"uhr.la"),1)
| |
| cs_helpers.sayNumber(call,str(calltime[4]),curr_user,config)
| |
| capisuite.audio_send(call,filename,1)
| |
| cmd=""
| |
| while (cmd not in ("1","4","5","6")):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"erklaerung.la"),1)
| |
| cmd=capisuite.read_DTMF(call,0,1)
| |
| if (cmd=="1"):
| |
| os.remove(filename)
| |
| os.remove(filename[:-2]+"txt")
| |
| del curr_msgs[i]
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht-geloescht.la"))
| |
| elif (cmd=="4"):
| |
| if (curr_msgs[i]>lastinquiry):
| |
| lastinquiry=curr_msgs[i]
| |
| lastfile=open(userdir+"received/last_inquiry","w")
| |
| lastfile.write(str(curr_msgs[i])+"\n")
| |
| lastfile.close()
| |
| i+=1
| |
| elif (cmd=="5"):
| |
| i-=1
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"keine-weiteren-nachrichten.la"))
| |
| | |
| finally:
| |
| # unlock
| |
| fcntl.lockf(lockfile,fcntl.LOCK_UN)
| |
| lockfile.close()
| |
| os.unlink(userdir+"received/inquiry_lock")
| |
| | |
| # @brief remote inquiry: record new announcement (uses german wave snippets!)
| |
| #
| |
| # @param call reference to the call. Needed by all capisuite functions
| |
| # @param userdir spool_dir of the current_user
| |
| # @param curr_user name of the user who is responsible for this
| |
| # @param config ConfigParser instance holding the config data
| |
| def newAnnouncement(call,userdir,curr_user,config):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-neue-ansage-komplett.la"))
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
| |
| cmd=""
| |
| while (cmd!="1"):
| |
| capisuite.audio_receive(call,userdir+"announcement-tmp.la",60,3)
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-ansage-lautet.la"))
| |
| capisuite.audio_send(call,userdir+"announcement-tmp.la")
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"wenn-einverstanden-1.la"))
| |
| cmd=capisuite.read_DTMF(call,0,1)
| |
| if (cmd!="1"):
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-neue-ansage-kurz.la"))
| |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"))
| |
| userannouncement=userdir+cs_helpers.getOption(config,curr_user,"announcement","announcement.la")
| |
| os.rename(userdir+"announcement-tmp.la",userannouncement)
| |
| userdata=pwd.getpwnam(curr_user)
| |
| os.chown(userannouncement,userdata[2],userdata[3])
| |
| | |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"ansage-gespeichert.la"))
| |
| | |
| #
| |
| # History:
| |
| #
| |
| # $Log: incoming.py,v $
| |
| # Revision 1.9.2.1 2003/08/24 12:47:19 gernot
| |
| # - faxIncoming tried to reconnect when it was called after a switch from
| |
| # voice to fax mode, which lead to a call abort. Thx to Harald Jansen &
| |
| # Andreas Scholz for reporting!
| |
| #
| |
| # Revision 1.9 2003/06/27 07:51:09 gernot
| |
| # - replaced german umlaut in filename "nachricht-gelscht.la", can cause
| |
| # problems on Redhat, thx to Herbert Hübner for reporting
| |
| #
| |
| # Revision 1.8 2003/06/16 10:21:05 gernot
| |
| # - define filename in any case (thx to Axel Schneck for reporting and
| |
| # analyzing...)
| |
| #
| |
| # Revision 1.7 2003/05/25 13:38:30 gernot
| |
| # - support reception of color fax documents
| |
| #
| |
| # Revision 1.6 2003/04/10 21:29:51 gernot
| |
| # - support empty destination number for incoming calls correctly (austrian
| |
| # telecom does this (sic))
| |
| # - core now returns "-" instead of "??" for "no number available" (much nicer
| |
| # in my eyes)
| |
| # - new wave file used in remote inquiry for "unknown number"
| |
| #
| |
| # Revision 1.5 2003/03/20 09:12:42 gernot
| |
| # - error checking for reading of configuration improved, many options got
| |
| # optional, others produce senseful error messages now if not found,
| |
| # fixes bug# 531, thx to Dieter Pelzel for reporting
| |
| #
| |
| # Revision 1.4 2003/03/13 11:08:06 gernot
| |
| # - fix remote inquiry locking (should fix bug #534, but doesn't - anyway,
| |
| # this fix is definitely necessary)
| |
| # - stricter permissions of saved files and created dirs, fixes #544
| |
| # - add "file://" prefix to the path shown in the mails to the user
| |
| #
| |
| # Revision 1.3 2003/02/21 13:13:34 gernot
| |
| # - removed some debug output (oops...)
| |
| #
| |
| # Revision 1.2 2003/02/21 11:02:17 gernot
| |
| # - removed os.setuid() from incoming script
| |
| # -> fixes Bug #527
| |
| #
| |
| # Revision 1.1.1.1 2003/02/19 08:19:54 gernot
| |
| # initial checkin of 0.4
| |
| #
| |
| # Revision 1.11 2003/02/17 11:13:43 ghillie
| |
| # - remoteinquiry supports new and old messages now
| |
| #
| |
| # Revision 1.10 2003/02/03 14:50:08 ghillie
| |
| # - fixed small typo
| |
| #
| |
| # Revision 1.9 2003/01/31 16:32:41 ghillie
| |
| # - support "*" for "all numbers"
| |
| # - automatic switch voice->fax when SI says fax
| |
| #
| |
| # Revision 1.8 2003/01/31 11:24:41 ghillie
| |
| # - wrong user handling for more than one users fixed
| |
| # - creates user_dir/user and user_dir/user/received now separately as
| |
| # idle.py can also create user_dir/user now
| |
| #
| |
| # Revision 1.7 2003/01/27 21:57:54 ghillie
| |
| # - fax_numbers and voice_numbers may not exist (no fatal error any more)
| |
| # - accept missing email option
| |
| # - fixed typo
| |
| #
| |
| # Revision 1.6 2003/01/27 19:24:29 ghillie
| |
| # - updated to use new configuration files for fax & answering machine
| |
| #
| |
| # Revision 1.5 2003/01/19 12:03:27 ghillie
| |
| # - use capisuite log functions instead of stdout/stderr
| |
| #
| |
| # Revision 1.4 2003/01/17 15:09:49 ghillie
| |
| # - cs_helpers.sendMail was renamed to sendMIMEMail
| |
| #
| |
| # Revision 1.3 2003/01/16 12:58:34 ghillie
| |
| # - changed DTMF timeout for pin to 3 seconds
| |
| # - delete recorded wave if fax or remote inquiry is recognized
| |
| # - updates in remoteInquiry: added menu for recording own announcement
| |
| # - fixed some typos
| |
| # - remoteInquiry: delete description file together with call if requested
| |
| # - new function: newAnnouncement
| |
| #
| |
| # Revision 1.2 2003/01/15 15:55:12 ghillie
| |
| # - added exception handler in callIncoming
| |
| # - faxIncoming: small typo corrected
| |
| # - voiceIncoming & remoteInquiry: updated to new config file system
| |
| #
| |
| # Revision 1.1 2003/01/13 16:12:58 ghillie
| |
| # - renamed from incoming.pyin to incoming.py as all previously processed
| |
| # variables are moved to config and cs_helpers.pyin
| |
| #
| |
| # Revision 1.4 2002/12/18 14:34:56 ghillie
| |
| # - added some informational prints
| |
| # - accept voice calls to fax nr
| |
| #
| |
| # Revision 1.3 2002/12/16 15:04:51 ghillie
| |
| # - added missing path prefix to delete routing in remote inquiry
| |
| #
| |
| # Revision 1.2 2002/12/16 13:09:25 ghillie
| |
| # - added some comments about the conf_* vars
| |
| # - added conf_wavedir
| |
| # - added support for B3 cause now returned by disconnect()
| |
| # - corrected some dir entries to work in installed system
| |
| #
| |
| # Revision 1.1 2002/12/14 13:53:18 ghillie
| |
| # - idle.py and incoming.py are now auto-created from *.pyin
| |
| #
| |
| # Revision 1.4 2002/12/11 12:58:05 ghillie
| |
| # - read return value from disconnect()
| |
| # - added disconnect() to exception handler
| |
| #
| |
| # Revision 1.3 2002/12/09 15:18:35 ghillie
| |
| # - added disconnect() in exception handler
| |
| #
| |
| # Revision 1.2 2002/12/02 21:30:42 ghillie
| |
| # fixed some minor typos
| |
| #
| |
| # Revision 1.1 2002/12/02 21:15:55 ghillie
| |
| # - moved scripts to own directory
| |
| # - added remote-connect script to repository
| |
| #
| |
| # Revision 1.20 2002/12/02 20:59:44 ghillie
| |
| # another typo :-|
| |
| #
| |
| # Revision 1.19 2002/12/02 20:54:07 ghillie
| |
| # fixed small typo
| |
| #
| |
| # Revision 1.18 2002/12/02 16:51:32 ghillie
| |
| # nearly complete new script, supports answering machine, fax receiving and remote inquiry now
| |
| #
| |
| # Revision 1.17 2002/11/29 16:28:43 ghillie
| |
| # - updated syntax (connect_telephony -> connect_voice)
| |
| #
| |
| # Revision 1.16 2002/11/29 11:09:04 ghillie
| |
| # renamed CapiCom to CapiSuite (name conflict with MS crypto API :-( )
| |
| #
| |
| # Revision 1.15 2002/11/25 11:43:43 ghillie
| |
| # updated to new syntax
| |
| #
| |
| # Revision 1.14 2002/11/23 16:16:17 ghillie
| |
| # moved switch2fax after audio_receive()
| |
| #
| |
| # Revision 1.13 2002/11/22 15:48:58 ghillie
| |
| # renamed pcallcontrol module to capicom
| |
| #
| |
| # Revision 1.12 2002/11/22 15:02:39 ghillie
| |
| # - added automatic switch between speech and fax
| |
| # - some comments added
| |
| #
| |
| # Revision 1.11 2002/11/19 15:57:18 ghillie
| |
| # - Added missing throw() declarations
| |
| # - phew. Added error handling. All exceptions are caught now.
| |
| #
| |
| # Revision 1.10 2002/11/18 12:32:36 ghillie
| |
| # - callIncoming lives now in __main__, not necessarily in pcallcontrol any more
| |
| # - added some comments and header
| |
| #
| |
| </pre>
| |
|
| |
|
| === File: ''/usr/lib/capisuite/idle_adv.py'' === | | === File: ''/usr/lib/capisuite/idle_adv.py'' === |