def main():
    global globals4signal

    globals4signal["session_id"] = dvoice.db.models.assign_dsh_uid()

    dsh_django2.init_log("dsh_failed: entered, session %s --------------------" % (get_session(),))

    #
    # get the AGI environment variables.
    # chicken out if it's not due to .call failure.
    #
    env = dsh_agi.read_env()
    if env == {}:
        message = "dsh_failed: failed to read agi envs."
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel="ERR", sessionID=get_session())
        sys.exit(1)

    if not env.has_key("agi_channel"):
        message = "dsh_failed: no agi_channel."
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel="ERR", sessionID=get_session())
        sys.exit(1)

    if env["agi_channel"] != "OutgoingSpoolFailed":
        message = "dsh_failed: unexpected agi_channel: " + env["agi_channel"]
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel="ERR", sessionID=get_session())
        sys.exit(1)

    dsh_config.init(env)

    #
    # get the dsh_uid of the callee from the command argument.
    #
    dsh_utils.db_print("dsh_failed: arguments are: " + repr(sys.argv), 116)
    if len(sys.argv) < 2:
        message = "dsh_failed: not enough arguments."
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel="ERR", sessionID=get_session())
        sys.exit(1)

    calleeDshUid = sys.argv[1].strip()
    if not calleeDshUid:
        message = "dsh_failed: no dshUid found."
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel="ERR", sessionID=get_session())
        sys.exit(1)

    dsh_utils.db_print("dsh_failed: calleeDshUid: " + calleeDshUid, 116)
    globals4signal["callee_dsh_uid"] = calleeDshUid

    #
    # let's sever ties with Asterisk.
    # this ensures the old .call file is deleted.
    #
    signal.signal(signal.SIGHUP, hangup_signal_handler)
    dsh_agi.send_command("HANGUP\n", caller="dsh_failed:")

    sys.exit(0)
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)
示例#3
0
def free_MB(path):
    """returns the amount of available space in MB. used to be in ryw.py"""

    #tested.
    dsh_utils.db_print('ryw_xp:free_MB() entered...', 49)
    
    path = os.path.normpath(path)
    if not dsh_utils.try_mkdir_ifdoesnt_exist(path, 'free_MB'):
        dsh_utils.give_bad_news(
            'free_MB: try_mkdir_ifdoesnt_exist failed: ' + path,
            logging.critical)
        return 0
        
    try:
        sectorsPerCluster,bytesPerSector,numFreeClusters,totalNumClusters = \
            win32file.GetDiskFreeSpace(path)
    except:
        dsh_utils.give_bad_news(
            'fatal_error: failed to determine free disk space: '+path,
            logging.critical)
        return 0
    
    sectorsPerCluster = long(sectorsPerCluster)
    bytesPerSector = long(bytesPerSector)
    numFreeClusters = long(numFreeClusters)
    totalNumClusters = long(totalNumClusters)
    freeMB = (numFreeClusters * sectorsPerCluster * bytesPerSector) / \
             (1024 * 1024)
    return freeMB
def patch_caller_as_DIET(caller, keyWordStr, keyWordTable, sessionID):
    """called by handle_staff_caller().
    pretend the caller to be for DIET.
    patch its organization to add a DIET flag.
    somewhat modeled after: get_active_broadcast_item().
    returns the patched caller.
    """

    keyWords = keyWordTable.objects.filter(key_word=keyWordStr)
    if keyWords:
        dsh_utils.db_print(
            'patch_caller_as_DIET: found keyword: '+ \
            repr(keyWords), 136)
        keyWord = keyWords[0]
    else:
        message = 'dsh_common_test.patch_caller_as_DIET: ' + \
                  'failed to locate this key word: ' + keyWordStr
        dsh_utils.give_bad_news(message, logging.error)
        dsh_agi.report_event(message, reportLevel='ERR',
                             sessionID=sessionID)
        return None

    caller.organization.org_key_word = keyWord
    dsh_utils.db_print('patch_caller_as_DIET: caller patched!', 136)
    return caller
def sound_exists(prefix):
    """see if prefix.gsm or prefix.sln exists."""
    if dsh_utils.is_valid_file(prefix + '.sln', 'dsh_utils.sound_exists:',
                               silent=True) or \
       dsh_utils.is_valid_file(prefix + '.gsm', 'dsh_utils.sound_exists:',
                               silent=True):
        return True
    dsh_utils.give_bad_news('dsh_simple1.sound_exists: no out file: ' +
                            prefix, logging.error)
    return False
