def init_unknown_org_person():
    """if the database doesn't have a default unknown organization, make one.
    if the database doesn't have a default unknown person (for no number),
    make one."""

    #
    # see if we could find the unknown org.  if not, make one.
    #
    unknownOrgAlias = dsh_config.lookup('UNKNOWN_ORG_ALIAS')
    unknownOrgs = Organization.objects.filter(alias=unknownOrgAlias)
    if unknownOrgs:
        unknownOrg = unknownOrgs.latest()
        if len(unknownOrgs) > 1:
            message = 'dsh_django1.init_unknown_org_person: ' + \
                      'more than one unknown org found.'
            dsh_utils.give_news(message, logging.warning)
            dsh_agi.report_event(message, reportLevel='WRN')
        dsh_utils.db_print('dsh_django1: found existing unknown org.', 99)
    else:
        unknownOrg = Organization(
            name='Unknown Organization',
            alias=unknownOrgAlias,
            language='OTH',
            description="""This is a place holder organization for unknown callers, automatically added by Asterisk.""")
        unknownOrg.save()
        dsh_utils.db_print('dsh_django1: created new unknown org.', 99)

    dsh_utils.db_print('dsh_django1: unknownOrg: ' + repr(unknownOrg), 99)

    #
    # see if we could find the unknown person.  if not, make one.
    #
    unknownNumber = dsh_config.lookup('UNKNOWN_PHONE_NUMBER')
    unknownPersonName = dsh_config.lookup('UNKNOWN_PERSON_NAME')
    unknownPersons = Person.objects.filter(
        first_name=unknownPersonName, phone_number=unknownNumber)
    if unknownPersons:
        unknownPerson = unknownPersons.latest()
        if len(unknownPersons) > 1:
            message = 'dsh_django1.init_unknown_org_person: ' + \
                      'more than one unknown person found.'
            dsh_utils.give_news(message, logging.warning)
            dsh_agi.report_event(message, reportLevel='WRN',
                                 phone_number=unknownPerson.phone_number)
        dsh_utils.db_print('dsh_django1: found existing unknown person.', 99)
    else:
        unknownPerson = Person(
            first_name=unknownPersonName,
            phone_number=unknownNumber,
            organization=unknownOrg,
            ptype='OTH',
            gender='F',
            description="""This is the place-holder person for callers whose phone numbers we don't know, automatically added by Asterisk.""")
        unknownPerson.save()
        dsh_utils.db_print('dsh_django1: created new unknown person.', 99)

    dsh_utils.db_print('dsh_django1: unknownPerson: ' + repr(unknownPerson),
                       99)

    return (unknownOrg,unknownPerson)
Beispiel #2
0
def init_log():
    """set up logging."""
    logdir = dsh_config.lookup('log_file_dir')
    logName = dsh_config.lookup('log_file_name')
    dsh_utils.check_logging(logdir, logName)
    dsh_utils.give_news('dsh_load: entered --------------------',
                        logging.info)
def init_dirs():
    global globals4signal

    #
    # set up logging.
    #
    logdir = dsh_config.lookup('log_file_dir')
    logName = dsh_config.lookup('log_file_name')
    dsh_utils.check_logging(logdir, logName)
    dsh_utils.give_news('dsh_simple1: entered --------------------',
                        logging.info)

    #
    # set up directories.
    #
    success,outDir,inDir = setup_dirs()
    if not success:
        return (False,None,None,None)
    dsh_utils.db_print('dsh_simple1.init_dirs: ' +
                       'outdir: ' + outDir + ', indir: ' + inDir, 94)

    #
    # check existence of output file.
    #
    outFile = dsh_config.lookup('outgoing_voice_file')
    outFile = os.path.join(outDir, outFile)
    if not sound_exists(outFile):
        return (False,None,None,None)
    dsh_utils.db_print('dsh_simple1.init_dirs: ' + 'outFile: ' + outFile, 94)

    globals4signal['log_dir'] = logdir
    
    return (True,inDir,outDir,outFile)
