def verify_ffmpeg_existence(RepositoryRoot):
    commandPath = r'/usr/bin/ffmpeg'
    if dsh_utils.is_valid_file(commandPath, 'verify_ffmpeg_existence'):
        return commandPath
    dsh_utils.give_news('Cannot find ffmpeg.  Advise you to install it.',
                  logging.info)
    return None
def verify_ffmpeg_existence(RepositoryRoot):
    commandPath = os.path.join(RepositoryRoot, FFMPEG_PATH_SUFFIX)
    if dsh_utils.is_valid_file(commandPath, 'verify_ffmpeg_existence'):
        return commandPath
    dsh_utils.give_news('Cannot find ffmpeg.  Advise you to install it.',
                  logging.info)
    return None
Exemple #3
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 sys_exit(code):
    """a wrapper for sys.exit()"""

    #
    # repeats the caller info: phone number, school, name.
    #
    if globals4signal.has_key('log_str'):
        logStr = globals4signal['log_str']
    else:
        logStr = ''

    #
    # compute the duration of the call.
    #
    endTime = datetime.datetime.now()
    startTime = globals4signal['start_time']
    delta = endTime - startTime
    seconds = delta.seconds
    dsh_utils.db_print('dsh_simple1.sys_exit: call duration: ' +
                       str(seconds) + 's.', 95)
    logStr += str(seconds) + ' || '

    #
    # compute the duration of the recording.
    #
    if globals4signal.has_key('start_record'):
        startRecord = globals4signal['start_record']
        delta = endTime - startRecord
        seconds = delta.seconds
        dsh_utils.db_print('dsh_simple1.sys_exit: record duration: ' +
                           str(seconds) + 's.', 95)
        logStr += str(seconds) + ' ||'

    dsh_utils.give_news('dsh_simple1.sys_exit: ' + logStr, logging.info)
    sys.exit(code)
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)
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 send_command(command, caller="", consoleMsg=True):
    if consoleMsg:
        dsh_utils.give_news(caller + command)
    sys.stdout.write(command)
    sys.stdout.flush()
    result = sys.stdin.readline().strip()
    res = check_result(result, consoleMsg)
    return res
def send_command2(command, caller="", consoleMsg=True):
    """just like send_command(), except it uses check_result2(),
    instead of check_result().  allows non-digit results.
    """
    if consoleMsg:
        dsh_utils.give_news(caller + command)
    sys.stdout.write(command)
    sys.stdout.flush()
    result = sys.stdin.readline().strip()
    res = check_result2(result, consoleMsg)
    return res
def log_event(totals, logAction='STT2', textLog=False):
    """
    puts the stats in the event table.
    """

    message = ('calls: %s, recorded: %s, items: %s, callsnorec: %s, ' +\
               'starred: %s, recdur: %s, calldur: %s') % \
               (str(totals[0]), str(totals[1]), str(totals[2]), str(totals[3]),
                str(totals[4]), str(totals[5]), str(totals[6]))
    dsh_agi.report_event(message, action=logAction)
    if textLog:
        dsh_utils.give_news(message, logging.info)
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 main():
    init_log()

    overWrite = False
    if '--overwrite' in sys.argv:
        overWrite = True
        dsh_utils.give_news('overwrite flag on.')

    dsh_utils.db_print('dsh_load: entered...', 104)
    dsh_dump.load_all(dumpfile.SelectedKeyWords,
                      dumpfile.SelectedOrgs,
                      dumpfile.SelectedPersons,
                      dumpfile.SelectedItems,
                      dumpfile.SelectedEvents,
                      overWrite)
