Exemple #1
0
def valid_json_file(vjf_file):
    """validate if a json file is a valid json file"""
    MY_LOGGER.debug('valid_json_file for %s', vjf_file)
    try:
        vjf_json = wxcutils.load_file(CONFIG_PATH, vjf_file)
        # MY_LOGGER.debug('json = %s', vjf_json)
        json.loads(vjf_json)
    except ValueError:
        MY_LOGGER.debug('valid_json_file exception handler: %s %s %s',
                        sys.exc_info()[0],
                        sys.exc_info()[1],
                        sys.exc_info()[2])
        return False
    return True
Exemple #2
0
def validate_server(vs_si):
    """validate server space used"""
    MY_LOGGER.debug('vs_si = %s', vs_si)

    vs_status = 'good'
    vs_text = ''
    vs_html = ''
    vs_data = ''

    # get the space used info from the file
    vs_space_used = wxcutils.load_file(vs_si['Location'], vs_si['File'])
    MY_LOGGER.debug('Space used = %s', vs_space_used)

    # see if too much used
    if int(vs_space_used) >= int(vs_si['Max Used']):
        MY_LOGGER.debug('Too much! %s >= %s', vs_space_used, vs_si['Max Used'])
        vs_text = 'ERROR ' + vs_si['Display Name'] + \
            ' has exceeded the max percent used threshold (' + \
            vs_si['Max Used'] + ' percent) with ' + vs_space_used + ' percent used'
        vs_html = '<td style=\"background-color:#FF0000\" align=\"center\">ERROR</td>'
        vs_status = 'bad'
    else:
        MY_LOGGER.debug('Not too much %s < %s', vs_space_used,
                        vs_si['Max Used'])
        vs_text = 'OK    ' + vs_si['Display Name'] + \
            ' is within the max percent used threshold (' + \
            vs_si['Max Used'] + ' percent) with ' + vs_space_used + ' percent used'
        vs_html = '<td style=\"background-color:#00FF00\" align=\"center\">OK</td>'

    if vs_status != vs_si['Last Status']:
        vs_change = 'Y'
    else:
        vs_change = 'N'

    vs_margin = str(int(vs_si['Max Used']) - int(vs_space_used))
    vs_html = '<tr>' + vs_html + \
        '<td align=\"center\">' + vs_change + '</td>' + \
        '<td>' + vs_si['Display Name'] + '</td>' + \
        '<td align=\"center\">' + vs_si['Max Used'] + '</td>' + \
        '<td align=\"center\">' + vs_space_used + '</td>' + \
        '<td align=\"center\">' + vs_margin + '</td></tr>' + NEWLINE

    vs_data = vs_si['Display Name'] + ',' + str(CURRENT_TIME) + ',' + ALERT_INFO + ',' + \
        vs_si['Max Used'] + ',' + vs_space_used + ',' + vs_margin + ',' + \
        vs_change + ',' + vs_status + '\r\n'

    return vs_status, vs_text, vs_html, vs_data