def record(fileName, consoleMsg=True):
    timeLimit = dsh_config.lookup('record_time_limit')
    stopButton = dsh_config.lookup('record_stop_key')
    fileFormat = dsh_config.lookup('record_file_format')
    command = 'RECORD FILE ' + fileName + ' ' + fileFormat + ' ' + \
              stopButton + ' ' + str(timeLimit) + '\n'
    res = send_command(command, 'dsh_agi.record: ', consoleMsg)
    return res
def init_log():
    global globals4signal

    #
    # set up logging.
    #
    logdir = dsh_config.lookup('log_file_dir')
    logName = dsh_config.lookup('log_file_name')
    dsh_utils.check_logging(logdir, logName)
    dsh_utils.give_news('dsh_django1: entered --------------------',
                        logging.info)
    #dsh_agi.debug_event('dsh_django1: entered --------------------', 97)
    globals4signal['log_dir'] = logdir
def record(fileName, consoleMsg=True):
    timeLimit = dsh_config.lookup('record_time_limit')
    stopButton = dsh_config.lookup('record_stop_key')
    fileFormat = dsh_config.lookup('record_file_format')
    #command = 'RECORD FILE ' + fileName + ' ' + fileFormat + ' ' + \
    #          stopButton + ' ' + str(timeLimit) + '\n'
    #
    # no stop button!
    # it seems to be causing trouble!
    #
    command = 'RECORD FILE ' + fileName + ' ' + fileFormat + ' ' + \
              '""' + ' ' + str(timeLimit) + '\n'
    res = send_command(command, 'dsh_agi.record: ', consoleMsg)
    return res
def forward_call(fileName, callNum, consoleMsg=True, testCheat=False):
    fileFormat = dsh_config.lookup('record_file_format')
    command = 'EXEC Monitor %s|%s|m\n' % (fileFormat, fileName)
    res = send_command(command, 'dsh_agi.exec_com: ', consoleMsg)
    #channel = dsh_config.lookup('FORWARD_OUTGOING_CHANNEL')
    channel = dsh_common_db.get_forward_outgoing_channel()
    
    if testCheat and dsh_config.lookup('BARNEY_TEST'):
        callNum = dsh_config.lookup('BARNEY_TEST_JUNIOR_ZOIPER')
        
    command = 'EXEC Dial %s/%s\n' % (channel, callNum)
    #command = 'EXEC Dial %s/%s 60 o\n' % (channel, callNum)
    res = send_command(command, 'dsh_agi.forward_call: ', consoleMsg)
    command = 'EXEC StopMonitor\n'
    res = send_command(command, 'dsh_agi.forward_call: ', consoleMsg)
    return res
Beispiel #8
0
def email_confirm(request):
    """displays a simple form for confirming emailing the selection.
    modeled after red5_save()."""

    if dsh_django_request.deny_it(request):
        return please_log_in()

    response = page_header('email the selected items?')

    response += """
<FORM ACTION="/email/" METHOD="post">

email addresses: <INPUT TYPE="TEXT" NAME="email_addresses" SIZE="80"
value="%s, "><br><br>

comments:<BR>
<TEXTAREA NAME="comments" ROWS=5 COLS=70></TEXTAREA><br><br>

attach voice? <INPUT TYPE=checkbox NAME=attach_voice>
&nbsp;&nbsp;&nbsp;
include dsh.cs URLs? <INPUT TYPE=checkbox NAME=dsh_url><br><br>

<!--
include pnet1-LAN URLs? <INPUT TYPE=checkbox NAME=lan_url>
&nbsp;&nbsp;&nbsp;
include pnet1-VPN URLs? <INPUT TYPE=checkbox NAME=vpn_url>
<br><br>
-->

<INPUT TYPE="submit" VALUE="send">
</FORM>
""" % (dsh_config.lookup('GMAIL_DEFAULT_RECIPIENT'),)
    
    response += page_footer()
    return HttpResponse(response)    