def read_env(consoleMsg=True):
    """reads AGI environment variables at the beginning of a call."""
    env = {}
    while 1:
        line = sys.stdin.readline().strip()
        if line == '':
            break

        
        #
        # ryw:
        # bad format. not splittable.
        # this is because I found a line that looks like this:
        # agi_channel: IAX2/127.0.0.1:35456-14868
        #
        #key,data = line.split(':')
        success,key,data = split_line(line)
        if not success:
            info = 'dsh_agi.read_env: bad line: ' + line
            dsh_utils.give_bad_news2(info, logging.warning)
            continue
            
        if key[:4] <> 'agi_':
            #skip input that doesn't begin with agi_
            info = 'dsh_agi.read_env: invalid key: ' + key[:4]
            dsh_utils.give_bad_news2(info, logging.warning)
            continue
        key = key.strip()
        data = data.strip()
        if key <> '':
            env[key] = data

    keys2skip = ['agi_rdnis', 'agi_uniqueid', 'agi_language', 'agi_callington',
                 'agi_callingtns', 'agi_accountcode', 
                 'agi_enhanced', 'agi_callingpres', 'agi_callingani2',
                 'agi_dnid', 'agi_rdnis', 'agi_priority']
                 
    if consoleMsg:
        info = "dsh_agi.read_env: AGI Environment Dump:"
        dsh_utils.give_news(info, logging.info)
        for key in env.keys():
            if key in keys2skip:
                continue
            info = " -- %s = %s" % (key, env[key])
            dsh_utils.give_news(info, logging.info)

    return env
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 remove_from_current_dial_if_no_message(
    caller, itemTable, keyWordTable, eventTable,
    noLogging=False, sessionID=''):
    """
    called by somewhere from the signal handler in dsh_django2.py.
    see note100331.
    """
    
    dsh_common_db.init_log(quiet=True)

    if not caller.current_dial:
        dsh_utils.db_print('remove_from_current_dial_if_no_message: ' +\
                           'not in CDS.', 165)
        return
    
    hasMessage,whatStr = person_has_any_message_at_all(
        caller, itemTable, keyWordTable, eventTable,
        noLogging=noLogging, sessionID=sessionID)

    if hasMessage:
        dsh_utils.db_print('remove_from_current_dial_if_no_message: ' +\
                           'has messages: ' + whatStr, 165)
        return

    caller.current_dial = False

    try:
        caller.save(noLogging=noLogging)
    except:
        message = 'dsh_common_agi.remove_from_current_dial_if_no_message: ' +\
                  'failed to save person: ' + caller.dsh_uid
        dsh_django_utils.error_event(message, item=person, errorLevel='CRT')
        dsh_utils.give_bad_news(message, reportLevel='CRT')
        return

    message = 'dsh_common_agi.remove_from_current_dial_if_no_message: ' +\
              'removed from current dial: ' + caller.__unicode__()
    dsh_agi.report_event(
        message,
        action='RCDS',
        owner=caller,
        sessionID=sessionID)
    dsh_utils.give_news(message, logging.info)
def hangup_signal_handler(signum, frame):
    """called after the hangup signal is received."""

    global globals4signal
    
    dsh_utils.db_print2('dsh_failed.signal_handler: entered...', 116)
    time.sleep(1)
    
    calleeDshUid = globals4signal['callee_dsh_uid']

    if is_triggered_by_dial_now(calleeDshUid):
        sys.exit(0)
    
    callee = dsh_django_utils.get_foreign_key(Person, calleeDshUid)
    if not callee:
        message = 'dsh_failed: no such callee found: ' + calleeDshUid
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel = 'ERR',
                             sessionID=get_session())
        sys.exit(1)
    else:
        dsh_utils.db_print('dsh_failed: found callee: ' + repr(callee), 116)

    event = Event(
        owner=callee,
        phone_number=callee.phone_number,
        action='NOPU',
        etype='INF',
        description='.call not picked up. re-arming.',
        session=get_session())
    event.save()
    dsh_django_utils.check_auto_timed_calls_for_person(
        callee, sessionID=get_session())

    calleeInfo = dsh_django_utils.callee_info(callee)    
    
    dsh_utils.give_news('dsh_failed.signal_handler: rearming callee: '+\
                        calleeInfo, logging.info)
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 reschedule_script_call(personTable):
    """
    10/03/22:
    called by dsh_reschedule.py
    which is in turn invoked by crontab
    """

    sessionID = dsh_common_db.make_session_id()
    dsh_common_agi.auto_schedule_delete_all(sessionID=sessionID)

    disabled = dsh_db_config.get('auto_dial_disable')
    if disabled:
        count = reschedule_current_dial_set(
            personTable, tinyResponse=True, sessionID=sessionID)
        message = 'dsh_reschedule.py: processing current dial set: ' +\
                  str(count)
        dsh_utils.give_news(message, logging.info)
    else:
        dsh_django_utils.check_auto_timed_calls_for_all_persons(noLogging=True)
        
    message = 'triggered by dsh_reschedule.py.  done'
    dsh_agi.report_event(message, action='RESC', sessionID=sessionID)
    dsh_utils.give_news(message, logging.info)