def check_personalized_followup_to(caller, msg, sessionID,
                                   sayPersonNameFunc=None):
    """
    called by dsh_django2.check_personalized_messages().
    if the followup_to field of the personalized message points
    to caller himself, we want to play the original question
    that resulted in this personalized message.
    modeled after check_personalized_messages().
    sayPersonNameFunc is dsh_django2.say_message_from_name().
    """

    dsh_utils.db_print('check_personalized_followup_to: entered.', 151)
    if not msg or not caller or not msg.owner:
        dsh_utils.db_print('check_personalized_followup_to: nulls.', 151)
        return
    
    question = msg.followup_to
    if not question:
        dsh_utils.db_print('check_personalized_followup_to: no followup_to.',
                           151)
        return

    if question.owner.dsh_uid != caller.dsh_uid:
        #dsh_utils.db_print('check_personalized_followup_to: not same owner.',
        #                   151)
        #return
        pass

    if question.owner.ptype != 'USR':
        #
        # we will read the question back ONLY if the question
        # was left by a "user."
        #
        dsh_utils.db_print('check_personalized_followup_to: '+\
                           'question not by user type.', 151)
        return

    chopped = get_sln_path_for_asterisk(question)
    if not chopped:
        message = 'dsh_common_agi.check_personalized_followup_to: ' +\
                  'unable to find .sln file: ' + repr(question)
        dsh_agi.report_event(message, reportLevel='ERR', sessionID=sessionID)
        dsh_utils.give_bad_news(message, logging.error)
        return

    say_date(question)

    if sayPersonNameFunc:
        dsh_utils.db_print('check_personalized_followup_to: saying name.', 151)
        sayPersonNameFunc(question.owner)

    dsh_agi.say_it(chopped)
    dsh_agi.say_it('beep')
示例#7
0
def launch_explorer(path):
    """from explorer.launchExplorer()"""
    command = r"explorer"
    options = ["/n,","/root,",path]
    dsh_utils.db_print('launch_explorer: command is: ' +
                 repr([command] + options), 46)
    ret = subprocess.call([command] + options)
    if ret != 1:
        dsh_utils.give_bad_news("launch_explorer: Error in launching explorer.",
                          logging.error)
        return False
    return True
def chop_prefix_digits_for_local(callNum, callee):
    """
    10/02/02: chopping of the leading zero is moved from
    dsh_django_utils.generate_dot_call_file().
    also adding code to remove 0522.
    """

    dsh_common_db.init_log(quiet=True)

    #if callee.phone_std:
        #
        # 10/03/13:
        # dial as is.
        #
        #return callNum

    dsh_utils.db_print(
        'chop_prefix_digits_for_local: enter: callNum: ' + callNum, 152)
    if len(callNum) > 1 and (not callee.phone_std) and \
       (not callee.phone_landline) and callNum[0] == '0' and \
       (callNum[1] == '9' or callNum[1] == '8'):
        #
        # it looks like Asterisk doesn't like the leading 0
        # for cell phone numbers, chop it off.
        # 10/03/14:
        # now dealing with phone numbers that start with 8.
        #
        callNum = callNum[1:]
        dsh_utils.db_print(
            'chop_prefix_digits_for_local: return1: callNum: ' + callNum, 152)
        return callNum

    localLandLinePrefix = dsh_db_config.get('local_land_line_prefix')
    if not localLandLinePrefix:
        message = 'chop_prefix_digits_for_local: no local land line prefix.'
        dsh_utils.give_bad_news(message, logging.warning)
        dsh_agi.report_event(message, reportLevel='WRN')
        #
        # try_remove_prefix() will deal with null prefix
        # so no need to worry about anything else than logging message.

    #
    # 10/03/14:
    # should look at the callee.phone_landline flag.
    # but I'm not: it's still legit to look for 0522 and kill it
    # even if it was not explicitly marked as a landline.
    #
    callNum = try_remove_prefix(callNum, localLandLinePrefix)

    dsh_utils.db_print(
        'chop_prefix_digits_for_local: returned ' + callNum, 152)
    return callNum