def add_to_tar(fileToAdd, tarFilePath):
    """adds fileToAdd to tarFilePath."""

    tarBin = dsh_django_config.lookup('TAR_PATH')
    mediaDir = dsh_config.lookup('MEDIA_DIR')
    
    try:
        os.chdir(mediaDir)

        if not dsh_utils.is_valid_file(fileToAdd, silent=True):
            message = 'dsh_dump.add_to_tar: invalid file: ' + fileToAdd
            tarMsg = dsh_utils.red_error_break_msg(message)
            dsh_django_utils.error_event(message, errorLevel='ERR')
            return (False, tarMsg)
        
        command = tarBin + ' rf ' + tarFilePath + ' ' + fileToAdd
        dsh_django_utils.debug_event(
            'dsh_dump.add_to_tar: command: ' + command, 8)
        result = dsh_utils.try_execute(command)
        if result == None:
            message = 'dsh_dump.add_to_tar: tar problem: ' + command
            dsh_django_utils.error_event(message, errorLevel='CRT')
            return (False, dsh_utils.red_error_break_msg(message))
        return (True, '')
    
    except:
        message = 'dsh_dump.add_to_tar: unknown tar problem: ' + command
        dsh_django_utils.error_event(message, errorLevel='CRT')
        return (False, dsh_utils.red_error_break_msg(message))
def say_digits(number):
    """
    10/04/09: called by read_back_caller_number().
    says the phone numbers
    """

    dsh_common_db.init_log(quiet=True)
    funcName = 'dsh_common_agi.say_digits:'
    number = number.strip()

    soundDir = dsh_common_config.lookup('DSH_PROMPT_DIR')
    sorrySound = dsh_config.lookup('DSH_PROMPT_SORRY')
    sorrySound = os.path.join(soundDir, sorrySound)
    
    if not number:
        dsh_agi.say_it(sorrySound)
        return

    try:
        inumber = int(number)
    except:
        message = '%s not a number: %s.' % (funcName, number)
        dsh_agi.report_event(message, reportLevel='ERR')
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.say_it(sorrySound)
        return

    datesDir = os.path.join(soundDir, 'dates')
    dateDir = os.path.join(datesDir, 'dates')

    for digit in number:
        digit = '0' + digit
        sound = os.path.join(dateDir, digit)
        dsh_agi.say_it(sound)
Beispiel #11
0
def hide_phone_digits(phone):
    if phone == '':
        return ''
    hideDigits = dsh_config.lookup('HIDE_PHONE_DIGITS')
    l = len(phone)
    if (l <= hideDigits):
        return ''.rjust(l, 'x')
    return phone[:(l-hideDigits)] + 'xxxx'
Beispiel #12
0
def abs_url_to_relative(url):
    """turns '/media/voice/blah/blah' into 'voice/blah/blah'.
    called by dsh_django1.py.
    and dsh_dump.py.
    """
    chopAbsURLPrefix = dsh_config.lookup('ABS_URL_PREFIX_CHOP')
    url = url.replace(chopAbsURLPrefix, '')
    url = url.lstrip('/')
    return url
def main():
    prefix = dsh_config.lookup('log_file_dir')
    logName = dsh_config.lookup('log_file_name')
    
    dsh_utils.check_logging(prefix, logName)
    dsh_utils.db_print('dsh_test1: entered...', 93)
    
    dsh_agi.read_env()

    testOut1 = prefix + 'test_out1'
    testOut2 = prefix + 'test_tanuja'
    testIn1 = prefix + 'test_in1'
    dsh_agi.say_it(testOut1)
    #dsh_agi.say_it(testOut2)
    #dsh_agi.say_it('/var/lib/asterisk/sounds/demo-congrats')
    dsh_agi.record(testIn1)
    dsh_agi.say_it(testIn1)
    dsh_utils.give_news('dsh_test1: done.')
def main():

    dsh_django2.init_log('dsh_stats_log.py: entered --------------------')
    sortBy = dsh_config.lookup('STATS_SORT_BY')

    success,response,totals = dsh_stats.stats_calculate(
        sortBy=sortBy, logAction='STT1', textLog=True)
    
    sys.exit(0)
Beispiel #15
0
def stats(request, sortBy=None):
    """triggered by urls.py"""
    response = page_header('stats')

    if not sortBy:
        sortBy = dsh_config.lookup('STATS_SORT_BY')
        
    response += dsh_stats.stats(sortBy=sortBy)
    response += page_footer()
    
    return HttpResponse(response)