def is_triggered_by_dial_now(dshUid):
    """
    the indicator is like: '__DIAL_NOW__'
    if this is triggered as "dial now," the indicator is postfixed by
    the real dsh_uid.
    """

    dialNowIndicator = dsh_django_config.lookup("DIAL_NOW_INDICATOR")
    indicLen = len(dialNowIndicator)
    prefix = dshUid[:indicLen]
    postfix = dshUid[indicLen:]

    if prefix == dialNowIndicator:
        #
        # this dot call is triggered as a result of hitting the
        # dial-now icon.  we're not re-arming.
        #
        message = "dsh_failed.is_triggered_by_dial_now: " + postfix
        dsh_agi.report_event(message, sessionID=get_session())
        dsh_utils.give_news(message, logging.info)
        return True

    return False
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)
def sys_exit(code):
    """a wrapper for sys.exit(), logs one line before exiting."""

    callDur,recDur = calculate_durations()

    #
    # repeats the caller info: phone number, school, name.
    #
    if globals4signal.has_key('caller_dude'):
        caller = globals4signal['caller_dude']
        logStr = '|| ' + caller.phone_number + ' || ' + \
                 caller.organization.alias + ' || ' + \
                 caller.__unicode__() + ' || '

        if recDur == None or recDur == 0:
            #
            # we know there's a caller, but there's no recDur.
            # that means the person hung up before recording.
            # we'll put a call without recording in the event table.
            #
            event = Event(
                owner=caller,
                phone_number=caller.phone_number,
                action='CALL',
                etype='INF',
                call_duration=callDur,
                description='hangup before recording.')
            event.save()        
    else:
        logStr = ''

    logStr += str(callDur) + ' || '
    if recDur:
        logStr += str(recDur)

    dsh_utils.give_news('dsh_django1.sys_exit: ' + logStr, logging.info)
    sys.exit(code)
def maybe_deactivate_personal_message(item):
    """if all the intended audience has heard this item,
    de-activate it."""
    allAudience = item.intended_audience.all()
    if not allAudience:
        dsh_utils.db_print('dsh_django1.maybe_deactivate_personal_message: '+\
                           item.dsh_uid, 108)
        return
    for caller in allAudience:
        heardEvents = Event.objects.filter(
            action='HERD',owner=caller.id, dsh_uid_concerned=item.dsh_uid)
        if not heardEvents:
            dsh_utils.db_print(
                'dsh_django1.maybe_deactivate_personal_message: ' +\
                'not heard by this caller yet: ' + caller.phone_number,
                108)
            return

    item.active = False
    item.save()
    message = 'dsh_django1.maybe_deactivate_personal_message: deactivated: '+\
              item.dsh_uid
    dsh_utils.give_news(message, logging.info)
    dsh_agi.report_event(message, item=item)
