예제 #1
0
def _send(message_list):
    from rsab.listenagain import config

    import email.Utils
    import smtplib

    if config.has_option('email', 'from'):
        email_from = config.get('email', 'from')
    else:
        email_from = DEFAULT_FROM

    if config.has_option('email', 'smtphost'):
        smtphost = config.get('email', 'smtphost')
    else:
        smtphost = ''
    if not smtphost:
        raise ListenAgainConfigError('[email]/smtphost not set')

    if config.has_option('email', 'smtpport'):
        smtpport = config.getint('email', 'smtpport')
    else:
        smtpport = None
    if not smtpport:
        smtpport = 25

    if config.has_option('email', 'smtpusername'):
        smtpusername = config.get('email', 'smtpusername')
    else:
        smtpusername = ''
    if config.has_option('email', 'smtppassword'):
        smtppassword = config.get('email', 'smtppassword')
    else:
        smtppassword = ''

    sent = 0
    smtp = smtplib.SMTP(smtphost, smtpport)
    if smtpusername:
        try:
            smtp.login(smtpusername, smtppassword)
        except smtplib.SMTPException, e:
            print 'ERROR: Could not log in to SMTP server.'
            print e
            return sent
예제 #2
0
def make_wav_files(bounds_and_files, schedule_list):
    import datetime
    import os
    import wave
    from rsab.listenagain import config, schedule, utils
    if config.has_option('main', 'wavs'):
        output_dir = config.get('main', 'wavs')
    else:
        output_dir = os.getcwd()

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    if not bounds_and_files:
        return None
    wav_reader = wave.open(bounds_and_files[0][2], 'rb')
    output_wav_params = wav_reader.getparams()
    output_wav_params = list(output_wav_params)
    output_wav_params[3] = 0
    output_wav_params = tuple(output_wav_params)
    wav_reader.close()

    frame_rate = output_wav_params[2]
    frame_size = output_wav_params[0] + output_wav_params[1]
    if config.has_option('main', 'framechunksize'):
        frame_chunk = config.getint('main', 'framechunksize')
    else:
        frame_chunk = 65536

    print 'Reading audio data in chunks of', utils.format_large_number(frame_chunk), 'frames'
    print 'Output directory:', output_dir

    output_wav_files = []
    bounds_and_files.sort()
    for details in schedule_list:
        if not details['record']:
            continue
        actual_time_start = utils.apply_padding(details['start'], details.get('pad_start', 0), subtract=True)
        actual_time_start = datetime.datetime.combine(details['date'], actual_time_start)
        actual_time_end = utils.apply_padding(details['end'], details.get('pad_end', 0), subtract=False)
        actual_time_end = datetime.datetime.combine(details['date'], actual_time_end)

        print
        print 'Schedule:', schedule.get_schedule_item_as_string(details)

        output_file_name = os.path.join(output_dir, make_output_file_name(details, 'wav'))
        print 'Output file:', os.path.split(output_file_name)[1]

        wav_writer = wave.open(output_file_name, 'wb')
        wav_writer.setparams(output_wav_params)
        for wav_file_start, wav_file_end, wav_file_path in bounds_and_files:
            if wav_file_start.date() != details['date'] \
            or wav_file_end.date() != details['date'] \
            or wav_file_end <= actual_time_start \
            or wav_file_start >= actual_time_end:
                continue

            wav_reader = wave.open(wav_file_path, 'rb')
            start_frame = end_frame = None
            if wav_file_start < actual_time_start:
                start_frame = (actual_time_start - wav_file_start).seconds * frame_rate
            if wav_file_end > actual_time_end:
                end_frame = (actual_time_end - wav_file_start).seconds * frame_rate
            if start_frame is None:
                start_frame = 0
            if end_frame is None:
                end_frame = wav_reader.getnframes()

            to_read = start_frame
            print 'Skipping', utils.format_large_number(to_read), 'frames in', os.path.split(wav_file_path)[1]
            while to_read > 0:
                data = wav_reader.readframes(min(to_read, frame_chunk))
                if not data:
                    break
                to_read -= (len(data) / frame_size)

            to_read = end_frame - start_frame
            print 'Copying', utils.format_large_number(to_read), 'frames from', os.path.split(wav_file_path)[1]
            while to_read > 0:
                data = wav_reader.readframes(min(to_read, frame_chunk))
                if not data:
                    break
                to_read -= (len(data) / frame_size)
                wav_writer.writeframes(data)
            wav_reader.close()

        wrote_frames = wav_writer.getnframes()
        wav_writer.close()
        if wrote_frames:
            print 'Wrote', utils.format_large_number(wrote_frames), 'frames'
            output_wav_files.append(output_file_name)
        else:
            print 'Wrote no frames; deleting empty file'
            os.unlink(output_file_name)

    return output_wav_files