Beispiel #16
0
def make_abs_file_pathname(url):
    #
    # get the file path.
    # path_prefix: /home/rywang/phone_data/django/
    # url: /media/voice/2009/07/test4_________.mp3
    # concatenate these two.
    #
    path_prefix = dsh_config.lookup('PHONE_DATA_DJANGO_PATH')
    strippedUrl = url.lstrip('/')
    filePath = os.path.join(path_prefix, strippedUrl)
    return filePath
Beispiel #17
0
def record(fileName, consoleMsg=True, allowStopButton=False, stopButton=''):
    timeLimit = dsh_config.lookup('record_time_limit')
    if not stopButton:
        stopButton = dsh_config.lookup('record_stop_key')
    fileFormat = dsh_config.lookup('record_file_format')

    #
    # 10/04/04:
    # revive the stop button, to allow doctors to loop over questions.
    #
    if allowStopButton:
        command = 'RECORD FILE ' + fileName + ' ' + fileFormat + ' ' + \
                  stopButton + ' ' + str(timeLimit) + '\n'
    else:
        #
        # no stop button!
        # it seems to be causing trouble!
        #
        command = 'RECORD FILE ' + fileName + ' ' + fileFormat + ' ' + \
                  '""' + ' ' + str(timeLimit) + '\n'
    res = send_command(command, 'dsh_agi.record: ', consoleMsg)
    return res
def setup_dirs():
    """make voice directories if they don't exist already."""

    outDir = dsh_config.lookup('voice_data_dir_out')

    if not dsh_utils.try_mkdir_ifdoesnt_exist(outDir,
                                              'dsh_simple1.setup_dirs: ' +
                                              'outgoing dir '):
        return (False,None,None)

    miscDict = dsh_utils.get_misc_dict()
    yearMonth = miscDict['year_month']

    inDir = dsh_config.lookup('voice_data_dir_in')
    inDir = os.path.join(inDir, yearMonth)
    
    if not dsh_utils.try_mkdir_ifdoesnt_exist(inDir,
                                              'dsh_simple1.setup_dirs: ' +
                                              'incoming dir '):
        return (False,None,None)

    return (True,outDir,inDir)
def demo_reply_prompt_confirm(recent, itemTable, keyWordTable, eventTable,
                              sessionID=''):
    """
    10/04/09: called by demo_reply().
    modeled after dsh_django2.handle_staff_caller().
    """

    funcName = 'dsh_common_agi.demo_reply_prompt_confirm:'
    count = 0
    promptDir = dsh_common_config.lookup('DSH_PROMPT_DIR')
    demoPress1 = dsh_common_config.lookup('DSH_PROMPT_DEMO_PRESS1_SEND')
    demoPress1 = os.path.join(promptDir, demoPress1)
    timeOut1 = dsh_config.lookup('DSH_PROMPT_WAIT1')
    maxRetries = dsh_common_config.lookup2('STAFF_RETRIES')
    demoSending = dsh_common_config.lookup('DSH_PROMPT_DEMO_SENDING_IN8')
    demoSending = os.path.join(promptDir, demoSending)

    while True:
        count += 1

        if count > maxRetries:
            say_goodbye()
            return True

        choice = dsh_agi.get_digits(demoPress1, 1, timeOut=timeOut1)
        dsh_utils.db_print('%s the choice is: %s.' % (funcName, repr(choice)),
                           168)

        if choice == None or choice == '' or choice == '*':
            say_goodbye()
            return True

        if choice == '1':
            dsh_common_db.attempt_demo_reply_now(
                recent, itemTable, keyWordTable, eventTable,
                sessionID=sessionID)
            dsh_agi.say_it(demoSending)
            say_goodbye()
            return True

        continue

    return True
Beispiel #20
0
def check_dot_call_num(agiEnv):
    """called by dsh_django2.lookup_number_in_db().
    check to see if this is the result of a .call file.
    if yes, you have something like:
    agi_calleridname = __DOT_CALL__ phoneNum
    returns (found, phoneNum)
    """

    if not agiEnv.has_key('agi_calleridname'):
        return (False, None)

    callerIdName = agiEnv['agi_calleridname']
    prefixToCheck = dsh_config.lookup('DOT_CALL_INDICATOR')
    if not callerIdName.startswith(prefixToCheck):
        return (False, None)

    chopped = callerIdName.replace(prefixToCheck, '')
    chopped = chopped.strip()
    return (True, chopped)