Exemple #3
0
def build_month_page(bpm_passes, bpm_file_path, bpm_file_name, bpm_month,
                     bpm_month_name, bpm_year, bpm_historic_links):
    """build captures page for the month / year"""
    def write_month(tmp_file_path, tmp_dir, tmp_title, tmp_passes, tmp_year,
                    tmp_month):
        """write out the detail for the month"""
        # only do this if the directory exists
        if os.path.isdir(tmp_file_path + tmp_dir):
            MY_LOGGER.debug('Directory %s%s exists', tmp_file_path, tmp_dir)
            MY_LOGGER.debug('write_month %s %s %s', tmp_file_path, tmp_dir,
                            tmp_title)
            filename_list = []
            for tmp_row in tmp_passes:
                if tmp_row['local year'] == tmp_year and tmp_row[
                        'local month'] == tmp_month:
                    filename_list.append({
                        'filename': tmp_row['path'] + '.html',
                        'day': tmp_row['local day'],
                        'time': tmp_row['local time']
                    })
            MY_LOGGER.debug('sorting list')
            filename_list = sorted(filename_list,
                                   key=lambda k: k['filename'],
                                   reverse=True)

            day = ''
            cp_html.write('<ul>')
            for filename_row in filename_list:
                MY_LOGGER.debug('filename = %s', filename_row['filename'])
                new_day = filename_row['day']
                if day != new_day:
                    if day != '':
                        cp_html.write('</ul>')
                    day = new_day
                    cp_html.write('<li>')
                    cp_html.write(
                        datetime.strptime(
                            tmp_year + '-' + tmp_month + '-' + day,
                            '%Y-%m-%d').strftime('%a'))
                    cp_html.write(' ' + ordinal(int(filename_row['day'])))
                    cp_html.write('</li><ul>')

                satellite = '???'
                # MY_LOGGER.debug('finding satellite name for %s', filename_row['filename'])
                for sat_test in SAT_DATA:
                    if sat_test['code'] in filename_row['filename']:
                        satellite = sat_test['name']

                cp_html.write('<li><a href="' + CONFIG_INFO['Link Base'] +
                              filename_row['filename'] +
                              '" rel=\"modal:open\">' +
                              filename_row['time'].replace('-', ':') + ' - ' +
                              satellite + '</a></li>')

            cp_html.write('</ul>')

    MY_LOGGER.debug('build_month_page for %s %s %s %s %s', bpm_file_path,
                    bpm_file_name, bpm_month, bpm_month_name, bpm_year)

    # now create captures page
    with open(bpm_file_path + bpm_file_name, 'w') as cp_html:
        # html header
        cp_label = bpm_month_name + ' ' + bpm_year
        cp_html.write('<!DOCTYPE html>')
        cp_html.write(
            '<html lang=\"en\"><head>'
            '<meta charset=\"UTF-8\">'
            '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
            '<meta name=\"description\" content=\"Monthly satellites passes page for '
            + cp_label + '\">'
            '<meta name=\"keywords\" content=\"' +
            CONFIG_INFO['webpage keywords'] + '\">'
            '<meta name=\"author\" content=\"WxCapture\">'
            '<title>Captures ' + cp_label + '</title>'
            '<link rel=\"stylesheet\" href=\"../../css/styles.css\">'
            '<link rel=\"shortcut icon\" type=\"image/png\" href=\"' +
            CONFIG_INFO['Link Base'] + 'favicon.png\"/>'
            '<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js\"></script>'
            '<script src=\"../../js/jquery.modal.min.js\"></script>'
            '<link rel=\"stylesheet\" href=\"../../css/jquery.modal.min.css\" />'
        )
        cp_html.write('</head>')
        cp_html.write('<body onload=\"defaulthide()\">')
        if CONFIG_INFO['skip header and footer'] == 'no':
            cp_html.write(wxcutils.load_file(CONFIG_PATH,
                                            'main-header-2up.txt').replace('PAGE-TITLE', \
                'Satellite Captures'))

        cp_html.write('<section class=\"content-section container\">')

        cp_html.write(
            '<button onclick=\"hideshowinstructions()\" id=\"showhideinstructions\" class=\"showhidebutton\">Show instructions</button>'
        )
        cp_html.write('&nbsp;')
        cp_html.write(
            '<button onclick=\"hideshowlinks()\" id=\"showhidelinks\" class=\"showhidebutton\">Show previous months / years</button>'
        )

        cp_html.write('<div id=\"instructionsDiv\">')
        cp_html.write('<h2 class=\"section-header\">Instructions</h2>')
        cp_html.write('<ul>')
        cp_html.write(
            '<li>Times and dates are in the local time zone for the receiver, which is '
            + LOCAL_TIME_ZONE + '</li>')
        cp_html.write(
            '<li>Click on any pass to see the full pass information including the images</li>'
        )
        cp_html.write(
            '<li>If you click outside the pop up or on the X and you\'ll return to the pass list</li>'
        )
        cp_html.write(
            '<li>Or click on an image and you\'ll see the image in full detail</li>'
        )
        cp_html.write(
            '<li>If you click outside the pop up window or on the X and you\'ll return to the pass information</li>'
        )
        cp_html.write('</ul>')
        cp_html.write('</div>')

        cp_html.write('<div id=\"linksDiv\">')
        cp_html.write(
            '<h2 class=\"section-header\">All Captures by Year and Month</h2>')
        cp_html.write(bpm_historic_links)
        cp_html.write('</div>')

        cp_html.write('</section>')

        cp_html.write('<section class=\"content-section container\">')
        cp_html.write('<h2 class=\"section-header\">' + cp_label + '</h2>')
        write_month(
            TARGET,
            CONFIG_INFO['Link Base'] + bpm_year + '/' + bpm_month + '/',
            bpm_month_name + ' ' + bpm_year, bpm_passes, bpm_year, bpm_month)
        cp_html.write('</ul></section>')

        if CONFIG_INFO['skip header and footer'] == 'no':
            cp_html.write('<footer class=\"main-footer\">')
            cp_html.write(
                '<p id=\"footer-text\">Captures last updated at <span class=\"time\">'
                + time.strftime(
                    '%H:%M (' + subprocess.check_output("date").decode(
                        'utf-8').split(' ')[-2] +
                    ')</span> on <span class=\"time\">%d/%m/%Y</span>') +
                '.</p>')
            cp_html.write('</footer>')

        cp_html.write('<script>')
        cp_html.write('function hideshowlinks() {')
        cp_html.write('  var x = document.getElementById(\"linksDiv\");')
        cp_html.write('  if (x.style.display === \"none\") {')
        cp_html.write('   x.style.display = \"block\";')
        cp_html.write(
            '   showhidelinks.innerHTML = \"Hide previous months / years\";')
        cp_html.write(' } else {')
        cp_html.write('   x.style.display = \"none\";')
        cp_html.write(
            '   showhidelinks.innerHTML = \"Show previous months / years\";')
        cp_html.write(' }')
        cp_html.write('}')
        cp_html.write('function hideshowinstructions() {')
        cp_html.write(
            '  var x = document.getElementById(\"instructionsDiv\");')
        cp_html.write('  if (x.style.display === \"none\") {')
        cp_html.write('    x.style.display = \"block\";')
        cp_html.write(
            '    showhideinstructions.innerHTML = \"Hide instructions\";')
        cp_html.write(' } else {')
        cp_html.write('   x.style.display = \"none\";')
        cp_html.write(
            '   showhideinstructions.innerHTML = \"Show instructions\";')
        cp_html.write(' }')
        cp_html.write('}')
        cp_html.write('function defaulthide() {')
        cp_html.write('  var x = document.getElementById(\"linksDiv\");')
        cp_html.write('  x.style.display = \"none\";')
        cp_html.write(
            '  showhidelinks.innerHTML = \"Show previous months / years\";')
        cp_html.write(
            '  var y = document.getElementById(\"instructionsDiv\");')
        cp_html.write('  y.style.display = \"none\";')
        cp_html.write(
            '  showhideinstructions.innerHTML = \"Show instructions\";')
        cp_html.write('}')
        cp_html.write('</script>')

        cp_html.write('</body></html>')
        html.write(
            '<html lang=\"en\"><head>'
            '<meta charset=\"UTF-8\">'
            '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
            '<meta name=\"description\" content=\"Satellite transmission status for Meteor-M and NOAA weather satellites, International Space Station (ISS) SSTV and WxCapture Twitter Feed\">'
            '<meta name=\"keywords\" content=\"' +
            CONFIG_INFO['webpage keywords'] + '\">'
            '<meta name=\"author\" content=\"WxCapture\">'
            '<title>Satellite Status</title>'
            '<link rel=\"stylesheet\" href=\"css/styles.css\">'
            '<link rel=\"shortcut icon\" type=\"image/png\" href=\"' +
            CONFIG_INFO['Link Base'] + 'favicon.png\"/>')
        html.write('</head>')
        html.write('<body>')
        html.write(
            wxcutils.load_file(CONFIG_PATH, 'main-header.txt').replace(
                'PAGE-TITLE', 'Satellite Status'))
        html.write('<section class=\"content-section container\">')

        html.write('<h2 class=\"section-header\">Meteor-M Series Status</h2>')
        html.write('<table>')
        html.write('<tr><th>Meteor-M N2</th><th>Meteor-M N2-2</th></tr>')
        html.write('<tr><td>' + get_meteor_status('Meteor-M N2') + '</td>')
        html.write('<td>' + get_meteor_status('Meteor-M N2-2') + '</td></tr>')
        html.write('</table>')
        html.write(
            '<p><a href=\"http://happysat.nl/Meteor/html/Meteor_Status.html\" target=\"_blank\" rel=\"noopener\">Data source</a></p>'
        )
        html.write('</section>')

        html.write('<section class=\"content-section container\">')
        html.write('<h2 class=\"section-header\">NOAA Series Status</h2>')
