|
|
(34 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
Zeile 1: |
Zeile 1: |
| | [[Neobiker%27s_Wiki:Portal|Zurück zum Portal]] |
| | |
| == Capisuite Erweiterung == | | == Capisuite Erweiterung == |
|
| |
|
| Bei der Umstellung von VBox unter Debian Sarge auf Capisuite unter Etch habe ich schmerzlich die Möglichkeit der individuellen Programmierung der Anrufbeantworter vermisst. Nachdem ich keine verbesserten ''Incoming.py'' Files im Web gefunden habe, habe ich auf die schnelle Python gelernt und die fehlende Funktion selbst implementiert. | | Bei der Umstellung von VBox unter Debian Sarge auf Capisuite unter Etch habe ich schmerzlich die Möglichkeit der individuellen '''Programmierung des Anrufbeantworters''' vermisst. Nachdem ich keine verbesserten ''incoming.py'' Files im Web gefunden habe, habe ich auf die schnelle Python gelernt und die fehlende Funktion selbst implementiert. |
| | |
| | '''Individuelle Programmierung''' |
| | |
| | In den Konfigfiles können Programme hinterlegt werden, die in Abhängigkeit von Zeit, Datum oder Telefonnummern (des Anrufers oder der Zielnummer) unterschiedlich reagieren. Ich nutze z.B. je eine eigene MSN für Privates, Geschäftliches und Fax. Die Geschäftsnummer klingelt nur Mo-Fr zw. 8:30 und 17:00, sonst aktiviert sich direkt der AB mit einer geschäftlichen Ansage. Wochenenden, Feiertage und Geburtstage sind zusätzlich hinterlegt. Familie und Freunde können uns Abends z.B. länger erreichen, als unbekannte Anrufer, die Nachrichten werden auch länger aufgezeichnet. Die Möglichkeiten sind nahezu beliebig. |
|
| |
|
| '''Programmierung''' | | * Die ''Programme'' werden '''fortlaufend (!)''' nummeriert, beginnend bei '''''prog1''''' |
| * Die Programme werden '''fortlaufend (!)''' nummeriert, beginnend bei '''''prog1'''''
| | * Das erste Programm ''prog1 ... progX'' das ''match'ed'' (Zeit, Datum, etc.) wird verwendet, deshalb ist die '''Reihenfolge''' relevant! |
| * Das erste Programm ''prog1 ... progX'' das ''match'ed'' wird verwendet, deshalb ist die '''Reihenfolge''' relevant! | | * Die Einträge '''dates''' und '''group''' können als ''eigene Section'' im Konfigfile definiert werden (siehe holiday, family, friends) |
| * Die Einträge '''dates''' und '''group''' können als ''eigene Section'' definiert werden (siehe holiday, family, friends) | |
| * Die Telefonnummern müssen so definiert sein, wie sie im Logfile (''/var/log/capisuite.log'') erscheinen, d.h. üblicherweise '''0911 12345678''' (nicht: +49 (911) 12345678). | | * Die Telefonnummern müssen so definiert sein, wie sie im Logfile (''/var/log/capisuite.log'') erscheinen, d.h. üblicherweise '''0911 12345678''' (nicht: +49 (911) 12345678). |
| | * Es kann ein eigenes Telefonbuch verwendet werden. Einträge darin werden mit Namen gelistet (Email/Fax Email enthält den Namen und die Nummer) |
|
| |
|
|
| |
|
Zeile 22: |
Zeile 28: |
|
| |
|
| [priv] | | [priv] |
| voice_numbers="20" | | voice_numbers="12345678" |
| announcement="ab_priv.la" | | announcement="ab_priv.la" |
| voice_action="MailAndSave" | | voice_action="MailAndSave" |
Zeile 28: |
Zeile 34: |
| record_length="90" | | record_length="90" |
| voice_email_from="ab@neobiker.de" | | voice_email_from="ab@neobiker.de" |
| voice_email="Anrufbeantworter <ab@neobiker.de>" | | voice_email="Anrufbeantworter (Priv) <ab@neobiker.de>" |
| pin="1111" | | pin="1111" |
| # ----- vbox programming: | | # ----- vbox programming: |
Zeile 38: |
Zeile 44: |
|
| |
|
| [buis] | | [buis] |
| voice_numbers="23" | | voice_numbers="22233345" |
| announcement="ab_buis.la" | | announcement="ab_buis.la" |
| voice_action="MailAndSave" | | voice_action="MailAndSave" |
| voice_delay="10" | | voice_delay="10" |
| record_length="60" | | record_length="60" |
| voice_email_from="Anrufbeantworter <dr@friedrichnet.de>" | | voice_email_from="Anrufbeantworter (Buis) <ab@neobiker.de>" |
| voice_email="ab@friedrichnet.de" | | voice_email="ab@neobiker.de" |
| pin="2222" | | pin="2222" |
| # ----- vbox programming: | | # ----- vbox programming: |
Zeile 60: |
Zeile 66: |
| Sonstige=1.1.,6.1.,1.5.,3.10.,1.11. | | Sonstige=1.1.,6.1.,1.5.,3.10.,1.11. |
| Birthdays=19.5. | | Birthdays=19.5. |
| | </pre> |
| | |
| | Zusätzlich habe ich ein '''Telefonbuch''' definiert, in welchem auch die verschiedenen ''Gruppen'' (s.o. das Konfigfile / AB-Programme) definiert sind (Familie, Freunde, ...): ''/etc/capisuit/phonebook.conf'' |
| | <pre> |
| | [GLOBAL] |
| | Privat = 123456 |
| | Geschäft = 123457 |
| | Fax = 123458 |
|
| |
|
| [family] | | [family] |
Zeile 67: |
Zeile 81: |
| [friends] | | [friends] |
| Karl=12345,017134566789 | | Karl=12345,017134566789 |
| Peter=0170123456 | | Peter=0170123456, 0911 123412 |
| | |
| | [others] |
| | Arzt = 12345 |
| | Werkstatt = 12346789 |
| | Buero = 123 345 567 |
| | </pre> |
| | Telefonnummern, welche nicht im Telefonbuch stehen, werden per '''online reverse lookup''' unter ''www.dasoertliche.de'' nachgeschlagen und sofern gefunden unter ''/var/cache/tbident/phonebook.cache'' gespeichert. |
| | |
| | Der Anrufbeantworter (Fax dito) sendet mir eine '''Email''' mit einer Wav-Datei (oder PDF bei Fax) und den wichtigsten Info's: |
| | <pre> |
| | From: Anrufbeantworter (Priv) <ab@neobiker.de> |
| | To: ab@neobiker.de |
| | Subject: Nachricht von Unbekannt fuer Privat |
| | Anlage: voice-184.wav |
| | |
| | Anrufer: Unbekannt (0911987654321) |
| | |
| | Laenge: 31 Sek. |
| | Datum: Di 11 Sep 2007 13:57:43 CEST |
| | Nummer: Privat (123456) |
| | |
| | Siehe Anhang. |
| | Das File wurde gespeichert unter: /var/spool/capisuite/users/ab/received/voice-184.la |
| </pre> | | </pre> |
| | |
| | === Downloads === |
| | [http://www.neobiker.de/ftp/pub/isdn/ Download ISDN Files] |
|
| |
|
| == Erweiterte Scripts == | | == Erweiterte Scripts == |
Zeile 75: |
Zeile 115: |
| * incoming_adv.py | | * incoming_adv.py |
| * idle_adv.py | | * idle_adv.py |
| erstellt. Diese müssen in ''/etc/capisuite/capisuite.conf'' aktiviert werden. | | * tbident.sh |
| | erstellt. Die ersten beiden werden in ''/etc/capisuite/capisuite.conf'' aktiviert, das letzte zur Telefonbuch-Identifikation (tbident.sh) muss im Standardpfad installiert werden (z.B. unter ''/usr/bin/tbident.sh''). |
| | |
| | Die Scripts sind für eine Deutsche Ausgabe optimiert worden. Es wird einmal setlocale(de_DE) verwendet. Deshalb sind auf dem System die deutschen locales notwendig, diese können unter Debian mit '''dpkg-reconfigure locales''' erzeugt werden. |
| | |
| | '''Hinweis''': Die Scripts müssen zuerst compiliert werden! |
|
| |
|
| Folgender Batch compiliert die Python Scripts anschliessend:
| | Folgendes Script compiliert die CapiSuite Python Scripts: |
| <pre> | | <pre> |
| #!/bin/sh | | #!/bin/sh |
| PYTHON=python2.3 | | PYTHON=python2.4 |
| DIRLIST=" /usr/lib/capisuite " | | DIRLIST=" /usr/lib/capisuite " |
| for i in $DIRLIST ; do | | for i in $DIRLIST ; do |
Zeile 89: |
Zeile 134: |
|
| |
|
| === File: ''/usr/lib/capisuite/incoming_adv.py'' === | | === File: ''/usr/lib/capisuite/incoming_adv.py'' === |
| | [[incoming_adv|Hier]] ist das erweiterte File ''/usr/lib/capisuite/incoming_adv.py''. |
| | |
| | === File: ''/usr/lib/capisuite/idle_adv.py'' === |
| | Das ''idle.py'' File benötigt eine kleine Änderung (ganz unten im Script, mit '+' markiert), damit die neuen Sections nicht zu einer Fehlermeldung (über nicht existierenden System-User) führen. |
| | |
| <pre> | | <pre> |
| # incoming_adv.py - advanced incoming script for capisuite | | # idle_adv.py - default script for capisuite |
| # -------------------------------------------------------- | | # --------------------------------------------- |
| # copyright : (c) 2007 by Neobiker | | # copyright : (C) 2007 neobiker |
| | # Version : 1.1 |
| | # Date : 03.01.2007 |
| # | | # |
| # original script: | | # original script: |
| # copyright : (C) 2002 by Gernot Hillier | | # copyright : (C) 2002 by Gernot Hillier |
| # email : gernot@hillier.de | | # email : gernot@hillier.de |
| # version : $Revision: 1.9.2.1 $ | | # version : Revision: 1.8.2.2 |
| # | | # |
| # This program is free software; you can redistribute it and/or modify | | # This program is free software; you can redistribute it and/or modify |
Zeile 105: |
Zeile 157: |
| # | | # |
|
| |
|
| # general imports
| | import os,re,time,pwd,fcntl |
| import datetime,time,os,re,string,pwd | | # capisuite stuff |
| # CapiSuite imports | |
| import capisuite,cs_helpers | | import capisuite,cs_helpers |
|
| |
|
| # @brief check if user program date fits actual date
| | def idle(capi): |
| #
| | config=cs_helpers.readConfig() |
| # @param pdate user program date
| | spool=cs_helpers.getOption(config,"","spool_dir") |
| # @param adate actual date
| | if (spool==None): |
| | capisuite.error("global option spool_dir not found.") |
| | return |
|
| |
|
| def check_date (pdate,adate):
| | done=os.path.join(spool,"done")+"/" |
| """check_date() check if actual date fits user program date"""
| | failed=os.path.join(spool,"failed")+"/" |
| 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
| | if (not os.access(done,os.W_OK) or not os.access(failed,os.W_OK)): |
| #
| | capisuite.error("Can't read/write to the necessary spool dirs") |
| # @param dsect date section list of dates
| | return |
|
| |
|
| def check_date_section (dsect,adate):
| | userlist=config.sections() |
| """check_date_section () check if date is listed in date section"""
| | userlist.remove('GLOBAL') |
| 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 | | for user in userlist: # search in all user-specified sendq's |
| #
| | + # neobiker: skip none user sections |
| # @param ptime program time intervall
| | + if not (config.has_option(user,'voice_numbers') or config.has_option(user,'fax_numbers')): |
| # @param atime actual time
| | + continue |
| | userdata=pwd.getpwnam(user) |
| | ... |
| | </pre> |
|
| |
|
| def prog_time (ptime,atime):
| | === File: ''/usr/bin/tbident.sh'' === |
| """prog_time() check if actual time fits user program time interval"""
| | Das Skript '''tbident.sh''' sucht mit '''lynx''' (muss installiert sein!) eine Telefonnummer online unter ''www.dasoertliche.de'' und cached jede Suche unter ''/var/cache/tbident/phonebook'': |
| 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 | | File ''/usr/bin/'''''tbident.sh''': |
| | <pre>#!/bin/sh |
| | # tbident.sh |
| # | | # |
| # @param pwday program weekday | | # Rückwärtssuche Telefonnummer -> Eintrag im Telefonbuch |
| # @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 | | # Usage: tbident.sh "09123 34 45 67" |
| | | # Ursprung: altes tbident.sh des VDR-Portal's |
| 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 | | # Gefundene Telefonnummern werden gecached unter: |
| # to see if user program is activ
| | # >>> /var/cache/tbident/phonebook <<< |
| # | | # |
| # @param dates program dates | | # $Log: tbident.sh,v $ |
| # @param times program time intervals
| | # Revision 1.4 2009/07/05 11:33:27 root |
| # @param wdays program week days
| | # added autom. updates of (grep) search parameters |
| # @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 | | # Revision 1.3 2008/06/05 11:35:00 root |
| # and reads corresponding definitions for | | # *** empty log message *** |
| # - delay the delay of vbox activation
| |
| # - message the specific message to play
| |
| # | | # |
| # @param (user-)section in config file to read | | # Revision 1.2 2008/06/05 11:33:27 root |
| # @return True/False if valid programm found or not
| | # updated html syntax |
| # @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 | | # Revision 1.1 2007/09/09 15:50:43 root |
| # which user. The real call handling is done in faxIncoming and voiceIncoming. | | # Initial revision |
| # | | # |
| # @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):
| | set -e |
| # 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'):
| | NR="$@" |
| numbers=config.get(u,'fax_numbers')
| | NUMMER=`echo "$NR" | tr -d ' ()' | sed -e "s/^\+49//"` |
| if (call_to in numbers.split(',') or numbers=="*"):
| | NAME="" |
| if (service in (capisuite.SERVICE_FAXG3,capisuite.SERVICE_VOICE)):
| | DETAILS="" |
| curr_user=u
| |
| curr_service=capisuite.SERVICE_FAXG3
| |
| break
| |
|
| |
|
| except IOError,e:
| | URL="http://www.dasoertliche.de/?form_name=search_inv&action=1&&ph=" |
| capisuite.error("Error occured during config file reading: "+e+" Disconnecting...")
| | CONTEXT='Trefferliste' |
| 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
| | CACHE=/var/cache/tbident/phonebook |
| #
| | TMPFILE=/tmp/tbident_$$ |
| # @param call reference to the call. Needed by all capisuite functions
| | TMPVARS=/var/cache/tbident/tbident.vars |
| # @param call_from string containing the number of the calling party
| | TIMEOUT=3 |
| # @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
| | if [ ! -x /usr/bin/lynx ]; then |
| (cause,causeB3)=capisuite.disconnect(call)
| | echo "Error: Lynx not installed." |
| capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| | exit 1 |
| | fi |
|
| |
|
| if (os.access(filename,os.R_OK)):
| | if [ ! -e /usr/bin/tbident-check.sh ]; then |
| cs_helpers.writeDescription(filename,
| | echo "Error: tbident-check.sh not installed." |
| "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\""
| | exit 1 |
| +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3))
| | fi |
| 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 [ ! -e $CACHE ]; then |
| if (fromaddress==""):
| | mkdir -p `dirname $CACHE` |
| fromaddress=curr_user
| | touch $CACHE |
| mailaddress=cs_helpers.getOption(config,curr_user,"fax_email","")
| | fi |
| if (mailaddress==""):
| | grep "^${NUMMER}|" $CACHE && exit 0 |
| 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 | | # read variables (daily per cron updated) |
| #
| | if [ ! -e "$TMPVARS" ]; then |
| # @param call reference to the call. Needed by all capisuite functions
| | tbident-check.sh |
| # @param call_from string containing the number of the calling party
| | fi |
| # @param call_to string containing the number of the called party
| | . $TMPVARS |
| # @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"):
| | # get 1.st match (-m1) of list |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"),1)
| | GREP="grep $CONTEXT $GREP_OPT -m1 $TMPFILE" |
| 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)
| | lynx "${URL}${NUMMER}" -dump -nolist -connect_timeout=$TIMEOUT >$TMPFILE 2>/dev/null |
| 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)
| | NAME=`$GREP | awk "{ if (NR == $NAME_LINE) print }" | sed -e "s/$NAME_FILTER\$//g" | |
| capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| | sed -e 's/^ *//' -e 's/ *$//'` |
| | DETAILS=`$GREP | awk "{ if (NR == $ADRS_LINE) print }" | sed -e "s/$ADRS_FILTER\$//g" | |
| | sed -e 's/^ *//' -e 's/ *$//'` |
|
| |
|
| except capisuite.CallGoneError: # catch this here to get the cause info in the mail
| | if [ -n "$NAME" ]; then |
| (cause,causeB3)=capisuite.disconnect(call)
| | echo "$NUMMER|$NAME|$DETAILS" |
| capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call)
| | echo "$NUMMER|$NAME|$DETAILS" >> $CACHE |
| | else |
| | echo "$NR|Unbekannt|" |
| | echo "$NR|Unbekannt|" >> $CACHE |
| | fi |
|
| |
|
| if (os.access(filename,os.R_OK)):
| | rm $TMPFILE |
| cs_helpers.writeDescription(filename,
| | </pre> |
| "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\""
| | File ''/usr/bin/'''''tbident-check.sh''': |
| +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3))
| | <pre>#!/bin/sh |
| userdata=pwd.getpwnam(curr_user)
| | # tbident-check.sh |
| 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 | | # Aktuelle Syntax prüfen und Variablen autom. setzen |
| # delete message - 1 | | # Rückwärtssuche Telefonnummer -> Eintrag im Telefonbuch |
| # 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
| | NR="091329040" |
| if (err.errno in (errno.EACCES,errno.EAGAIN)):
| | NUMMER=`echo "$NR" | tr -d ' ()' | sed -e "s/^\+49//"` |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fernabfrage-aktiv.la"))
| |
| lockfile.close()
| |
| return
| |
|
| |
|
| try:
| | URL="http://www.dasoertliche.de/?form_name=search_inv&action=1&&ph=" |
| # read directory contents
| | CONTEXT='Trefferliste' |
| messages=os.listdir(userdir+"received/")
| | NAME="" |
| messages=filter (lambda s: re.match("voice-.*\.la",s),messages) # only use voice-* files
| | DETAILS="" |
| 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
| | TMPFILE=/tmp/tbident_$$ |
| lastinquiry=-1
| | TMPVARS=/var/cache/tbident/tbident.vars |
| if (os.access(userdir+"received/last_inquiry",os.W_OK)):
| | TIMEOUT=3 |
| lastfile=open(userdir+"received/last_inquiry","r")
| |
| lastinquiry=int(lastfile.readline())
| |
| lastfile.close()
| |
|
| |
|
| # sort out old messages
| | if [ ! -x /usr/bin/lynx ]; then |
| oldmessages=[]
| | echo "Error: Lynx not installed." |
| i=0
| | exit 1 |
| while (i<len(messages)):
| | fi |
| 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 [ ! -e "$TMPVARS" ]; then |
| if (len(messages)==1):
| | cat > $TMPVARS << EOT |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
| | NAME_LINE=0 |
| else:
| | ADRS_LINE=0 |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
| | NAME_FILTER= |
| | ADRS_FILTER= |
| | GREP_OPT= |
| | EOT |
| | chmod a+rx $TMPVARS |
| | fi |
| | mv $TMPVARS ${TMPVARS}.bak |
|
| |
|
| # menu for record new announcement
| | lynx "${URL}${NUMMER}" -dump -nolist -connect_timeout=$TIMEOUT -dont_wrap_pre >$TMPFILE 2>/dev/null || |
| cmd=""
| | { echo "Error $0: Lynx failed." |
| while (cmd not in ("1","9")):
| | exit 1 |
| 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
| | awk ' |
| for curr_msgs in (messages,oldmessages):
| | BEGIN { |
| cs_helpers.sayNumber(call,str(len(curr_msgs)),curr_user,config)
| | srch="Trefferliste" |
| if (curr_msgs==messages):
| | nam="Herzo Werke GmbH" |
| if (len(curr_msgs)==1):
| | adr="Schießhausstr. 9, 91074 Herzogenaurach" |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachricht.la"),1)
| | srch_line=0 |
| else:
| | nam_line=0 |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"neue-nachrichten.la"),1)
| | adr_line=0 |
| else:
| | } |
| if (len(curr_msgs)==1):
| | /Trefferliste/ { srch_line = NR } |
| 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
| | /Herzo Werke GmbH/ { |
| while (i<len(curr_msgs)):
| | nam_line = NR |
| filename=userdir+"received/voice-"+str(curr_msgs[i])+".la"
| | drop_nam = index($0, nam) + length(nam) |
| descr=cs_helpers.readConfig(filename[:-2]+"txt")
| | drop_nam_str = substr($0, drop_nam) |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"nachricht.la"),1)
| | } |
| cs_helpers.sayNumber(call,str(i+1),curr_user,config)
| | /Schießhausstr. 9, 91074 Herzogenaurach/ { |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"von.la"),1)
| | adr_line = NR |
| cs_helpers.sayNumber(call,descr.get('GLOBAL','call_from'),curr_user,config)
| | drop_adr = index($0, adr) + length(adr) |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"fuer.la"),1)
| | drop_adr_str = substr($0, drop_adr) |
| 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)
| | END { |
| calltime=time.strptime(descr.get('GLOBAL','time'))
| | print "GREP_OPT=\"-A" max(adr_line, nam_line) - srch_line "\"" |
| cs_helpers.sayNumber(call,str(calltime[2]),curr_user,config)
| | print "NAME_LINE=\"" nam_line - srch_line + 1 "\"" |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
| | print "ADRS_LINE=\"" adr_line - srch_line + 1 "\"" |
| cs_helpers.sayNumber(call,str(calltime[1]),curr_user,config)
| | if ( length(drop_nam_str) ) printf "NAME_FILTER=\"%s\"\n", drop_nam_str |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"..la"),1)
| | else print "NAME_FILTER=" |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"um.la"),1)
| | if ( length(drop_adr_str) ) printf "ADRS_FILTER=\"%s\"\n", drop_adr_str |
| cs_helpers.sayNumber(call,str(calltime[3]),curr_user,config)
| | else print "ADRS_FILTER=" |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"uhr.la"),1)
| | } |
| cs_helpers.sayNumber(call,str(calltime[4]),curr_user,config)
| | function max(a,b) |
| capisuite.audio_send(call,filename,1)
| | { |
| cmd=""
| | if (a<b) return b |
| while (cmd not in ("1","4","5","6")):
| | else return a |
| capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"erklaerung.la"),1)
| | } |
| cmd=capisuite.read_DTMF(call,0,1)
| | ' $TMPFILE > $TMPVARS || |
| if (cmd=="1"):
| | { echo "Error $0: Awk failed." |
| os.remove(filename)
| | mv ${TMPVARS}.bak $TMPVARS |
| os.remove(filename[:-2]+"txt")
| | exit 1 |
| 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:
| | chmod a+rx $TMPVARS |
| # 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!)
| | diff $TMPVARS ${TMPVARS}.bak >/dev/null || echo "Info $0: Vars updated" |
| #
| | rm $TMPFILE |
| # @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> | | </pre> |
|
| |
|
| === File: ''/usr/lib/capisuite/idle_adv.py'' ===
| | [[Neobiker%27s_Wiki:Portal|Zurück zum Portal]] |
| <pre>
| |
| # idle_adv.py - default script for capisuite
| |
| # ---------------------------------------------
| |
| # copyright : (C) 2007 neobiker
| |
| #
| |
| # copyright : (C) 2002 by Gernot Hillier
| |
| # email : gernot@hillier.de
| |
| # version : $Revision: 1.8.2.2 $
| |
| #
| |
| # 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.
| |
| #
| |
| | |
| import os,re,time,pwd,fcntl
| |
| # capisuite stuff
| |
| import capisuite,cs_helpers
| |
| | |
| def idle(capi):
| |
| config=cs_helpers.readConfig()
| |
| spool=cs_helpers.getOption(config,"","spool_dir")
| |
| if (spool==None):
| |
| capisuite.error("global option spool_dir not found.")
| |
| return
| |
| | |
| done=os.path.join(spool,"done")+"/"
| |
| failed=os.path.join(spool,"failed")+"/"
| |
| | |
| if (not os.access(done,os.W_OK) or not os.access(failed,os.W_OK)):
| |
| capisuite.error("Can't read/write to the necessary spool dirs")
| |
| return
| |
| | |
| userlist=config.sections()
| |
| userlist.remove('GLOBAL')
| |
| | |
| for user in userlist: # search in all user-specified sendq's
| |
| # skip none user sections
| |
| if not config.has_option(user,'voice_numbers'):
| |
| break
| |
| userdata=pwd.getpwnam(user)
| |
| outgoing_nr=cs_helpers.getOption(config,user,"outgoing_MSN","")
| |
| if (outgoing_nr==""):
| |
| incoming_nrs=cs_helpers.getOption(config,user,"fax_numbers","")
| |
| if (incoming_nrs==""):
| |
| continue
| |
| else:
| |
| outgoing_nr=(incoming_nrs.split(','))[0]
| |
| | |
| udir=cs_helpers.getOption(config,"","fax_user_dir")
| |
| if (udir==None):
| |
| capisuite.error("global option fax_user_dir not found.")
| |
| return
| |
| udir=os.path.join(udir,user)+"/"
| |
| sendq=os.path.join(udir,"sendq")+"/"
| |
| if (not os.access(udir,os.F_OK)):
| |
| os.mkdir(udir,0700)
| |
| os.chown(udir,userdata[2],userdata[3])
| |
| if (not os.access(sendq,os.F_OK)):
| |
| os.mkdir(sendq,0700)
| |
| os.chown(sendq,userdata[2],userdata[3])
| |
| | |
| files=os.listdir(sendq)
| |
| files=filter (lambda s: re.match("fax-.*\.txt",s),files)
| |
| | |
| for job in files:
| |
| job_fax=job[:-3]+"sff"
| |
| real_user_c=os.stat(sendq+job).st_uid
| |
| real_user_j=os.stat(sendq+job_fax).st_uid
| |
| if (real_user_j!=pwd.getpwnam(user)[2] or real_user_c!=pwd.getpwnam(user)[2]):
| |
| capisuite.error("job "+sendq+job_fax+" seems to be manipulated (wrong uid)! Ignoring...")
| |
| continue
| |
| | |
| lockfile=open(sendq+job[:-3]+"lock","w")
| |
| # read directory contents
| |
| fcntl.lockf(lockfile,fcntl.LOCK_EX) # lock so that it isn't deleted while sending
| |
| | |
| if (not os.access(sendq+job,os.W_OK)): # perhaps it was cancelled?
| |
| fcntl.lockf(lockfile,fcntl.LOCK_UN)
| |
| lockfile.close()
| |
| os.unlink(sendq+job[:-3]+"lock")
| |
| continue
| |
| | |
| control=cs_helpers.readConfig(sendq+job)
| |
| # set DST value to -1 (unknown), as strptime sets it wrong for some reason
| |
| starttime=(time.strptime(control.get("GLOBAL","starttime")))[0:8]+(-1,)
| |
| starttime=time.mktime(starttime)
| |
| if (starttime>time.time()):
| |
| fcntl.lockf(lockfile,fcntl.LOCK_UN)
| |
| lockfile.close()
| |
| os.unlink(sendq+job[:-3]+"lock")
| |
| continue
| |
| | |
| tries=control.getint("GLOBAL","tries")
| |
| dialstring=control.get("GLOBAL","dialstring")
| |
| addressee=cs_helpers.getOption(control,"GLOBAL","addressee","")
| |
| subject=cs_helpers.getOption(control,"GLOBAL","subject","")
| |
| mailaddress=cs_helpers.getOption(config,user,"fax_email","")
| |
| if (mailaddress==""):
| |
| mailaddress=user
| |
| fromaddress=cs_helpers.getOption(config,user,"fax_email_from","")
| |
| if (fromaddress==""):
| |
| fromaddress=user
| |
| | |
| capisuite.log("job "+job_fax+" from "+user+" to "+dialstring+" initiated",1)
| |
| result,resultB3 = sendfax(capi,sendq+job_fax,outgoing_nr,dialstring,user,config)
| |
| tries+=1
| |
| capisuite.log("job "+job_fax+": result was %x,%x" % (result,resultB3),1)
| |
| | |
| if (result in (0,0x3400,0x3480,0x3490,0x349f) and resultB3==0):
| |
| movejob(job_fax,sendq,done,user)
| |
| capisuite.log("job "+job_fax+": finished successfully",1)
| |
| mailtext="Your fax job to "+addressee+" ("+dialstring+") was sent successfully.\n\n" \
| |
| +"Subject: "+subject+"\nFilename: "+job_fax \
| |
| +"\nNeeded tries: "+str(tries) \
| |
| +("\nLast result: 0x%x/0x%x" % (result,resultB3)) \
| |
| +"\n\nIt was moved to file://"+done+user+"-"+job_fax
| |
| cs_helpers.sendSimpleMail(fromaddress,mailaddress,
| |
| "Fax to "+addressee+" ("+dialstring+") sent successfully.",
| |
| mailtext)
| |
| else:
| |
| max_tries=int(cs_helpers.getOption(config,"","send_tries","10"))
| |
| delays=cs_helpers.getOption(config,"","send_delays","60,60,60,300,300,3600,3600,18000,36000").split(",")
| |
| delays=map(int,delays)
| |
| if ((tries-1)<len(delays)):
| |
| next_delay=delays[tries-1]
| |
| else:
| |
| next_delay=delays[-1]
| |
| starttime=time.time()+next_delay
| |
| capisuite.log("job "+job_fax+": delayed for "+str(next_delay)+" seconds",2)
| |
| cs_helpers.writeDescription(sendq+job_fax,"dialstring=\""+dialstring+"\"\n"
| |
| +"starttime=\""+time.ctime(starttime)+"\"\ntries=\""+str(tries)+"\"\n"
| |
| +"user=\""+user+"\"\naddressee=\""+addressee+"\"\nsubject=\""+subject+"\"\n")
| |
| if (tries>=max_tries):
| |
| movejob(job_fax,sendq,failed,user)
| |
| capisuite.log("job "+job_fax+": failed finally",1)
| |
| mailtext="I'm sorry, but your fax job to "+addressee+" ("+dialstring \
| |
| +") failed finally.\n\nSubject: "+subject \
| |
| +"\nFilename: "+job_fax+"\nTries: "+str(tries) \
| |
| +"\nLast result: 0x%x/0x%x" % (result,resultB3) \
| |
| +"\n\nIt was moved to file://"+failed+user+"-"+job_fax
| |
| cs_helpers.sendSimpleMail(fromaddress,mailaddress,
| |
| "Fax to "+addressee+" ("+dialstring+") FAILED.",
| |
| mailtext)
| |
| | |
| fcntl.lockf(lockfile,fcntl.LOCK_UN)
| |
| lockfile.close()
| |
| os.unlink(sendq+job[:-3]+"lock")
| |
| | |
| def sendfax(capi,job,outgoing_nr,dialstring,user,config):
| |
| try:
| |
| controller=int(cs_helpers.getOption(config,"","send_controller","1"))
| |
| timeout=int(cs_helpers.getOption(config,user,"outgoing_timeout","60"))
| |
| stationID=cs_helpers.getOption(config,user,"fax_stationID")
| |
| if (stationID==None):
| |
| capisuite.error("Warning: fax_stationID for user "+user+" not set")
| |
| stationID=""
| |
| headline=cs_helpers.getOption(config,user,"fax_headline","")
| |
| (call,result)=capisuite.call_faxG3(capi,controller,outgoing_nr,dialstring,timeout,stationID,headline)
| |
| if (result!=0):
| |
| return(result,0)
| |
| capisuite.fax_send(call,job)
| |
| return(capisuite.disconnect(call))
| |
| except capisuite.CallGoneError:
| |
| return(capisuite.disconnect(call))
| |
| | |
| def movejob(job,olddir,newdir,user):
| |
| os.rename(olddir+job,newdir+user+"-"+job)
| |
| os.rename(olddir+job[:-3]+"txt",newdir+user+"-"+job[:-3]+"txt")
| |
| | |
| #
| |
| # History:
| |
| #
| |
| # $Log: idle.py,v $
| |
| # Revision 1.8.2.2 2004/01/10 07:56:27 gernot
| |
| # - fax_numbers is really allowed to miss now (taken from MAIN, 1.11)...
| |
| #
| |
| # Revision 1.8.2.1 2003/09/21 12:35:20 gernot
| |
| # - add 0x349f to list of normal results
| |
| #
| |
| # Revision 1.8 2003/06/26 11:53:17 gernot
| |
| # - fax jobs can be given an addressee and a subject now (resolves #18, reported
| |
| # by Achim Bohnet)
| |
| #
| |
| # Revision 1.7 2003/06/19 14:58:43 gernot
| |
| # - fax_numbers is now really optional (bug #23)
| |
| # - tries counter was wrongly reported (bug #29)
| |
| #
| |
| # Revision 1.6 2003/04/06 11:07:40 gernot
| |
| # - fix for 1-hour-delayed sending of fax (DST problem)
| |
| #
| |
| # 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:09:58 gernot
| |
| # - use stricted permissions for saved files and created userdirs. Fixes
| |
| # bug #544
| |
| #
| |
| # Revision 1.3 2003/03/09 11:48:10 gernot
| |
| # - removed wrong unlock operation (lock not acquired at this moment!)
| |
| #
| |
| # Revision 1.2 2003/03/06 09:59:11 gernot
| |
| # - added "file://" as prefix to filenames in sent mails, thx to
| |
| # Achim Bohnet for this suggestion
| |
| #
| |
| # Revision 1.1.1.1 2003/02/19 08:19:54 gernot
| |
| # initial checkin of 0.4
| |
| #
| |
| # Revision 1.12 2003/02/18 09:54:22 ghillie
| |
| # - added missing lockfile deletions, corrected locking protocol
| |
| # -> fixes Bugzilla 23731
| |
| #
| |
| # Revision 1.11 2003/02/17 16:48:43 ghillie
| |
| # - do locking, so that jobs can be deleted
| |
| #
| |
| # Revision 1.10 2003/02/10 14:50:52 ghillie
| |
| # - revert logic of outgoing_MSN: it's overriding the first number of
| |
| # fax_numbers now
| |
| #
| |
| # Revision 1.9 2003/02/05 15:59:11 ghillie
| |
| # - search for *.txt instead of *.sff so no *.sff which is currently created
| |
| # by capisuitefax will be found!
| |
| #
| |
| # Revision 1.8 2003/01/31 11:22:00 ghillie
| |
| # - use different sendq's for each user (in his user_dir).
| |
| # - use prefix user- for names in done and failed
| |
| #
| |
| # Revision 1.7 2003/01/27 21:56:46 ghillie
| |
| # - mailaddress may be not set, that's the same as ""
| |
| # - use first entry of fax_numbers as outgoing MSN if it exists
| |
| #
| |
| # 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:26 ghillie
| |
| # - updated to use new configuration file capisuite-script.conf
| |
| #
| |
| # Revision 1.3 2003/01/13 16:12:00 ghillie
| |
| # - renamed from idle.pyin to idle.py as all previously processed variables
| |
| # stay in the config file and cs_helpers.pyin now
| |
| #
| |
| # Revision 1.2 2002/12/16 13:07:22 ghillie
| |
| # - finished queue processing
| |
| #
| |
| # Revision 1.1 2002/12/14 13:53:19 ghillie
| |
| # - idle.py and incoming.py are now auto-created from *.pyin
| |
| #
| |
| </pre>
| |