Beispiel #21
0
def red5_clear(request):
    if dsh_django_request.deny_it(request):
        return please_log_in()

    response = page_header('clear files in red5 scratch space')

    keepList = ['9.flv', '9.flv.meta',
                'toystory3.flv', 'toystory3.flv.meta',
                'test_randy.flv', 'test_randy.flv.meta', ]

    red5Dir = dsh_config.lookup('RED5_STREAMS_DIR')
    red5TmpDir = os.path.join(red5Dir, 'tmp')

    dsh_utils.empty_dir(red5Dir, keepList)
    dsh_utils.empty_dir(red5TmpDir)

    response += dsh_utils.black_break_msg('Cleared.')
    response += page_footer()

    return HttpResponse(response)
def determine_unknown_caller(unknownOrg, unknownPerson,
                             phoneNumberLookupResult):
    """if the caller's phone number is not known at all, we say the caller is
    unknownPerson from the unknownOrg.
    if the caller's phone number is known but not in the database,
    we add the caller to the database, and make her belong to unknownOrg."""

    if not phoneNumberLookupResult:
        #
        # we don't know the guy's phone number.
        #
        return unknownPerson

    person,phoneNumber = phoneNumberLookupResult

    if person:
        return person

    #
    # we have a phone number. but the person is not in the database.
    # we should put the person in.
    #
    unknownPersonName = dsh_config.lookup('UNKNOWN_PERSON_NAME')
    newUnknownPerson = Person(
        first_name=unknownPersonName,
        phone_number=phoneNumber,
        organization=unknownOrg,
        ptype='OTH',
        gender='F',
        description="""This unknown caller was automatically added by Asterisk.""")
    newUnknownPerson.save()
    message = 'dsh_django1.determine_caller: ' + \
              'added unknown caller to database with number: ' + \
              phoneNumber
    dsh_utils.give_news(message, logging.info)
    dsh_agi.report_event(message, reportLevel='INF',
                         phone_number=phoneNumber)
    return newUnknownPerson
def change_call_num_to_zoiper_test(callee, callNum):
    """
    10/04/09:
    called by dsh_django_utils.generate_dot_call_file().
    if I'm doing testing on home laptops,
    change the call number to a fellow laptop's Zoiper number.
    normally, it's just callee.phone_number.
    in the Zoiper case, it'll be something like:
    192.168.2.14:4569-753
    see models.py 10/04/09.
    """

    calleeNum = callee.phone_number
    physChannel = dsh_db_config.get('outgoing_channel')
    if not physChannel:
        return callNum
    if physChannel != dsh_config.lookup('FORWARD_OUTGOING_CHANNEL_IAX2'):
        return callNum
    zoiperNumber = dsh_db_config.get('zoiper_number')
    if not zoiperNumber:
        return callNum
    zoiperNumber = zoiperNumber.strip()
    return zoiperNumber
def sort_key(sortBy):
    """called by stats() below.  which key in the tuple is sort key?
    corresponds to stats_person_tuple_list() above.
    """
    if not sortBy:
        sortBy = dsh_config.lookup('STATS_SORT_BY')
    if sortBy == 'recorded':
        sortKey = operator.itemgetter(1)
    elif sortBy == 'items':
        sortKey = operator.itemgetter(2)
    elif sortBy == 'callsnorec':
        sortKey = operator.itemgetter(3)
    elif sortBy == 'calls':
        sortKey = operator.itemgetter(4)
    elif sortBy == 'starred':
        sortKey = operator.itemgetter(5)
    elif sortBy == 'recdur':
        sortKey = operator.itemgetter(6)
    elif sortBy == 'calldur':
        sortKey = operator.itemgetter(7)
    else:
        return None
    return sortKey