def lookup_number_in_db(env, debugCheat=False):
    """lookup the caller info in the django database.  returns the tuple
    (pObj, phoneNumber)"""

    if debugCheat:
        env['agi_callerid'] = '06935237794'

    if not env.has_key('agi_callerid'):
        message = 'dsh_django1.lookup_number_in_db: ' + \
                  ' no phone number given by Asterisk.'
        dsh_utils.give_news(message, logging.info)
        dsh_agi.report_event(message, reportLevel='WRN')
        return None
    
    phoneNumber = env['agi_callerid']
    
    persons = Person.objects.filter(phone_number=phoneNumber)
    if not persons:
        message = 'dsh_django1.lookup_number_in_db: ' + \
                  ' phone number not found in database: ' + phoneNumber
        dsh_utils.give_news(message, logging.info)
        dsh_agi.report_event(message, reportLevel='WRN',
                             phone_number=phoneNumber)
        return (None, phoneNumber)

    if len(persons) > 1:
        message = 'dsh_django1.lookup_number_in_db: ' + \
                  'more than one person in the db has this number: ' + \
                  phoneNumber + \
                  ', the list of people are: ' + \
                  repr(persons)
        dsh_utils.give_news(message, logging.info)
        dsh_agi.report_event(message, reportLevel='INF',
                             phone_number=phoneNumber)

    #p = persons[0]
    p = persons.latest()
    answer = (p, phoneNumber)
    dsh_utils.db_print('dsh_django1.lookup_number_in_db: ' +
                       repr(answer), 98)
    return answer
Exemple #23
0
def load_all(allKeyWords, allOrgs, allPersons, allItems, allEvents, allZObject01s, allZObject02s, allZObject03s, allZObject04s, allZObject05s, allZObject06s, allZObject07s, allZObject08s, overWrite):
    """called by dsh_load.py"""

    #
    # key words.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading key words...',
                        logging.info)
    for keyWord in allKeyWords:
        load_one(keyWord, dvoice.db.models.KeyWord, overWrite)

    #
    # organizations.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading organizations...',
                        logging.info)
    for org in allOrgs:
        load_one(org, dvoice.db.models.Organization, overWrite)

    #
    # persons.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading persons...',
                        logging.info)
    for person in allPersons:
        load_one(person, dvoice.db.models.Person, overWrite)

    #
    # items.
    #
    # if this item should not proceed to a second round,
    # put it in the itemsToSkip list.
    #
    itemsToSkip = []
    dsh_utils.give_news('dsh_dump.load_all: loading items...',
                        logging.info)
    for item in allItems:
        load_one(item, dvoice.db.models.Item, overWrite,
                 itemsToSkip=itemsToSkip)

    #
    # load the pointers within the Item table.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading pointers within items...',
                        logging.info)
    for item in allItems:
        load_pointers_for_one(item, dvoice.db.models.Item, overWrite,
                              itemsToSkip)

    #
    # events.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading events...',
                        logging.info)
    for event in allEvents:
        load_one(event, dvoice.db.models.Event, overWrite)

    #
    # zObject01s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject01s...',
		        logging.info)
    for zObject01 in allZObject01s:
	load_one(zObject01, dvoice.db.models.ZObject01, overWrite)


    #
    # zObject02s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject02s...',
		        logging.info)
    for zObject02 in allZObject02s:
	load_one(zObject02, dvoice.db.models.ZObject02, overWrite)


    #
    # zObject03s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject03s...',
		        logging.info)
    for zObject03 in allZObject03s:
	load_one(zObject03, dvoice.db.models.ZObject03, overWrite)



    #
    # zObject04s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject04s...',
		        logging.info)
    for zObject04 in allZObject04s:
	load_one(zObject04, dvoice.db.models.ZObject04, overWrite)


    #
    # zObject05s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject05s...',
		        logging.info)
    for zObject05 in allZObject05s:
	load_one(zObject05, dvoice.db.models.ZObject05, overWrite)


    #
    # zObject06s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject06s...',
		        logging.info)
    for zObject06 in allZObject06s:
	load_one(zObject06, dvoice.db.models.ZObject06, overWrite)


    #
    # zObject07s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject07s...',
		        logging.info)
    for zObject07 in allZObject07s:
	load_one(zObject07, dvoice.db.models.ZObject07, overWrite)


    #
    # zObject08s.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading zobject08s...',
		        logging.info)
    for zObject08 in allZObject08s:
	load_one(zObject08, dvoice.db.models.ZObject08, overWrite)