示例#9
0
def stdio_logs_open(logDirectory=''):
    """called by launch_explorer(), redirects stdout and stderr.
    so they don't get sent to the browser window."""

    if logDirectory == '':
        logDir = os.path.join(RepositoryRoot, 'WWW', 'logs')
    else:
        logDir = logDirectory

    try:
        stdout = open(os.path.join(logDir, 'stdout.txt'), 'a')
        stderr = open(os.path.join(logDir, 'stderr.txt'), 'a')
        return [stdout, stderr]
    except:
        dsh_utils.give_bad_news('stdio_logs_open: failed to open log files.',
                          logging.error)
        return None
示例#10
0
def determine_recorded_file_name(caller, outgoingItem):
    #
    # I need to make a new item because that's where the new dsh_uid is.
    #
    item = Item(
        owner=caller,
        itype='I',
        followup_to=outgoingItem)

    #
    # the name has to be computed for placing in the django database.
    # so it's not done lightly.
    #
    incomingFullName = dsh_agi.make_full_unique_filename(
        item.dsh_uid,
        '',
        phoneNumber=caller.phone_number,
        orgAlias=caller.organization.alias,
        name=caller.__unicode__(),
        startWithRoot=True,
        uploadType='asterisk')

    dirName = os.path.dirname(incomingFullName)
    if not dsh_utils.try_mkdir_ifdoesnt_exist(
        dirName, 'dsh_django1.determine_recorded_file_name: '):
        message = 'dsh_django1.dsh_utils.try_mkdir_ifdoesnt_exist failed: '+\
                  dirName
        dsh_utils.give_bad_news(message, logging.critical)
        dsh_agi.report_event(message, reportLevel='CRT')
        return (item, None)

    dsh_utils.chmod_tree2(dirName, recurse=False)

    slnDir = os.path.join(dirName, 'sln')
    if not dsh_utils.try_mkdir_ifdoesnt_exist(
        slnDir, 'dsh_django1.determine_recorded_file_name: '):
        message = 'dsh_django1.dsh_utils.try_mkdir_ifdoesnt_exist failed: '+\
                  'on slnDir: ' + slnDir
        dsh_utils.give_bad_news(message, logging.critical)
        dsh_agi.report_event(message, reportLevel='CRT')
        return (item, None)
    dsh_utils.chmod_tree2(slnDir, recurse=False)
    
    return (item,incomingFullName)
def test_call_say_time(caller):
    """called by handler_staff_caller().
    test spoken dates.
    """

    dsh_utils.db_print('test_call: entered...', 134)
    answer = dsh_django2.get_outgoing_voice_from_db(caller)
    if not answer:
        dsh_utils.give_bad_news(
            'test_call: get_outgoing_voice_from_db() failed.',
            logging.critical)
        return False
    outVobj,outgoingVoice,allSharedHeard,playShared = answer
    dsh_utils.db_print('test_call: outgoingVoice: ' + outgoingVoice, 134)
    time = outVobj.modify_datetime
    timeStr = time.strftime('%#Y-%#m-%#d')
    dsh_utils.db_print('test_call: timeStr: ' + timeStr, 134)
    dsh_common_agi.say_date(outVobj)
    return True
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 field_to_sln_path(field, sessionID=None):
    """
    moved from dsh_django2.py
     fix up the file name: from the database, it's an mp3 URL.
     django should have taken the trouble of converting it to sln alredy.
     we call some function to get the path name of the sln file.
    """
    
    #mp3FilePath = item.file.url
    mp3FilePath = field.url
    pathStuff = dsh_agi.figure_out_sln_names(mp3FilePath)
    if not pathStuff:
        message = 'dsh_django1.get_sln_path_for_asterisk: ' + \
                  'failed to find path stuff for: ' + repr(mp3FilePath)
        dsh_agi.report_event(message, reportLevel='CRT',
                             sessionID=sessionID)
        dsh_utils.give_bad_news(message, logging.critical)
        return None
    slnDir,slnBaseName,wavBaseName,fullSlnName,fullWavName = pathStuff
    dsh_utils.db_print('dsh_django1.get_sln_path_for_asterisk: ' +
                       fullSlnName, 97)

    #
    # do a sanity check of the .sln file.
    #
    if not dsh_utils.is_valid_file(fullSlnName, msg='', silent=True):
        message = 'dsh_django.get_sln_path_for_asterisk: ' + \
                  'not a valid file: ' + fullSlnName
        dsh_agi.report_event(message, reportLevel='ERR',
                             sessionID=sessionID)
        dsh_utils.give_bad_news(message, logging.error)
        return None
    
    #
    # Asterisk doesn't like to be told the .sln extension so get rid of it.
    #
    chopped = fullSlnName.replace('.sln', '')
    dsh_utils.db_print('dsh_django1.get_sln_path_for_asterisk: success: ' +
                       chopped, 108)
    return chopped