def read_back_caller_number(item, fromPhone=False, sessionID=''):
    """
    10/04/09: called by demo_reply().  read back the phone number of the
    most recent caller.
    """

    response = ''
    funcName = 'dsh_common_agi.read_back_caller_number:'
    
    caller = item.owner
    phoneNumber = caller.phone_number

    if not phoneNumber:
        message = '%s no phone number: %s.' % (funcName, caller.dsh_uid)
        response += dsh_utils.red_error_break_msg(message)
        dsh_agi.report_event(message, reportLevel='ERR', sessionID=sessionID)
        dsh_utils.give_bad_news(message, logging.error)
        return (False, response)

    message = 'Send an immediate reply to %s @ %s? ' %\
              (caller.__unicode__(), phoneNumber)
    message += '<a href="/senddemoreplyconfirmed/%s">Confirm</a>?' %\
               (item.dsh_uid,)
    response += dsh_utils.black_break_msg(message)

    if fromPhone:
        promptDir = dsh_common_config.lookup('DSH_PROMPT_DIR')
        last4 = dsh_common_config.lookup('DSH_PROMPT_DEMO_LAST4')
        dsh_agi.say_it(os.path.join(promptDir, last4))
        howManyDigits = dsh_config.lookup('HIDE_PHONE_DIGITS')
        lastDigits = phoneNumber[-howManyDigits:]
        dsh_utils.give_news(
            'demo to phone: %s, last 4 digits: %s.' %\
            (phoneNumber, lastDigits), logging.info)
        say_digits(lastDigits)

    return (True, response)
#!/usr/bin/python -u
#
# called by /etc/rc.local
# clears the outgoing spool. then reschedules.
#


import sys,logging,os,signal,subprocess,datetime,time
import dsh_agi,dsh_utils,dsh_config,dsh_bizarro,dsh_django2



#
# django-specific initializations.
#
os.environ['DJANGO_SETTINGS_MODULE'] = dsh_config.lookup(
    'DJANGO_SETTINGS_MODULE')
dsh_utils.add_to_sys_path(dsh_config.lookup('django_sys_paths'))
from dvoice.db.models import Person,Organization,Item,Event
import dsh_django_utils,dsh_db_config,dsh_stats

    
    
def main():

    dsh_django2.init_log('dsh_stats_log.py: entered --------------------')
    sortBy = dsh_config.lookup('STATS_SORT_BY')

    success,response,totals = dsh_stats.stats_calculate(
        sortBy=sortBy, logAction='STT1', textLog=True)
    
    sys.exit(0)
def hangup_signal_handler(signum, frame):
    """attempt to do file format conversion upon a hangup.
    from .wav to .mp3."""
    
    dsh_utils.db_print2('dsh_simple1.signal_handler: entered...', 94)


    #
    # get the name of the file that was just recorded.
    #
    if not globals4signal.has_key('in_file'):
        dsh_utils.give_news('dsh_simple1.hangup_signal_handler: ' +
                            'hangup before recording.', logging.info)
        sys_exit(0)

    inputFile = globals4signal['in_file']


    #
    # the recorded format is wav? if not, we don't convert.
    #
    fileFormat = dsh_config.lookup('record_file_format')
    if fileFormat != 'wav':
        dsh_utils.give_bad_news('dsh_simple1.hangup_signal_handler: ' +
                                "can't convert non-wav file: " + inputFile,
                                logging.error)

    #
    # does the .wav file exist and is it non-zero sized?
    #
    inputWav = inputFile + '.wav'
    success,bytes = dsh_utils.get_file_size(inputWav)
    if not success:
        dsh_utils.give_news('dsh_simple1.hangup_signal_handler: ' +
                            'no input file to convert: ' +
                            inputWav, logging.info)
        sys_exit(1)
    if bytes == 0:
        dsh_utils.give_news('dsh_simple1.hangup_signal_handler: ' +
                            'inputfile size 0: ' + inputWav, logging.info)
        sys_exit(1)

    dsh_utils.db_print2('dsh_simple1.signal_handler: ready to convert: ' +
                        inputWav, 94)

    #
    # where's the lame binary?
    #
    lamePath = dsh_config.lookup('lame_location')
    if not dsh_utils.is_valid_file(lamePath,
                                   msg='dsh_simple1.hangup_signal_handler:'):
        dsh_utils.give_bad_news('dsh_simple1.hangup_signal_handler: ' +
                                'need to install lame.', logging.error)
        sys_exit(1)


    #
    # stdout and stderr redirected to the log directory.
    #
    stdLogs = dsh_bizarro.stdio_logs_open(globals4signal['log_dir'])
    if not stdLogs:
        sys_exit(1)
    stdout,stderr = stdLogs


    #
    # the conversion command should be:
    # lame --resample 22.05 -b 24 test.wav test4.mp3
    #
    mp3Quality = dsh_config.lookup('lame_mp3_quality')
    outputMp3 = inputFile + '.mp3'
    #command = ffmpegPath + ' -i ' + inputWav + mp3Quality + outputMp3
    command = lamePath + mp3Quality + inputWav + ' ' + outputMp3

    ret = subprocess.call(command, shell=True, stdout=stdout, stderr=stderr)
    if ret != 0:
        dsh_utils.give_bad_news('dsh_simple1.signal_handler: ' +
                                'error in format conversion: ' +
                                command, logging.error)
        sys_exit(1)

    dsh_utils.give_news('dsh_simple1.signal_handler: conversion success: ' +
                        command, logging.info)
    if not dsh_utils.cleanup_path(inputWav, 'dsh_simple1.signal_handler'):
        dsh_utils.give_bad_news('dsh_simple1.signal_handler: ' +
                                'failed to remove original wav: ' +
                                inputWav, logging.warning)

    #
    # no point continuing execution after hangup.
    #
    sys_exit(0)