def main():
    global globals4signal

    globals4signal['start_time'] = datetime.datetime.now()

    #
    # check the voice data directories.
    #
    success,inDir,outDir,outFile = init_dirs()
    if not success:
        sys_exit(1)

    #
    # get the AGI environment variables.
    #
    env = dsh_agi.read_env()
    if env == {}:
        dsh_utils.give_bad_news('dsh_simple1: failed to read agi envs.',
                                logging.error)
        sys_exit(1)

    #
    # log the caller info.
    # and construct a recorded file name based on caller info.
    #
    phoneNumber,callerInfo = lookup_number(env)
    logStr = dsh_map.log_caller_info(phoneNumber, callerInfo)
    globals4signal['log_str'] = logStr
    callerInfoStr = dsh_map.info2str(phoneNumber, callerInfo)
    callerInfoStr = dsh_utils.date_time_rand2() + '_' + callerInfoStr

    #
    # looks like: 090702_200101_38_09935237793_DSH_Randy-Wang.gsm
    #
    dsh_utils.db_print('dsh_simple1: callerInfoStr: ' + callerInfoStr, 94)


    #
    # setting up signal handler for hangup.
    # the handler will attempt to do the file format conversion.
    #
    signal.signal(signal.SIGHUP, hangup_signal_handler)
    

    #
    # play the out file.
    #
    dsh_agi.say_it(outFile)

    #
    # record it.
    #
    inFile = os.path.join(inDir, callerInfoStr)
    globals4signal['in_file'] = inFile
    globals4signal['start_record'] = datetime.datetime.now()
    dsh_agi.record(inFile)

    #
    # say it back.
    #
    #dsh_agi.say_it(inFile)

    dsh_utils.give_news('dsh_simple1: recording done.')

    #
    # convert file format too with a proper hangup (pressing the # key).
    #
    hangup_signal_handler(0, None)
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 main():
    global globals4signal

    globals4signal['start_time'] = datetime.datetime.now()

    init_log()

    #
    # find or create unknown org and unknown person.
    #
    try:
        unknownOrg,unknownPerson = init_unknown_org_person()
    except:
        message = 'dsh_django: init_unknown_org_person failed.'
        dsh_utils.give_bad_news(message, logging.critical)
        dsh_agi.report_event(message, reportLevel='CRT')
        sys_exit(1)

    #
    # get the outgoing voice from the database.
    #
    answer = get_outgoing_voice_from_db()
    if not answer:
        sys_exit(1)
    outVobj,outgoingVoice = answer

    #
    # get the AGI environment variables.
    #
    env = dsh_agi.read_env()
    if env == {}:
        dsh_utils.give_bad_news('dsh_django1: failed to read agi envs.',
                                logging.error)
        sys_exit(1)

    #
    # look up the phone number in the django database.
    # if not found in the database, we do something about unknown callers.
    # XXX
    #lookupResult = lookup_number_in_db(env, debugCheat=True)
    lookupResult = lookup_number_in_db(env)
    caller = determine_unknown_caller(unknownOrg, unknownPerson, lookupResult)
    dsh_utils.db_print('dsh_django1: the caller determined to be: ' +
                       repr(caller), 100)
    globals4signal['caller_dude'] = caller
    
    #
    # setting up signal handler for hangup.
    # the handler will attempt to do the file format conversion.
    # and then saving into the django database.
    #
    signal.signal(signal.SIGHUP, hangup_signal_handler)


    #
    # check whether there're any personalized messages for this caller.
    #
    check_personalized_messages(caller)
    
    
    #
    # play the outgoing file.
    #
    # XXX
    dsh_agi.say_it(outgoingVoice)
    time.sleep(1)
    dsh_agi.say_it('beep')
    dsh_agi.say_it('beep')


    #
    # determine the input file name and record it.
    #
    inVobj,incomingFullName=determine_recorded_file_name(caller, outVobj)
    if incomingFullName == None:
        dsh_utils.give_bad_news(
            'dsh_django1: determine_recorded_file_name failed: ',
            logging.critical)
        sys_exit(1)
    dsh_utils.db_print('dsh_django1: incomingFullName: ' + incomingFullName,
                       101)
    globals4signal['db_in_obj'] = inVobj
    globals4signal['start_record'] = datetime.datetime.now()
    globals4signal['in_file'] = incomingFullName
    dsh_agi.record(incomingFullName)
    dsh_utils.db_print('dsh_django1: record call ends.', 101)
    time.sleep(1)
    dsh_utils.give_news('dsh_django1: recording done.')
    dsh_agi.say_it('auth-thankyou')
    dsh_agi.say_it('vm-goodbye')

    #
    # convert file format too with a proper hangup (pressing the # key).
    #
    hangup_signal_handler(0, None)