示例#14
0
def launch_explorer(path):
    """from explorer.launchExplorer()"""

    #
    # If I don't redirect stdout and stderr,
    # this stuff gets sent to the browser window.
    #
    pair = stdio_logs_open()
    if pair:
        stdout = pair[0]
        stderr = pair[1]
    else:
        stdout = None
        stderr = None


    if os.path.exists('/usr/local/bin/rox'):
        dsh_utils.db_print_info_browser('launch_explorer: found rox.', 91)
        command = '/usr/local/bin/rox '
    elif os.path.exists('/usr/bin/thunar'):
        dsh_utils.db_print_info_browser('launch_explorer: found thunar.', 91)
        command = '/usr/bin/thunar --display :0.0 '
    else:
        dsh_utils.give_bad_news("launch_explorer: can't find an explorer.",
                          logging.error)
        return False
        
    command = command + path + ' &'
    dsh_utils.db_print_info_browser(
        'launch_explorer: command is: ' + command, 91)
    ret = subprocess.call(command, shell=True, stdout=stdout, stderr=stderr,
                          env={'DISPLAY':':0.0'})

    stdio_logs_close(pair)
    
    if ret != 0:
        dsh_utils.give_bad_news('launch_explorer: error in launching explorer.',
                          logging.error)
        return False
    return True
示例#15
0
def get_outgoing_voice_from_db():
    #
    # look up in the django database.
    # look for items that are "active" and are of the "broadcast" type.
    #
    activeBroadcastItems = Item.objects.filter(active=True, itype='B')
    if not activeBroadcastItems:
        message = 'dsh_django1.get_outgoing_voice_from_db: ' + \
                  'no currently active broadcast message.'
        dsh_agi.report_event(message, reportLevel='ERR')
        dsh_utils.give_bad_news(message, logging.error)
        return None
    
    item = activeBroadcastItems[0]
    dsh_utils.db_print('dsh_django1.get_outgoing_voice_from_db: ' +
                       repr(item), 97)

    chopped = get_sln_path_for_asterisk(item)
    if chopped == None:
        return None
        
    return (item,chopped)
示例#16
0
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 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)
示例#18
0
def get_foreign_key_list(whatKind, dshUidList, required=False):
    """called by load_one().  locate a list of foreign key objects.
    like a list of key words."""

    ansList = []
    for dshUid in dshUidList:
        obj = get_foreign_key(whatKind, dshUid)
        if not obj:
            if required:
                dsh_utils.give_bad_news(
                    'dsh_dump.get_foreign_key_list: missing required obj :'+\
                    dshUid, logging.error)
                return None
            #
            # if it's not required and we can't find it in the list.
            # this is like a missing key word, not a big deal.
            # but perhaps I should warn.
            #
            dsh_utils.give_bad_news(
                'dsh_dump.get_foreign_key_list: missing optional obj: ' +\
                dshUid, logging.warning)
            continue
        ansList.append(obj)
    return ansList
示例#19
0
def dos2unix(fileName):
    """called during reformant_ntfs.py."""

    commandPath = '/usr/bin/dos2unix'
    if not os.path.exists(commandPath):
        dsh_utils.give_bad_news("ryw_linux.dos2unix: dos2unix doesn't exist. " +
                          "should fix this: apt-get install tofrodos.",
                          logging.error)
        return False

    command = commandPath + ' ' + fileName
    ret = subprocess.call(command, shell=True)

    if ret != 0:
        dsh_utils.give_bad_news(
            'ryw_linux.dos2unix: error in running dos2unix: ' +
            fileName, logging.error)
        return False
    else:
        dsh_utils.db_print_info_browser(
            'ryw_linux.dos2unix: dos2unix success: ' +
            fileName, 69)

    return True