def email_selections(emailAddrs, attach, comments='', urlFields=None):
    """called by views.email_selection()."""

    returnMsg = ''


    #
    # display the email addresses.
    #
    returnMsg = dsh_utils.black_break_msg('<i><u>email(s) sent to:</u></i>\n')
    for email in emailAddrs:
        returnMsg += dsh_utils.black_break_msg(email)
    returnMsg += '<BR>\n'


    #
    # deal with comments: display them, include them.
    #
    emailText = ''
    if comments:
        returnMsg += '<i><u>comments:</u></i><br>\n'
        returnMsg += comments
        returnMsg += '<br><br>'
        emailText = '[comments:]\n\n%s\n' % (comments,)
        emailText += '\n---------------\n\n'


    #
    # now loop through all the selected items.
    #
    returnMsg += dsh_utils.black_break_msg('<i><u>items sent:</u></i><br>\n')
    
    selectedItems = dv2.db.models.Item.objects.filter(u17=True)
    if not selectedItems:
        returnMsg += dsh_utils.red_error_break_msg(
            'no item selected currently.')
        return returnMsg

    #
    # 09/11/14:
    # reverse it so it's in reverse chronological order.
    # for some reason, this didn't work...
    #
    #selectedItems.reverse()
    

    count = 0
    displayText = '<TABLE border=1>\n'
    fileList = []
    attachedFileList = []
    

    #
    # 09/11/14:
    # reverse it so it's in reverse chronological order.
    #
    for item in selectedItems[::-1]:

        emailText += smart_unicode(item.email_text(attach=attach,
                                                   urlFields=urlFields))
        emailText += '\n---------------\n\n'

        
        displayText += '<TR><TD>%s</TD></TR>\n' % \
                       (item.email_text(br=True, attach=attach,
                                        urlFields=urlFields,
                                        allowTags=True),)

        if attach:
            file = item.full_file_path()
            attachedFile = item.attachment_file_name()
        
            if file and attachedFile:
                fileList.append(file)
                attachedFileList.append(attachedFile)
            
    displayText += '</TABLE>\n'
    returnMsg += smart_unicode(displayText)
    
    returnMsg += dsh_utils.black_break_msg_debug('', 118)
    returnMsg += dsh_utils.black_break_msg_debug(repr(fileList), 118)
    returnMsg += dsh_utils.black_break_msg_debug('', 118)
    returnMsg += dsh_utils.black_break_msg_debug(repr(attachedFileList), 118)

    emailText = smart_unicode(emailText)
    emailText = smart_str(emailText)


    #
    # got everything.  ready to actually call gmail_send().
    #
    try:
        success,errorMsg = dsh_utils.gmail_send(
            dsh_config.lookup('GMAIL_SENDER_ADDRESS'),
            dsh_config.lookup('GMAIL_SENDER_PASSWORD'),
            emailAddrs,
            dsh_config.lookup('GMAIL_SENDER_SUBJECT'),
            emailText,
            attachedFiles=fileList,
            attachmentNames=attachedFileList)
        if success:
            message = 'selection emailed to: %s.  comments: %s.' %\
                      (', '.join(emailAddrs), comments)
            dsh_agi.report_event(message, action='EMAI')
            returnMsg += '<br>' + dsh_utils.black_break_msg('Message sent.')
        else:
            dsh_django_utils.error_event(errorMsg, errorLevel='ERR')
            returnMsg += '<br>' + dsh_utils.red_error_break_msg(errorMsg)
    except:
        message = 'dsh_selection.email_selections: gmail_send() failed. ' +\
                  'Unexpected error.  Tell Randy about this page.'
        dsh_django_utils.error_event(message, errorLevel='ERR')
        returnMsg += '<br>' + dsh_utils.red_error_break_msg(message)
        
    return returnMsg