def check_personalized_messages(caller):
    """does this caller have any unheard personalized messages?"""

    #
    # does this caller have any personal messages intended for him?
    #
    messages = caller.message_for_me.all()
    dsh_utils.db_print('dsh_django1.check_personalized_message: msg: ' +\
                       repr(messages), 108)
    if not messages:
        return
    
    for msg in messages:
        #
        # the message needs to be "personalized" and it needs to be "active."
        #
        maybe_deactivate_personal_message(msg)
        if not msg.active:
            dsh_utils.db_print('not active.', 108)
            continue
        if msg.itype != 'P':
            dsh_utils.db_print('not personalized: ' + msg.itype, 108)
            continue

        #
        # has this caller heard this before?
        #
        heardEvents = Event.objects.filter(
            action='HERD', owner=caller.id, dsh_uid_concerned=msg.dsh_uid)
        if heardEvents:
            dsh_utils.db_print('already heard, skipping: ' + msg.dsh_uid, 108)
            continue

        #
        # find out the .sln file path name.
        #
        chopped = get_sln_path_for_asterisk(msg)
        dsh_utils.db_print(
            'dsh_django1.check_personalized_message: sln path: ' +\
            repr(chopped), 108)

        if not chopped:
            message = 'dsh_django1.check_personalized_message: ' +\
                      'unable to find .sln file: ' + repr(msg)
            dsh_agi.report_event(message, reportLevel='ERR')
            dsh_utils.give_bad_news(message, logging.error)
            continue

        #
        # now play the personalized message and compute how long it lasted.
        #
        beginTime = datetime.datetime.now()
        dsh_agi.say_it(chopped)
        endTime = datetime.datetime.now()
        time.sleep(1)
        deltaSeconds = (endTime - beginTime).seconds

        #
        # remember the fact that this caller has heard this message.
        #
        dsh_agi.report_event(
            'personalized message heard.',
            item=msg,
            action='HERD',
            phone_number=caller.phone_number,
            owner=caller,
            call_duration=deltaSeconds)
        dsh_utils.give_news('dsh_django1.check_personalized_message: heard: '+\
                            msg.dsh_uid, logging.info)

        #
        # if everyone has heard this personalized message,
        # we should just deactivate it.
        #
        maybe_deactivate_personal_message(msg)

        #
        # beep twice at the end of each message.
        #
        dsh_agi.say_it('beep')
        dsh_agi.say_it('beep')