示例#20
0
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)
示例#21
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)
示例#22
0
def load_pointers_for_one(dump, whatKind, overWrite, itemsToSkip):
    """going through the dumped object the second round to
    set all the pointers within.
    for example, the 'followup_to' field in the Item table.
    """
    
    dsh_utils.db_print('dsh_dump.load_pointers_for_one: entered... ' +\
                       repr(dump), 105)

    if not dump.has_key('dsh_uid'):
        return False
    dshUid = dump['dsh_uid'][1]

    #
    # this means that the first round of loading items has decided that
    # this item should not proceed to a second round.
    #
    if dshUid in itemsToSkip:
        return True

    #
    # set the "overWrite" arg to True.
    #
    success,newObj,obj = check_new_or_old(dump, whatKind, True)
    if not success or obj == None:
        dsh_utils.give_bad_news(
            'dsh_dump.load_pointers_for_one: check_new_or_old failed.',
            logging.error)
        return success


    #
    # take all the fields from the dump file.
    #
    for fieldName,fieldContent in dump.iteritems():
        
        fieldType,fieldValue = fieldContent

        if fieldType == 'OptionalFollowUpsType':
            #
            # fieldValue is a dsh_uid.
            # get the item that has this dsh_uid.
            #
            followItem = get_foreign_key(
                dvoice.db.models.Item, fieldValue)
            if not followItem:
                dsh_utils.give_bad_news(
                    'dsh_dump.load_pointers_for_one: ' + \
                    'cannot find followup_to item: '+\
                    fieldValue, logging.error)
                #
                # because it's optional, we'll just move on.
                # not a big deal.
                #
                continue
            setattr(obj, fieldName, followItem)
            continue

        if fieldType == 'OptionalKeyWordsType':
            #
            # instead of a single foreign key,
            # now we're dealing with a list of foreign keys
            # in a many-to-many relationship.
            #
            # this also has to be dealt with in a second round because...
            # it turns out I must do a save to obtain a primary key,
            # otherwise I can't set many-to-many attr.
            # and unfortunately, the dump "spec," which is just a dictionary,
            # when you iterate through it, it goes in an unpredictable order,
            # so the owner and such required keys could be encountered after
            # this field.
            # this is why this field is moved here.
            #
            keyWords = get_foreign_key_list(dvoice.db.models.KeyWord,
                                            fieldValue)
            if keyWords == None:
                #
                # this shouldn't happen. in the worst case, it should've
                # been an empty list.
                #
                dsh_utils.give_bad_news(
                    'dsh_dump.load_one: something bad happened with ' +\
                    'loading key words: ' + repr(keyWords),
                    logging.critical)
                continue
            if keyWords == []:
                continue
            #
            # it turns out I must do a save to obtain a primary key,
            # otherwise I can't set many-to-many attr.
            #
            #if newObj:
            #    obj.save()
            setattr(obj, fieldName, keyWords)
            continue
            
        if fieldType == 'OptionalPersonsType':
            #
            # like the KeyWord type above.
            # I should've tried to reduce repetition.
            #
            audience = get_foreign_key_list(dvoice.db.models.Person,
                                            fieldValue)
            if audience == None:
                #
                # this shouldn't happen. in the worst case, it should've
                # been an empty list.
                #
                dsh_utils.give_bad_news(
                    'dsh_dump.load_one: something bad happened with ' +\
                    'loading audience: ' + repr(audience),
                    logging.critical)
                continue
            if audience == []:
                continue
            #
            # it turns out I must do a save to obtain a primary key,
            # otherwise I can't set many-to-many attr.
            #
            #if newObj:
            #    obj.save()
            setattr(obj, fieldName, audience)
            continue
            

        #
        # do nothing with any other types of fields.
        #

    #
    # finally, put it in the django database.
    #
    try:
        obj.save()
        dsh_utils.db_print('dsh_dump.load_pointers_for_one: obj is saved.',
                           105)
    except:
        dsh_utils.give_bad_news(
            'dsh_dump.load_pointers_for_one: obj.save() failed: ' +\
            dshUid, logging.critical)
        return False

    return True