def stats_calculate(sortBy=None, logAction='STT2', textLog=False):
    """called by views.stats().
    possible values of sortedBy are:
    'recorded'
    'items'
    'callsnorec'
    'calls'
    'starred'
    'recdur'
    'calldur'
    returns (success,response,totals)
    when triggered from daily cron job in dsh_stats_log,
    logAction=='STT1' and textLog=True.
    otherwise, the default value here.
    """

    #
    # fill the tuple list of people and their counts.
    #
    people = dvoice.db.models.Person.objects.all()
    tupleList = []
    for person in people:
        tuple = person_tuple_list(person)
        tupleList.append(tuple)
        

    #
    # what key do we sort it by? and sort it!
    #
    if not sortBy:
        sortBy = dsh_config.lookup('STATS_SORT_BY')

    sortKey = sort_key(sortBy)
    if not sortKey:
        resp = dsh_utils.red_error_break_msg('invalid sort field: ' +
                                             repr(sortBy))
        return (False, resp, None)
        
    sortedTupleList = sorted(tupleList, key=sortKey, reverse=True)


    #
    # just prints a message at the beginning of the page.
    #
    sortStr = sortBy
    if sortBy == 'callsnorec':
        sortStr = 'calls without recording'
    elif sortBy == 'recdur':
        sortStr = 'record duration'
    elif sortBy == 'calldur':
        sortStr = 'call duration'

    response = ''
    response += dsh_utils.black_break_msg(
        'click the column headings to sort by different criteria.')
    response += dsh_utils.black_break_msg(
        'currently sorted by <b><i>%s</i></b>:' % (sortStr,))
    response += '<BR>'


    #
    # table header.
    #
    i = 1
    response += '<TABLE border=1>\n'
    response += table_header()

    #
    # to be replaced.
    #
    response += '<!-- total row -->'

    #
    # the body of the table.
    #
    totals = (0, 0, 0, 0, 0, 0, 0)
    for tuple in sortedTupleList:
        oneRow,totals = one_row(tuple, i, totals)
        response += oneRow
        i += 1

    totalRow = total_row(totals)
    response += totalRow
    response += table_header()
    
    response += '</TABLE>'

    response = response.replace('<!-- total row -->', totalRow)

    log_event(totals, logAction=logAction, textLog=textLog)
    return (True, response, totals)
}



def lookup(what):
    return config[what]



import sys,dsh_django_utils2
dsh_django_utils2.append_to_sys_path(lookup('DSH_VOICE_CODE_DIR'))
import dsh_config



config['PHONE_DATA_DJANGO_PATH'] = dsh_config.lookup('PHONE_DATA_DJANGO_PATH')
config['HIDE_PHONE_DIGITS'] = dsh_config.lookup('HIDE_PHONE_DIGITS')
#config['PERSON_URL'] = dsh_config.lookup('PERSON_URL')
config['RECORDED_THRESH'] = dsh_config.lookup('RECORDED_THRESH')
import os
os.environ['DJANGO_SETTINGS_MODULE'] = dsh_config.lookup(
    'DJANGO_SETTINGS_MODULE')


import datetime
config['YEAR'] = datetime.datetime.now().strftime('%Y')


#
# used as the footer of pages generated by views.py
#