예제 #3
0
def notify_all(uploaded_files):
    from rsab.listenagain import config
    import html
    import schedule

    from email.MIMEText import MIMEText
    import os
    import sets

    if uploaded_files is None:
        return

    mapping = { None: sets.Set(uploaded_files), }
    for fname in uploaded_files:
        details = schedule.schedule_from_audio_file_name(fname)
        for name in [details['show']] + details.get('presenters', []):
            if name not in mapping:
                mapping[name] = sets.Set()
            mapping[name].add(fname)

    config_sections = [
        sname
        for sname in config.sections()
        if sname == 'notify' or sname.startswith('notify.')
    ]

    if config.has_option('ftp', 'keep_days'):
        keep_days = config.getint('ftp', 'keep_days')
    else:
        keep_days = 7
    if config.has_option('main', 'userfacingserveraddress'):
        remote_server = config.get('main', 'userfacingserveraddress')
    else:
        remote_server = 'http://listenagain.rsab.org'
    if config.has_option('ftp', 'audio_path'):
        remote_path = config.get('ftp', 'audio_path')
    else:
        remote_path = '/audio'
    if config.has_option('email', 'from'):
        email_from = config.get('email', 'from')
    else:
        email_from = DEFAULT_FROM


    print
    print 'Notification emails:'

    messages = []
    for section in config_sections:
        print
        print 'Section name:', section
        if config.has_option(section, 'email'):
            addresses = filter(None, [x.strip() for x in config.get(section, 'email').split(',')])
        else:
            addresses = []
        print 'Addresses:', (addresses and ', '.join(addresses) or '(none)')
        if not addresses:
            print 'Skipping'
            continue

        if config.has_option(section, 'match'):
            match_names = filter(None, [x.strip() for x in config.get(section, 'match').split(',')])
        else:
            match_names = []
        print 'Requested:', ('*' in match_names and '(all)' or ', '.join(match_names))

        if '*' in match_names:
            notify_files = list(mapping[None])
        elif match_names:
            notify_files = sets.Set()
            for name in match_names:
                notify_files.update(mapping.get(name, []))
            notify_files = list(notify_files)
        else:
            notify_files = []

        if not notify_files:
            print 'No files matched.'
            continue

        notify_files.sort()

        if config.has_option(section, 'subject'):
            subject = config.get(section, 'subject')
        else:
            subject = 'New files uploaded by Radio St Austell Bay'

        if config.has_option(section, 'template'):
            template_name = config.get(section, 'template')
        else:
            template_name = 'mail-notify-default.txt'

        template = html.Template(template_name) # Not actually HTML!

        template.keep_days = keep_days
        files_string = '\n'.join([
            '    %s%s/%s' % (
                remote_server,
                remote_path,
                os.path.split(fname)[1],
            )
            for fname in notify_files
        ])
        template.files = files_string
        print 'Files:'
        print files_string

        message = MIMEText(str(template))
        message['Subject'] = subject
        message['From'] = email_from
        message['To'] = ', '.join(addresses)
        messages.append(message)

    print
    print 'Sending messages...'
    print
    sent = _send(messages)
    print
    print 'Done.  Sent %s of %s messages' % (sent, len(messages))
예제 #4
0
def get_schedule(date, filter_items=None):
    import datetime
    import glob
    import os
    from rsab.listenagain import \
        config, \
        utils, \
        ListenAgainConfigError

    schedules_folder = None

    if config.has_option('main', 'schedules'):
        schedules_folder = config.get('main', 'schedules')
    if not os.path.isdir(schedules_folder):
        raise ListenAgainConfigError('Cannot find schedules folder', schedules_folder)

    schedule_file_path = None
    require_dow = True
    override_file_path = os.path.join(schedules_folder, 'override', date.strftime('%Y-%m-%d.csv'))
    if os.path.isfile(override_file_path):
        schedule_file_path = override_file_path
        require_dow = False
    if schedule_file_path is None:
        override_file_path = os.path.join(schedules_folder, 'override', date.strftime('%Y-%m-%d.txt'))
        if os.path.isfile(override_file_path):
            schedule_file_path = override_file_path
            require_dow = False
    if schedule_file_path is None:
        schedule_files_by_date = []
        for fname in glob.glob(os.path.join(schedules_folder, '*.csv')) + glob.glob(os.path.join(schedules_folder, '*.txt')):
            fname_base = os.path.splitext(os.path.split(fname)[1])[0]
            date_for_fname = utils.parse_date(fname_base)
            if date_for_fname is None:
                print 'schedule.get_schedule: Could not interpret filename as date:', fname
                continue
            schedule_files_by_date.append( (date_for_fname, fname) )
        schedule_files_by_date.sort()
        schedule_file_path = None
        for date_for_fname, try_schedule_file_path in schedule_files_by_date:
            # Later date: don't change the file we've already remembered, as
            # it's the latest one before the current date.  Break.
            if date_for_fname > date:
                break
            # The file's date is less than or equal to the date we want.  Keep
            # this file as a candidate for the schedule.
            schedule_file_path = try_schedule_file_path
            # Exact date: keep the file and break.  XXX I suspect we don't need
            # this clause as it will all work anyway, but let's be explicit...
            if date_for_fname == date:
                break
    if schedule_file_path is None:
        schedule_from_file = []
    else:
        schedule_from_file = read_schedule_file(
            date,
            schedule_file_path,
            dow=date.weekday(),
            require_dow=require_dow,
        )

    pad_start = pad_end = 0
    if config.has_option('main', 'padstart'):
        pad_start = config.getint('main', 'padstart')
    if config.has_option('main', 'padend'):
        pad_end = config.getint('main', 'padend')

    schedule = []
    for details in schedule_from_file:
        if filter_items:
            for filter_item in filter_items:
                if filter_item == details['show'] \
                or filter_item in details.get('presenters', []):
                    break
            else:
                continue
        if details.get('pad_start') is None:
            details['pad_start'] = pad_start
        if details.get('pad_end') is None:
            details['pad_end'] = pad_end
        schedule.append(details)

    return schedule