def load_all(allKeyWords, allOrgs, allPersons, allItems, allEvents, overWrite):
    """called by dsh_load.py"""

    #
    # key words.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading key words...',
                        logging.info)
    for keyWord in allKeyWords:
        load_one(keyWord, dvoice.db.models.KeyWord, overWrite)

    #
    # organizations.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading organizations...',
                        logging.info)
    for org in allOrgs:
        load_one(org, dvoice.db.models.Organization, overWrite)

    #
    # persons.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading persons...',
                        logging.info)
    for person in allPersons:
        load_one(person, dvoice.db.models.Person, overWrite)

    #
    # items.
    #
    # if this item should not proceed to a second round,
    # put it in the itemsToSkip list.
    #
    itemsToSkip = []
    dsh_utils.give_news('dsh_dump.load_all: loading items...',
                        logging.info)
    for item in allItems:
        load_one(item, dvoice.db.models.Item, overWrite,
                 itemsToSkip=itemsToSkip)

    #
    # load the pointers within the Item table.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading pointers within items...',
                        logging.info)
    for item in allItems:
        load_pointers_for_one(item, dvoice.db.models.Item, overWrite,
                              itemsToSkip)

    #
    # events.
    #
    dsh_utils.give_news('dsh_dump.load_all: loading events...',
                        logging.info)
    for event in allEvents:
        load_one(event, dvoice.db.models.Event, overWrite)
def check_new_or_old(dump, whatKind, overWrite, itemsToSkip=None):
    """upon loading, see if we need to make a new object, or
    we are overwriting an existing old object.
    returns (success, newObj, obj)
    called by load_one() and load_pointers_for_one()"""

    #
    # check the dsh_uid.
    # to see if it's already in the database.
    #
    if not dump.has_key('dsh_uid'):
        dsh_utils.give_bad_news('dsh_dump.check_new_or_old: ' + \
                                'failed to find dsh_uid',
                                logging.critical)
        return (False, False, None)

    dshUid = dump['dsh_uid'][1]

    existingObjs = whatKind.objects.filter(dsh_uid=dshUid)
    howMany = len(existingObjs)
    if howMany > 1:
        dsh_utils.give_bad_news(
            'dsh_dump.check_new_or_old: found multiple dsh_uids: ' + \
            dshUid, logging.critical)
        if itemsToSkip != None:
            itemsToSkip.append(dshUid)
        return (False, False, None)


    #
    # if it's already in the database...
    #
    if howMany == 1:
        dsh_utils.db_print('dsh_dump.check_new_or_old: dsh_uid found 1: ' + \
                           dshUid, 105)
        if not overWrite:
            #
            # give up if we don't want to overwrite it.
            #
            dsh_utils.give_news(
                'dsh_dump.check_new_or_old: not overwriting dsh_uid: ' + \
                dshUid, logging.info)
            if itemsToSkip != None:
                itemsToSkip.append(dshUid)
            return (True, False, None)

        #
        # we will overwrite the existing object.
        #
        dsh_utils.give_news(
            'dsh_dump.check_new_or_old: ' + \
            'overwriting dsh_uid: ' + dshUid, logging.info)
        obj = existingObjs[0]
        return (True, False, obj)
    else:
        #
        # it's not in the existing database.
        # so we'll make a new one.
        #
        dsh_utils.give_news('dsh_dump.check_new_or_old: dsh_uid to save: ' + \
                            dshUid, logging.info)
        obj = whatKind()
        return (True, True, obj)