Exemple #5
0
    MY_LOGGER.debug('Starting decode')
    # sox -t wav morse_sample.wav -esigned-integer -b16 -r 22050 -t raw morse_sample.raw
    # may not need!
    MY_LOGGER.debug('Convert .wav to .raw')
    wxcutils.run_cmd('sox -t wav ' + AUDIO_PATH + FILENAME_BASE +
                     '.wav -esigned-integer -b16 -r 22050 -t raw ' +
                     AUDIO_PATH + FILENAME_BASE + '.raw')

    # multimon-ng -t raw -a MORSE_CW morse_sample.raw /dev/stdin >> op.txt
    MY_LOGGER.debug('Parse text with multimon-ng')
    wxcutils.run_cmd('multimon-ng -t raw -a MORSE_CW ' + AUDIO_PATH +
                     FILENAME_BASE + '.raw > ' + OUTPUT_PATH + FILENAME_BASE +
                     '-decode.txt')

    # read in the file
    DECODE_TEXT = wxcutils.load_file(OUTPUT_PATH,
                                     FILENAME_BASE + '-decode.txt')

    MY_LOGGER.debug('Completed decode')

    MY_LOGGER.debug('-' * 30)

    # build web page for pass
    with open(OUTPUT_PATH + FILENAME_BASE + '.html', 'w') as html:
        html.write('<!DOCTYPE html>')
        html.write('<html lang=\"en\"><head>')
        html.write(
            '<meta charset=\"UTF-8\">'
            '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
            '<meta name=\"description\" content=\"Satellite pass capture page for NOAA / Meteor / International Space Station (ISS) SSTV / Amsat (Amateur Satellites)\">'
            '<meta name=\"keywords\" content=\"' +
            CONFIG_INFO['webpage keywords'] + '\">'
Exemple #6
0
        html.write(
            '<html lang=\"en\"><head>'
            '<meta charset=\"UTF-8\">'
            '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
            '<meta name=\"description\" content=\"Satellite transmission status for Meteor-M and NOAA weather satellites, International Space Station (ISS) SSTV and WxCapture Twitter Feed\">'
            '<meta name=\"keywords\" content=\"' +
            CONFIG_INFO['webpage keywords'] + '\">'
            '<meta name=\"author\" content=\"WxCapture\">'
            '<title>configuration Status</title>'
            '<link rel=\"stylesheet\" href=\"css/styles.css\">'
            '<link rel=\"shortcut icon\" type=\"image/png\" href=\"' +
            CONFIG_INFO['Link Base'] + 'favicon.png\"/>')
        html.write('</head>')
        html.write('<body>')
        html.write(
            wxcutils.load_file(CONFIG_PATH, 'main-header.txt').replace(
                'PAGE-TITLE', 'Configuration Status'))
        html.write('<section class=\"content-section container\">')

        # config validation results
        html.write('<section class=\"content-section container\">')
        html.write(
            '<h2 class=\"section-header\">WxCapture Configuration Validation</h2>'
        )

        if DRIVE_ERRORS:
            html.write('<h1>Storage Space Issue Detected!</h1>')
        if CONFIG_ERRORS:
            html.write(
                '<h1>Configuration Error(s) Detected - Validate Config!</h1>')
        html.write('<div id=\"configurationDiv\">')
        html.write(DRIVE_HTML)
Exemple #7
0
                    '<meta charset=\"UTF-8\">'
                    '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
                    '<meta name=\"description\" content=\"Monthly captures page for NOAA satellites\">'
                    '<meta name=\"keywords\" content=\"wxcapture, weather, satellite, NOAA, Meteor, images, ISS, Zarya, SSTV, Amsat, orbit, APT, LRPT, SDR, Mike, KiwiinNZ, Predictions, Auckland, New Zealand, storm, cyclone, hurricane, front, rain, wind, cloud\">'
                    '<meta name=\"author\" content=\"WxCapture\">'
                    '<title>' + cp_label + '</title>'
                    '<link rel=\"stylesheet\" href=\"../../css/styles.css\">'
                    '<link rel=\"shortcut icon\" type=\"image/png\" href=\"' +
                    CONFIG_INFO['Link Base'] + 'favicon.png\"/>'
                    '<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js\"></script>'
                )
                cp_html.write('</head>')
                cp_html.write('<body>')
                cp_html.write(
                    wxcutils.load_file(CONFIG_PATH,
                                       'main-header-2up.txt').replace(
                                           'PAGE-TITLE', cp_label))

                cp_html.write('<section class=\"content-section container\">')

                cp_html.write('<h2 class=\"section-header\">' + cp_label +
                              '</h2>')

                for filename_row in fix_pass_pages_lib.find_files(
                        TARGET + year + '/' + month + '/', '*-norm-tn.jpg'):
                    if os.path.getsize(filename_row) > 3000:
                        images_found += 1
                        web_filename = filename_row.split(TARGET)[1]
                        path_part, file_part = os.path.split(web_filename)
                        MY_LOGGER.debug(
                            'row = %sFilename = %s, path = %s, file = %s',
            '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">'
            '<meta name=\"description\" content=\"Predicted satellite pass times / dates for NOAA and Meteor weather satellite plus the International Space Station (ISS) and Amsat (Amateur Satellites)\">'
            '<meta name=\"keywords\" content=\"' +
            CONFIG_INFO['webpage keywords'] + '\">'
            '<meta name=\"author\" content=\"WxCapture\">'
            '<title>Satellite Pass Predictions'
            '</title>'
            '<link rel=\"stylesheet\" href=\"css/styles.css\">'
            '<link rel=\"stylesheet\" href=\"lightbox/css/lightbox.min.css\">'
            '<link rel=\"shortcut icon\" type=\"image/png\" href=\"' +
            CONFIG_INFO['Link Base'] + 'favicon.png\"/>')
        html.write('</head>')
        html.write('<body onload=\"defaulthide()\">')
        if CONFIG_INFO['skip header and footer'] == 'no':
            html.write(
                wxcutils.load_file(CONFIG_PATH, 'main-header.txt').replace(
                    'PAGE-TITLE', 'Satellite Pass Predictions'))
        html.write('<section class=\"content-section container\">')

        MY_LOGGER.debug('Table for today')
        NOW_DAY = str(datetime.now().strftime('%A'))
        NOW_DAY_NUM = str(datetime.now().strftime(
            datetime.now().strftime('%d')))
        NOW_DAY_ORD = wxcutils.ordinal(int(NOW_DAY_NUM))
        NOW_MONTH = datetime.now().strftime(datetime.now().strftime('%B'))
        NOW_YEAR = str(datetime.now().strftime(datetime.now().strftime('%Y')))
        NOW = NOW_DAY + ' ' + NOW_DAY_ORD + ' ' + NOW_MONTH + ' ' + NOW_YEAR
        html.write('<h2 class=\"section-header\">Today Over ' +
                   CONFIG_INFO['Location'] + ' - ' + NOW + '</h2>')
        html.write(
            '<button onclick=\"hideshow()\" id=\"showhide\" class=\"showhidebutton\">Show instructions</button>'
        )