示例#23
0
def load_one(dump, whatKind, overWrite, itemsToSkip=None):
    """called by dsh_load.py, to load one dumped object into the django db.
    'dump' is a dictionary, read from the dump file. of the form:
    fieldName: [fieldType, fieldValue],
    'whatKind' is the Class.  like: KeyWord, Organization, Person, Item.
    """
    
    dsh_utils.db_print('dsh_dump.load_one: entered... ' + repr(dump), 105)
    
    success,newObj,obj = check_new_or_old(dump, whatKind, overWrite,
                                          itemsToSkip=itemsToSkip)
    if not success or obj == None:
        return success
    dshUid = dump['dsh_uid'][1]


    #
    # take all the fields from the dump file.
    #
    for fieldName,fieldContent in dump.iteritems():
        
        fieldType,fieldValue = fieldContent

        #
        # some fields take some work to load.
        #
        if fieldType == 'RequiredForeignOrgType':
            #
            # fieldValue is a dsh_uid.
            # get the org that has this dsh_uid.
            #
            org = get_foreign_key(dvoice.db.models.Organization, fieldValue)
            if not org:
                dsh_utils.give_bad_news(
                    'dsh_dump.load_one: failed on RequiredForeignOrgType: '+\
                    fieldValue, logging.error)
                #
                # because it's a required field,
                # there's no point continuing---loading is aborted.
                #
                return False
            setattr(obj, fieldName, org)
            continue

        if fieldType == 'RequiredForeignPersonType':
            #
            # similar to the case above.
            #
            person = get_foreign_key(dvoice.db.models.Person, fieldValue)
            if not person:
                dsh_utils.give_bad_news(
                    'dsh_dump.load_one: ' +\
                    'failed on RequiredForeignPersonType: ' +\
                    fieldValue, logging.error)
                return False
            setattr(obj, fieldName, person)
            continue

        if fieldType == 'OptionalFollowUpsType' or \
           fieldType == 'OptionalKeyWordsType' or \
           fieldType == 'OptionalPersonsType':
            #
            # this is to be dealt with in a second round.
            # so we skip it in this round.
            # if I don't say something here, however,
            # it falls through the default case at the bottom.
            # the default case is for trivial field types.
            #
            continue

        if fieldType == 'OptionalOwnerType':
            #
            # this is used by the Event table.
            # like owner of the Item table.
            # except it's optional this time.
            #
            person = get_foreign_key(dvoice.db.models.Person, fieldValue)
            if not person:
                continue
            setattr(obj, fieldName, person)
            continue
            
        #
        # all other types of fields (like string and int) are easy to set.
        #
        setattr(obj, fieldName, fieldValue)

        
    dsh_utils.db_print('dsh_dump.load_one: obj is: ' + repr(obj), 105)


    #
    # finally, put it in the django database.
    #
    try:
        obj.save()
        dsh_utils.db_print('dsh_dump.load_one: obj is saved.', 105)
    except:
        dsh_utils.give_bad_news('dsh_dump.load_one: obj.save() failed: ' +\
                                dshUid, logging.critical)
        return False

    return True
示例#24
0
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)
示例#25
0
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)
示例#26
0
import sys
import _winreg
import dsh_utils
import shutil, os, subprocess, logging



try:
    import win32api
    import win32file
    import pywintypes
    import win32con
    import win32security
except:
    dsh_utils.give_bad_news(
        'fatal_error: failed to import win32 libraries.' +
        '  install win32 extensions.', logging.critical)
    sys.exit(1)



def get_apache_path():
    """called by install-repository-lai.py"""

    dsh_utils.db_print3('ryw_xp:get_apache_path() entered...', 50)
    
    try:
        a = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE')
        a = _winreg.OpenKey(a, 'Apache Group')
        a = _winreg.OpenKey(a, 'Apache')
示例#27
0
def sudo_chmod(path, smode='777', imode=0777, repositoryRoot = None):
    """from ryw.chmod_tree(). smode is a string, like '666' or '777'
    imode is a numbr, like 0666 or 0777.
    smode is used on Linux.
    imode is used on XP.
    caller should supply both.
    """

    if repositoryRoot == None:
        repositoryRoot = RepositoryRoot
        
    #chmodPath = os.path.join(repositoryRoot, 'etc', 'chmod')
    chmodPath = os.path.join('/usr/local/bin', 'cmod2')

    if not dsh_utils.is_valid_file(chmodPath):
        dsh_utils.give_bad_news(
            'Cannot find suid chmod. Advise you to fix this.', logging.error)
        return

    command = chmodPath + ' ' + smode + ' ' + path
    ret = subprocess.call(command, shell=True)

    if ret != 0:
        dsh_utils.give_bad_news('sudo_chmod failed on ' + path, logging.error)



#
# moved from ryw_ffmpeg.py
#
def verify_ffmpeg_existence(RepositoryRoot):
    commandPath = r'/usr/bin/ffmpeg'
示例#28
0
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')
示例#29
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)