def hangup_signal_handler(signum, frame):
    """attempt to do file format conversion upon a hangup.
    from .wav to .mp3.
    after conversion, we put it in the django database."""
    
    dsh_utils.db_print2('dsh_django1.signal_handler: entered...', 101)


    #
    # get the name of the file that was just recorded.
    #
    if not globals4signal.has_key('in_file'):
        dsh_utils.give_news('dsh_django1.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':
        message = 'dsh_django1.hangup_signal_handler: ' + \
                  "can't convert non-wav file: " + inputFile
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel='ERR')
        sys_exit(1)


    #
    # 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:
        message = 'dsh_django1.hangup_signal_handler: ' + \
                  'no input file to convert: ' + \
                  inputWav
        dsh_utils.give_news(message, logging.info)
        #
        # looks like we could get this far even if there's
        # a hangup before record.  that's because the
        # signal doesn't seem to be delivered fast enough.
        # so globals4signal['in_file'] gets set anyhow.
        #
        #dsh_agi.report_event(message, reportLevel='ERR')
        sys_exit(1)
    if bytes == 0:
        message = 'dsh_django1.hangup_signal_handler: ' + \
                  'inputfile size 0: ' + inputWav
        dsh_utils.give_news(message, logging.info)
        dsh_agi.report_event(message, reportLevel='WRN')
        sys_exit(1)

    dsh_utils.db_print2('dsh_django1.signal_handler: ready to convert: ' +
                        inputWav, 101)


    #
    # where's the lame binary?
    #
    lamePath = dsh_config.lookup('lame_location')
    if not dsh_utils.is_valid_file(lamePath,
                                   msg='dsh_django1.hangup_signal_handler:'):
        message = 'dsh_django1.hangup_signal_handler: ' + \
                  'need to install lame.'
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel='CRT')
        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

    try:
        ret = subprocess.call(command, shell=True,
                              stdout=stdout, stderr=stderr)
    except:
        ret = -1
        
    if ret != 0:
        message = 'dsh_django1.signal_handler: ' + \
                  'error in format conversion: ' + \
                  command
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel='CRT')
        sys_exit(1)

    dsh_utils.give_news('dsh_django1.signal_handler: conversion success: ' +
                        command, logging.info)

    dsh_utils.chmod_tree2(outputMp3, recurse=False)
    
    if not dsh_utils.cleanup_path(inputWav, 'dsh_django1.signal_handler'):
        message = 'dsh_django1.signal_handler: ' + \
                  'failed to remove original wav: ' + \
                  inputWav
        dsh_utils.give_bad_news(message, logging.warning)
        dsh_agi.report_event(message, reportLevel='WRN')


    #
    # calculate some more fields for saving in the database.
    #
    callDur,recDur = calculate_durations()
    dsh_utils.db_print2('dsh_django1.signal_handler: durations are: ' +
                        str(callDur) + ', ' + str(recDur), 101)


    #
    # dirPrefix is: /u/rywang/phone_data/django/
    # chop that off.
    # so what's left is:  /media/voice/09/07/090729_215817_85983050_08935237794_unknown-org_no-name.mp3
    # no, need to chop of '/media/' as well!
    # otherwise deletes don't work!
    #
    dirPrefix = dsh_config.lookup('PHONE_DATA_DJANGO_PATH')
    choppedFileName = outputMp3.replace(dirPrefix, '/')
    #chopAbsURLPrefix = dsh_config.lookup('ABS_URL_PREFIX_CHOP')
    #choppedFileName = choppedFileName.replace(chopAbsURLPrefix, '')
    choppedFileName = dsh_agi.abs_url_to_relative(choppedFileName)
    dsh_utils.db_print2('dsh_django1.signal_handler: choppedFileName is: '+\
                        choppedFileName, 105)


    #
    # FINALLY save the object in the django database!
    #
    item = globals4signal['db_in_obj']
    item.file = choppedFileName
    item.call_duration = callDur
    item.rec_duration = recDur
    try:
        item.save()
        dsh_utils.db_print2('dsh_django1.signal_handler: item saved: ' +
                            choppedFileName, 101)
    except:
        message = 'dsh_django1.signal_handler: saving in django failed: ' + \
                  choppedFileName, 101
        dsh_utils.give_bad_news(message, logging.critical)
        dsh_agi.report_event(message, reportLevel='CRT')
        sys_exit(1)

    #
    # no point continuing execution after hangup.
    #
    sys_exit(0)