def fix_file(ff_path, ff_filename):
    """fix file for upgrade"""
    def update_page(up_page, up_search, up_replace):
        """update text file with search / replace"""
        MY_LOGGER.debug('%s %s', up_search, up_replace)
        if up_search in up_page:
            MY_LOGGER.debug('%s found', up_search)
            ff_location = up_page.find(up_search)
            if ff_location > 0:
                MY_LOGGER.debug('string found at %d', ff_location)
                # up_page.replace(up_search, up_replace, 1)
                left = up_page[0:ff_location]
                skip = ff_location + len(up_search)
                right = up_page[skip:]
                up_page = left + up_replace + right
            else:
                MY_LOGGER.debug('string NOT found')
        else:
            MY_LOGGER.debug('%s NOT found', up_search)
        # MY_LOGGER.debug('%s', up_page)
        return up_page

    def fix_img(fi_page, fi_path, fi_filename):
        """fix up the img tags for lightbox"""
        MY_LOGGER.debug('starting fix_img %s %s', fi_path, fi_filename)
        start_tag = '<a href=\"images/'
        mid_tag = '\"><img src=\"images/'
        end_tag = '\"></a>'
        parse_pos = 0
        new_page = ''

        img_pos = fi_path.find('/wxcapture/')
        img_path = fi_path[img_pos:] + 'images/'
        MY_LOGGER.debug('img_path = %s', img_path)

        while parse_pos >= 0:
            if fi_page.find(start_tag, parse_pos) > 0:

                first_pos_left = fi_page.find(start_tag,
                                              parse_pos) + len(start_tag)
                first_pos_right = fi_page.find(mid_tag, first_pos_left)
                second_pos_left = first_pos_right + len(mid_tag)
                second_pos_right = fi_page.find(end_tag, second_pos_left)

                main_img = fi_page[first_pos_left:first_pos_right]
                thumb_img = fi_page[second_pos_left:(second_pos_right)]
                bits = main_img[:10].split('-')

                img_path = CONFIG_INFO['Link Base'] + bits[0] + '/' + bits[
                    1] + '/' + bits[2] + '/images/'

                MY_LOGGER.debug('%d %s %s %s', parse_pos, main_img, thumb_img,
                                img_path)

                new_bit_1 = fi_page[parse_pos:(first_pos_left -
                                               len(start_tag))]
                new_bit_2 = '<a class=\"example-image-link\" href=\"' + img_path + \
                     main_img+ \
                    '\" data-lightbox=\"' + img_path + main_img + \
                    '\"><img class=\"example-image\" src=\"' + img_path + \
                    thumb_img + '"></a>'

                MY_LOGGER.debug('-start-----------------')
                MY_LOGGER.debug(new_page)
                MY_LOGGER.debug('-new_bit_1-------------')
                MY_LOGGER.debug(new_bit_1)
                MY_LOGGER.debug('-new_bit_2-------------')
                MY_LOGGER.debug(new_bit_2)
                MY_LOGGER.debug('-end-------------------')
                new_page += new_bit_1 + new_bit_2
                parse_pos = second_pos_right + len(end_tag)
            else:
                # get the rest of the page
                new_page += fi_page[parse_pos:]
                parse_pos = -1
        MY_LOGGER.debug('completed fix_img')

        # fix plot reference
        MY_LOGGER.debug('fix plot reference')
        new_page = update_page(new_page, '<img src=\"images/',
                               '<img src=\"' + img_path)

        return new_page

    def fix_img_iss(fi_page, fi_path, fi_filename):
        """fix up the img tags only, no lightbox required"""
        MY_LOGGER.debug('starting fix_img %s %s', fi_path, fi_filename)
        start_tag = '<img src=\"images/'
        end_tag = '\">'
        parse_pos = 0
        new_page = ''

        img_pos = fi_path.find('/wxcapture/')
        img_path = fi_path[img_pos:] + 'images/'
        MY_LOGGER.debug('img_path = %s', img_path)

        while parse_pos >= 0:
            if fi_page.find(start_tag, parse_pos) > 0:

                MY_LOGGER.debug('img tag found')

                pos_left = fi_page.find(start_tag, parse_pos) + len(start_tag)
                pos_right = fi_page.find(end_tag, pos_left)

                main_img = fi_page[pos_left:pos_right]
                bits = main_img[:10].split('-')

                img_path = CONFIG_INFO['Link Base'] + bits[0] + '/' + bits[
                    1] + '/' + bits[2] + '/images/'

                MY_LOGGER.debug('%d %s %s', parse_pos, main_img, img_path)

                new_bit_1 = fi_page[parse_pos:(pos_left - len(start_tag))]
                new_bit_2 = '<img src=\"' + img_path + main_img + '\">'

                MY_LOGGER.debug('-start-----------------')
                MY_LOGGER.debug(new_page)
                MY_LOGGER.debug('-new_bit_1-------------')
                MY_LOGGER.debug(new_bit_1)
                MY_LOGGER.debug('-new_bit_2-------------')
                MY_LOGGER.debug(new_bit_2)
                MY_LOGGER.debug('-end-------------------')
                new_page += new_bit_1 + new_bit_2
                parse_pos = pos_right + len(end_tag)
            else:
                # get the rest of the page
                new_page += fi_page[parse_pos:]
                parse_pos = -1
        MY_LOGGER.debug('completed fix_img')

        # # fix plot reference
        # MY_LOGGER.debug('fix plot reference')
        # new_page = update_page(new_page, '<img src=\"images/', '<img src=\"' + img_path)

        return new_page

    def fix_audio(fi_page, fi_path, fi_filename):
        """fix up the audio tags only"""
        MY_LOGGER.debug('starting fix_audio %s %s', fi_path, fi_filename)
        start_tag = '<a href=\"audio/'
        end_tag = '\">'
        parse_pos = 0
        new_page = ''

        audio_pos = fi_path.find('/wxcapture/')
        audio_path = fi_path[audio_pos:] + 'audio/'
        MY_LOGGER.debug('audio_path = %s', audio_path)

        while parse_pos >= 0:
            if fi_page.find(start_tag, parse_pos) > 0:

                MY_LOGGER.debug('audio tag found')

                pos_left = fi_page.find(start_tag, parse_pos) + len(start_tag)
                pos_right = fi_page.find(end_tag, pos_left)

                main_audio = fi_page[pos_left:pos_right]
                bits = main_audio[:10].split('-')

                audio_path = CONFIG_INFO['Link Base'] + bits[0] + '/' + bits[
                    1] + '/' + bits[2] + '/audio/'

                MY_LOGGER.debug('%d %s %s', parse_pos, main_audio, audio_path)

                new_bit_1 = fi_page[parse_pos:(pos_left - len(start_tag))]
                new_bit_2 = '<a href=\"' + audio_path + main_audio + '\">'

                MY_LOGGER.debug('-start-----------------')
                MY_LOGGER.debug(new_page)
                MY_LOGGER.debug('-new_bit_1-------------')
                MY_LOGGER.debug(new_bit_1)
                MY_LOGGER.debug('-new_bit_2-------------')
                MY_LOGGER.debug(new_bit_2)
                MY_LOGGER.debug('-end-------------------')
                new_page += new_bit_1 + new_bit_2
                parse_pos = pos_right + len(end_tag)
            else:
                # get the rest of the page
                new_page += fi_page[parse_pos:]
                parse_pos = -1
        MY_LOGGER.debug('completed fix_audio')

        return new_page

    MY_LOGGER.debug('fix_file %s %s', ff_path, ff_filename)

    # load config
    CONFIG_INFO = wxcutils.load_json(CONFIG_PATH, 'config.json')

    # create page backup file
    # only if there isn't an existing .backup file (i.e. our backup of the original)
    if not os.path.isfile(ff_path + ff_filename + '.backup'):
        MY_LOGGER.debug('no existing backup, so creating page backup file')
        wxcutils.copy_file(ff_path + ff_filename,
                           ff_path + ff_filename + '.backup')
    else:
        MY_LOGGER.debug('File backup exists, so retaining original backup')
        # restore the backup and re-fix it
        wxcutils.copy_file(ff_path + ff_filename + '.backup',
                           ff_path + ff_filename)

    # load file
    MY_LOGGER.debug('load file')
    ff_page = wxcutils.load_file(ff_path, ff_filename)

    # add stylesheets
    MY_LOGGER.debug('add stylesheets')
    ff_page = update_page(
        ff_page, '</head>',
        '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><meta name=\"description\" content=\"Satellite pass capture page for NOAA / Meteor / International Space Station (ISS) SSTV / Amsat (Amateur Satellites)\"><meta name=\"keywords\" content=\"wxcapture, weather, satellite, NOAA, Meteor, images, ISS, Zarya, SSTV, Amsat, orbit, APT, LRPT, SDR, Mike, KiwiinNZ, Predictions, Auckland, New Zealand, storm, cyclone, hurricane, front, rain, wind, cloud\"><meta name=\"author\" content=\"WxCapture\"><link rel=\"stylesheet\" href=\"/css/styles.css\"><link rel=\"stylesheet\" href=\"/lightbox/css/lightbox.min.css\"></head>'
    )

    # add script code
    MY_LOGGER.debug('add script code')
    ff_page = update_page(
        ff_page, '</body>',
        '<script src=\"/lightbox/js/lightbox-plus-jquery.min.js\"></script></body>'
    )

    # remove table start
    MY_LOGGER.debug('remove table start')
    ff_page = update_page(ff_page, '</h2><table><tr><td>', '</h2>')

    # remove table end
    MY_LOGGER.debug('remove table end')
    ff_page = update_page(ff_page, '</td><td></table>', '<br>')

    # remove table border
    MY_LOGGER.debug('remove table border')
    ff_page = update_page(ff_page, '<table border = 1>', '<table>')

    # fix audio link - amsat  only
    if 'ISS' in ff_filename or 'SSTV' in ff_filename or 'SAUDISAT' in ff_filename or 'FOX' in ff_filename:
        ff_page = fix_audio(ff_page, ff_path, ff_filename)

    # update img tags to use lightbox
    if 'ISS' in ff_filename or 'SSTV' in ff_filename:
        ff_page = fix_img_iss(ff_page, ff_path, ff_filename)
    else:
        ff_page = fix_img(ff_page, ff_path, ff_filename)

    # MY_LOGGER.debug('%s', ff_page)

    # save file
    wxcutils.save_file(ff_path, ff_filename, ff_page)