This page permanently redirects to gemini://gemini.techrights.org/git/tr-git/Links/.

Git browser: Links/

This page presents code associated with the module/unit named above.

=> Summary of changes
=> Back to Git index
=> Licence (AGPLv3)

Links/merge-daily-links.sh

#!/bin/sh

PATH=/home/links/bin:/usr/local/bin:/usr/bin:/bin

# 2020-03-13
# updated : see Git
set -evx

closure() {
    test -d ${tmpdir} || exit 1
    echo "Erasing temporary directory (${tmpdir}) and its files."
    rm -f ${tmpdir}/feed-tmp.*
    rmdir ${tmpdir}
}

cancel() {
    echo "Cancelled."
    closure
    exit 2
}

# trap various signals to be able to erase temporary files
trap "cancel" 1 2 15

d=$(date +"%F");

read -p "Enter a date or press return for $d: " dt;

# update perl libraries from Git
cd ${HOME}/Git/tr-git/Links/
git pull
cd -

if [ -n ${dt} ]; then
        dt=${dt:-$d};
        d=$(date -d ${dt} +"%F") || exit 1;
fi;

datepath=$(date -d ${d} +"m%Y-%m")

linkshome="/home/links/Links"
linksdir="${linkshome}/${datepath}/"
mergedfile="${linkshome}/${datepath}/${d}-merged.html"

srcfile="${linkshome}/tmp/${d}.html"
automatedfile="${linkshome}/tmp/${d}-automated.html"
otherlinks="${linkshome}/tmp/other-links-${d}.txt"

if ! test -e ${dir}; then
    if ! mkdir -p ${dir}; then
	echo "problem making or finding'${dir}'"
        exit 1
    fi
fi

# verify camelCase variants for all URL-generated "tags" in manual file
links-check-camelcase.pl ${srcfile} || exit 1

# validate XHTML in the manual file
echo "Checking for '$srcfile'"
test -e $file || exit 1;
tidy -errors -quiet -xml ${srcfile} || exit 1;
echo "Ok";

echo "Checking if way is clear for new '${mergedfile}'"
test -e ${mergedfile} && exit 1;
echo "Ok";

umask 027

tmpdir=$(mktemp -d /tmp/feeds-tmp.XXXXXX)
tmpfile=$(mktemp -p ${tmpdir} feed-tmp.XXXXXXX)

# remove empty nodes from the manually collected links
# and generate a table of contents
links-cull-empty.pl ${srcfile} > ${tmpfile}
# do TOC separately in case links-cull-empty.pl fails
test -d ${linksdir} || mkdir ${linksdir}
cat ${tmpfile} | links-toc.pl > ${mergedfile}
rm ${tmpfile}

echo

start=$(date -d "$d yesterday" +"%F")
feeds=/home/links/Links/daily.feeds

echo "Loading automated feeds"
while read feed; do
    tmpfile=$(mktemp -p ${tmpdir} feed-tmp.XXXXXXX)
    rss-since-scraper.pl -d $start -o ${tmpfile} ${feed} &
done < ${automatedfile}

# clear signal trapping
trap - 1 2 15

# remove temporary files
closure

cat ${automatedfile} >> ${mergedfile}

dl=$(date -d "${d} last month" +"m%Y-%m")
dn=$(date -d "${d}" +"m%Y-%m")
p="/home/links/Links"

# check this month and last month for duplicates, remove those found
links-de-duplicate.pl -w ${mergedfile}

chmod 644 ${mergedfile}

dir="/home/links/Links/${datepath}/"

if test -e ${otherlinks}; then
        chmod 644 ${otherlinks}
        cp -p ${otherlinks} $dir && rm ${otherlinks}
fi

# insert citations formatted for social control media
# links-interleave-social-control-media.pl -w ${mergedfile}

exit 0

Links/tr-links-cull-empty.pl

#!/usr/bin/perl

# Try to cull empty nodes recursively upwards
# https://devhints.io/xpath

use utf8;
use HTML::TreeBuilder::XPath;
use Getopt::Long;
use Term::ANSIColor qw(:constants);
use HTML::Entities;
use open qw(:std :utf8);

use English;

use warnings;
use strict;

our %opt = ('p' => 0, 'w' => 0, 'h' => 0, 'v' => 0, );

GetOptions ("paragraphs|p"     => \$opt{'p'},
            "write|w"          => \$opt{'w'},
            "verbose+"         => \$opt{'v'},
            "help|h"           => \$opt{'h'},
    );

&usage if ($opt{'h'});

# read directly from stdin or else get a list of file names
push(@ARGV, '/dev/stdin') if ($#ARGV < 0);

while (my $infile = shift) {
    &readthefile($infile, $opt{'p'}, $opt{'w'});
}

exit(0);

sub readthefile {
    my ($file, $opt_p, $opt_w) = (@_);

    my $xhtml = HTML::TreeBuilder::XPath->new;
    $xhtml->implicit_tags(1);
    $xhtml->no_space_compacting(1);

    # force input to be read in as UTF-8
    my $filehandle;
    open ($filehandle, "<", $file)
        or die("Could not open file '$file' : error: $!\n");

    # parse UTF-8
    $xhtml->parse_file($filehandle)
        or die("Could not parse file handle for '$file' : $!\n");

    close ($filehandle);

    # find blockquotes with text but missing paragraph elements, add paragraphs
    for my $blockquote (
        $xhtml->findnodes('//li/blockquote[text()][count(p)=0]')) {

        my $bq = $blockquote->as_text();
        $blockquote->delete_content;

        # trim leading and trailing whitespace
        $bq =~ s/^\s+//; $bq =~ s/\s+$//;

        my @p = split(/\s*\n\s*/, $bq);
        foreach my $paragraph (@p) {
            $blockquote->push_content(['p', ,$paragraph]);
        }
    }

    if ($opt_p) {
        # find double-spaced paragraphs inside blockquotes and expand them
        for my $blockquote ($xhtml->findnodes('//blockquote[p][count(p)=1]')) {
            for my $p ($blockquote->findnodes('./p')) {

		my $text = $p->as_text();
		my @paragraphs = split(/\n\s*\n\s*/, $text);

		if ($#paragraphs >= 0) {
		    my @new_elems;
		    for my $p (@paragraphs) {
			my $new = HTML::Element->new('p');
			$new->push_content($p);
			push(@new_elems, $new);
		    }
		    $p->replace_with(@new_elems);
		}
            }
        }
    }

    # find empty end nodes
    for my $link ($xhtml->findnodes('//li[h5/a[not(text())and @href=""]
               and blockquote[not(*/child::text())]')) {
        $link->delete;
    }

    # work-around to delete empty ul nodes
    for my $link ($xhtml->findnodes('//ul[count(*)=0]')) {
        $link->delete;
    }

    # remove LI nodes with H3 and empty UL
    my $keepgoing = 1;
    while ($keepgoing) {
        $keepgoing = 0;
        for my $link ($xhtml->findnodes('//li[h3 and count(ul/li)=0 and count(blockquote)=0]')) {
            $link->delete;
            $keepgoing=1;
        }
    }

    # trim any leading or trailing whitespace from within anchor href
    for my $anchor ($xhtml->findnodes('//h5/a[@href]')) {
        my $href = $anchor->attr('href');
        $href =~ s/^\s+//;
        $href =~ s/\s+$//;
        $anchor->attr('href', $href);
#        &trim_white_space($anchor);
    }

#    for my $paragraph ($xhtml->findnodes('//h5/following-sibling::blockquote/p')) {
#        &trim_white_space($paragraph);
#    }

    # remove repeated HR elements
    for my $hr ($xhtml->findnodes('//hr/preceding-sibling::*[1][self::hr]')) {
        $hr->delete;
    }

    my $uerr = 0;
    for my $anchor ($xhtml->findnodes( '//a[@href = ""]')) {
        unless ($uerr++) {
            print STDERR BRIGHT_RED ON_BLUE, "One or more URLs missing\n";
        }
        print STDERR qq(\t),$anchor->as_text(),qq(\n);
    }
    print STDERR RESET "\n";

    my $aerr=0;
    for my $anchor ($xhtml->findnodes('//a[@href and not(boolean(text()))]')) {
        unless ($aerr++) {
            print STDERR BRIGHT_RED ON_BLUE "One or more titles missing\n";
        }
        print STDERR qq(\t),$anchor->attr('href'),qq(\n);
    }

    if($uerr || $aerr) {
        my $s = $uerr + $aerr;
        print STDERR qq(\n), $s, qq( error),$s eq 1 ? qq() : qq(s),qq(\n);

        for my $quote ($xhtml->findnodes('//h5[a[@href="" and not(boolean(text()))]]/following-sibling::blockquote')) {
            print STDERR qq(\nHint:\t),$quote->as_text(),qq(\n);
        }

        print STDERR RESET "\n";
        exit(1);
    }

    open (OUT, ">", "/dev/stdout")
        or die("Could not open file 'stdout' : error: $!\n");
    print OUT $xhtml->as_XML_indented;

    $xhtml->delete;
    return (1);
}

sub usage {
    my $script = $PROGRAM_NAME;

    $script =~ s/^.*\///;

    print qq(Usage: $script [hp] filename [filename...] \n);
    print qq(\t-h\tthis output\n);
    print qq(\t-p\texpand double-spacing into paragraphs within blockquotes\n);
    print qq(\t-w\twarnings about links missing a URL or text go to STDERR\n);
    exit 0;
}

sub trim_white_space {
    my $element = shift;

    # see: HTML::Element and HTML::Element::traverse
    for my $itemref ($element->content_refs_list) {
        if($element->starttag =~ m/^

Links/decruft.sh

# renove cruft and unwanted newlines

sed ~/rss-tools/feedlist2.html -z \
    -e 's/?bia_source=rss//g' \
    -e 's/?utm_source=h2v&utm_medium=rss_feed&utm_campaign=rss//g' \
    -e 's/?utm_source=h2v&utm_medium=rss_feed&utm_campaign=rss//g' \
    -e 's/?utm_source=social&utm_medium=feed&utm_campaign=rssfeed//g' \
    -e 's/?ref=rss&utm_medium=rss&utm_source=rss_feed//g' \
    -e 's/?utm_source=rss&utm_campaign=rss&utm_medium=links//g' \
    -e 's/?bia_source=rss//g' \
    -e 's/?origin=rss//g' \
    -e 's/#ftag=RSSbaffb68//g' \
    -e 's/#ref=rss//g' \
    -e 's/?cmp=rss//g' \
    -e 's/?utm_source=rss&utm_medium=feed&utm_campaign=rss_feed//g' \
    -e 's/?maca=en-rss-en-all-1573-xml-atom//g' \
    -e 's/?src=rss//g' \
    -e 's/?utm_medium=rss&utm_source=site-feed&utm_campaign=rss//g' \
    -e 's/?utm_source=feed//g' \
    -e 's/?icid=rss//g' \
    -e 's/\n<\/blockquote><\/li>/<\/blockquote><\/li>/g' \
    -e 's/\n
<\/div><\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e 's/\n<\/div><\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e 's/\n

<\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e 's/\n
<\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e 's/\n<\/p><\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e 's/\n

<\/p><\/blockquote><\/li>/<\/blockquote><\/li>/g' \ -e "s/\n<\/blockquote><\/li>/<\/blockquote><\/li>/g" \ -e "s/Read our blog to see how the day's events unfolded. All times are Paris time (GMT+2)./ /g" \ -e "s/Follow our live blog for all the latest developments on the war in Ukraine. All times are Paris time (GMT+2)./ /g" \ >> ~/rss-tools/RSS.html ./compress-links.sh # next stage appended

Links/tr-supplementary-daily-links.sh

#!/bin/sh

PATH=/home/links/bin:/usr/local/bin:/usr/bin:/bin

# 2023-01-31
# updated : see Git
set -evx

closure() {
	test -d ${tmpdir} || exit 1
	echo "Erasing temporary directory (${tmpdir}) and its files."
	rm -f ${tmpdir}/feed-tmp.*
	rmdir ${tmpdir}
}

cancel() {
	echo "Cancelled."
	closure
	exit 2
}

# trap various signals to be able to erase temporary files
trap "cancel" 1 2 15

d=$(date +"%F");
path=$(date -d ${d} +"m%Y-%m")

if tty; then
	read -p "Enter a date or press return for $d: " dt;
fi

if [ -n ${dt} ]; then
	dt=${dt:-$d};
	d=$(date -d ${dt} +"%F") || exit 1;
fi;

sfile="/home/links/Links/tmp/${d}-supplementary.html"
dir="/home/links/Links/${path}/"

if [ -e ${dir}/${d}-supplementary.html ]; then
	echo "Links for '${d}' already in place"
	exit 1
fi

if ! test -e ${dir}; then
	if ! mkdir -p ${dir}; then
		echo "problem making or finding'${dir}'"
		exit 1
	fi
fi

umask 027

start=$(date -d "$d yesterday" +"%F")
feeds=/home/links/Links/daily-supplementary.feeds
tmpdir=$(mktemp -d /tmp/feeds-tmp.XXXXXX)

echo

echo "Loading automated feeds"
while read feed; do
	tmpfile=$(mktemp -p ${tmpdir} feed-tmp.XXXXXXX)
	tr-rss-since-scraper.pl -d $start -o ${tmpfile} ${feed} &
done < ${sfile}

# clear signal trapping
trap - 1 2 15

# remove temporary files
closure

umask 022

dl=$(date -d "${d} last month" +"m%Y-%m")
dn=$(date -d "${d}" +"m%Y-%m")
p="/home/links/Links"

# check for duplicates, remove those found from the main part of the file
tr-links-de-duplicate.pl -w ${sfile}

# be careful not to run the above script twice since the list of duplicates
# is stored in database and thus *all* the links will be considered duplicate
# the second time around

cp ${sfile} ${dir} && rm ${sfile}
chmod 664 ${dir}/${d}-supplementary.html

# insert citations formatted for social control media
# links-interleave-social-control-media.pl -w ${sfile}

exit 0

Links/list-rss-feed.sh

#!/bin/sh

# print out list of RSS links, based on OPML file
# updated 2022-06-13

# cat roy-feeds.opml  | grep -o 'xmlUrl.*\"' | sort | uniq  > sorted-rss-feeds.txt
cat roy-feeds.opml \
        | xmlstarlet sel -t -v '//outline/@xmlUrl' \
        | sort \
        | uniq \
        > sorted-rss-feeds.txt

Links/tr-links-check-camelcase.pl

#!/usr/bin/perl

# find links and prepend the nodes they are in with
# citations suitable for social control media
# "tag" the comment based on the page's domain
# see Git

use utf8;
use Getopt::Long;
use File::Glob ':bsd_glob';
use HTML::TreeBuilder::XPath;
use URI;
use open qw(:std :utf8);
use Term::ANSIColor qw(:constants);

use lib "$ENV{HOME}/lib/";
use Links::MetaData qw(camelCase);

use English;

use warnings;
use strict;

our %tags;
our %opt = (
    'verbose' => 0,
    'help' => 0,
);

GetOptions (
    "help|h"       => \$opt{'help'},            # flag
    "verbose|v+"   => \$opt{'verbose'},         # flag, multiple settings
    );

&usage if ($opt{'help'});

my @filenames;
while (my $file = shift) {
    my @files = bsd_glob($file);
    foreach my $f (@files) {
        push(@filenames, $f);
    }
}

&usage if($#filenames < 0);

while (my $infile = shift(@filenames)) {
    next if ($infile=~/~$/);
    my $result = &interleave($infile);

    if(keys %tags) {
        print STDERR BRIGHT_RED ON_BLUE "Check these for CamelCase: \n";
        # print join("\n ", @tags);
        foreach my $site (sort keys %tags) {
            print qq( $site\n);
        }
        print STDERR RESET;
        print qq(\n);
        # print qq(Run "links-interleave-social-control-media.pl" manually.\n);
        # print STDERR qq(Re-run "merge-daily-links.sh" manually.\n);
        exit(1);
    }
}

exit(0);

sub usage {
    print qq(Check URLs and verify that the Links::CamelCase module\n);
    print qq(recognizes them and can substitute the right "tag" for them.\n);
    $0 =~ s/^.*\///;
    print qq($0: file\n);
    exit(1);
}

sub interleave {
    my ($file)= (@_);

    my $xhtml = HTML::TreeBuilder::XPath->new;
    $xhtml->implicit_tags(1);
    $xhtml->parse_file($file)
        or die("Could not parse '$file' : $!\n");

    for my $node ($xhtml->findnodes('//li[h5]')) {
        for my $anchor ($node->findnodes('./h5/a[@href]')) {
            my $href = $anchor->attr('href');
            next unless($href);

	    my $uri = URI->new($href);
	    if ($opt{'verbose'}) {
		print qq(U=$uri\n);
	    }

	    my $host = $uri->host;

	    if ($opt{'verbose'}) {
		print qq(H=$host\n);
	    }

            my $sitetag = MetaData::camelCase($host);

            if ( ! $sitetag ) {
		$tags{$host}++;
            }
        }
    }

    $xhtml->delete;
    return (1);
}

Links/filter-sorted.sh

grep -v -e telesur \
	-e rferl \
	-e france24 \
	-e scheeerpost \
        -e techdirt \
        -e nytimes \
        -e qz \
        -e lxer  \
        -e vice.com \
        -e ec.europa.eu \
        -e technologyreview \
        -e detroitnews \
        -e h2-view \
        -e stanforddaily \
        -e yle \
        -e meduza \
        -e lrt.lt \
        -e atlanticcouncil \
        -e sciencealert \
        -e  axios \
        -e michaelwest  \
        -e commondreams \
        -e rfa.org \
        -e aspistrategist \
        -e csmonitor \
        -e reason.com \
        -e desmog \
        -e ipwatchdog \
        -e unifiedpatents.com \
        -e juve-patent \
        -e patentlyo.com \
        -e www.epo.org \
        -e kluweriplaw \
        -e patentprogress \
	-e cyberscoop \
        -e pressgazette \
        -e phoronix \
        -e ubuntu.com \
        -e idroot \
        -e hackaday \
        -e omgubuntu \
        -e unixcop \
        -e tecmint \
        -e trendoceans \
        -e  tecadmin \
        -e  savannah.gnu \
        -e  cloudbooklet \
        -e  tfir.io  \
        -e  drydeadfish \
        -e  tomshardware  \
        -e  siliconangle  \
        -e  venturebeat  \
        -e  cloudnativenow  \
        -e  itavisen  \
        -e version2.dk  \
        -e digitalmusicnews  \
	-e federalnewsnetwork \
        -e which.co.uk \
        -e helsinkitimes \
        -e neritam \
        -e hongkongfp \
        -e techrights.org \
        -e linuxhint \
        -e linuxlinks \
        -e gamingonlinux \
        -e straitstimes \
        -e linuxtoday.com \
        -e linuxconcept \
        -e 9to5linux \
        -e linuxiac \
        -e jupiter.zone \
        -e unixmen \
        -e linuxcapable \
	-e nypost \
        -e fair.org \
        -e jurist.org \
        -e theatlantic.com \
        -e twincities \
        -e net2.com \
        -e hecticgeek \
        -e sysdfree \
        -e cnx-software \
        -e linuxconcept \
        -e boilingsteam \
        -e linux-magazine.com \
        -e fossmint \
        -e dwaves.de \
        -e techzim \
        -e howtoforge \
        -e medevel \
        -e schneier \
        -e linuxsecurity.com \
        -e securityweek \
        -e itjungle \
        -e thenation.com \
 /home/roy/rss-tools/sorted.html > /home/roy/rss-tools/filtered.html

Links/template-roy-2022.html




  
  


Links 13/05/2022:

Links for the day

  • GNU/Linux

    • Desktop/Laptop

    • Server

    • Audiocasts/Shows

    • Kernel Space

      • Graphics Stack

    • Benchmarks

    • Applications

    • Instructionals/Technical

    • Wine or Emulation

    • Games

    • Desktop Environments/WMs

      • K Desktop Environment/KDE SC/Qt

      • GNOME Desktop/GTK

    • Distributions

      • Reviews

      • New Releases

      • BSD

      • Screenshots/Screencasts

      • PCLinuxOS/Mageia/Mandriva/OpenMandriva Family

      • Gentoo Family

      • SUSE/OpenSUSE

      • Slackware Family

      • Arch Family

      • IBM/Red Hat/Fedora

      • Devuan Family

      • Debian Family

      • Canonical/Ubuntu Family

    • Devices/Embedded

      • Open Hardware/Modding

      • Mobile Systems/Mobile Applications

    • Free, Libre, and Open Source Software

      • Events

      • Web Browsers

        • Chromium

        • Mozilla

      • SaaS/Back End/Databases

      • Productivity Software/LibreOffice/Calligra

      • Content Management Systems (CMS)

      • Education

      • Funding

      • FSFE

      • FSF

        • GNU Projects

        • Licensing/Legal

      • Public Services/Government

      • Openness/Sharing/Collaboration

        • Open Data

        • Open Access/Content

      • Programming/Development

        • Perl/Raku

        • Python

        • Shell/Bash/Zsh/Ksh

        • Rust

        • Java

      • Standards/Consortia

  • Leftovers

    • Science

    • Education

    • Hardware

    • Health/Nutrition/Agriculture

    • Integrity/Availability

      • Proprietary

        • Pseudo-Open Source

          • Openwashing

          • Privatisation/Privateering

            • Linux Foundation

          • Entrapment (Microsoft GitHub)

        • Security

          • Fear, Uncertainty, Doubt/Fear-mongering/Dramatisation

          • Privacy/Surveillance

            • Confidentiality

    • Defence/Aggression

    • Transparency/Investigative Reporting

    • Environment

      • Energy

      • Wildlife/Nature

      • Overpopulation

    • Finance

    • AstroTurf/Lobbying/Politics

    • Misinformation/Disinformation

    • Censorship/Free Speech

    • Freedom of Information/Freedom of the Press

    • Civil Rights/Policing

    • Internet Policy/Net Neutrality

    • Digital Restrictions (DRM)

    • Monopolies

      • Patents

        • Software Patents

      • Trademarks

      • Copyrights

Links/add-lines-for-irc.pl

#!/usr/bin/perl

# 2022-04-09 See Git logs for change history
# 2020-12-31
# 2021-01-24
# find links and prepend the nodes they are in with
# citations suitable for social control media
# "tag" the comment based on the page's domain

use utf8;
use open qw(:std :utf8);
use Getopt::Std;
use File::Glob ':bsd_glob';
use HTML::TreeBuilder::XPath;
use File::Temp qw(tempfile tempdir);
use File::Copy qw(move);
use URI;

use lib "$ENV{HOME}/lib/";	           # also look for local modules
use Links::MetaData qw(camelCase);        # local module

use English;

use warnings;
use strict;

our %opt;

getopts('hw', \%opt);

&usage if ($opt{'h'});

my @filenames;
while (my $file = shift) {
    my @files = bsd_glob($file);
    foreach my $f (@files) {
        push(@filenames, $f);
    }
}

&usage if($#filenames < 0);

while (my $infile = shift(@filenames)) {
    next if ($infile=~/~$/);
    my $result = &interleave($infile);
#     $result =~ s/\x{00A0}/ /gm;

    if($opt{'w'}) {
        &overwrite_file($infile, $result);
    } else {
	open(OUT, ">", "/dev/stdout")
	    or die("Could not open file 'stdout' : error: $!\n");
        print OUT $result;
	close(OUT)
    }

}

exit(0);

sub usage {
    print qq(Find links and prepend the nodes they are in.\n);
    print qq(with citations suitable for social control media\n);
    print qq(The default is to send output to stdout.\n);
    print qq( -w overwrites the exiting files instead of sending to stdout.\n);
    $0 =~ s/^.*\///;
    print qq($0: new_file old_file [oldfile...]\n);
    exit(1);
}

sub interleave {
    my ($file)= (@_);

    my $xhtml = HTML::TreeBuilder::XPath->new;
    $xhtml->implicit_tags(1);
    $xhtml->no_space_compacting(1);

    # force input to be read in as UTF-8
    my $filehandle;
    open ($filehandle, "<", $file)
        or die("Could not open file '$file' : error: $!\n");

    # parse UTF-8
    $xhtml->parse_file($filehandle)
        or die("Could not parse file handle for '$file' : $!\n");

    close ($filehandle);

    for my $node ($xhtml->findnodes('//li[h5]')) {
	for my $heading ($node->findnodes('./h5[a[@href]]')) {
	    for my $anchor ($node->findnodes('./h5/a[@href]')) {
		my $href = $anchor->attr('href');
		next unless($href);
		my $title = $anchor->as_text;
		next unless($title);

		my $sitetag = &sitetag($href);

		$sitetag = &MetaData::camelCase($sitetag);

		my $sc;

		$sc = HTML::Element->new('~literal',
					     'text'=>"\n");
		$node->preinsert($sc);

                $sc = HTML::Element->new('~comment',
                                         'text'=>" $href | Source: $sitetag ");
                $node->preinsert($sc);
	    }
	}
    }

    my $result = $xhtml->as_HTML('<', "\t", {});

    $xhtml->delete;
    return ($result);
}

sub overwrite_file {
    my ($outfile, $result) = (@_);
    my ($fh, $filename) = tempfile();

    print qq(F= $filename\n);
    print $fh $result;

    close($fh);

    rename($outfile,"$outfile.old")
        or die("$!\n");

    move($filename, $outfile)
        or die("$!\n");

    return(1);
}

sub sitetag {
    my ($href) = (@_);

    my $tag;
    my $uri = URI->new($href);
    next unless(defined $uri->scheme && $uri->scheme =~ /^http/);
    my $domain = $uri->host || 0;
    return($domain);
}

sub exceptions {
    my ($d) = (@_);
    $d = 'riskybiz' if ($d =~ m/\brisky\.biz$/i);
    return($d);
}

Links/sort-wrapper.sh

#!/bin/sh

#Licence: Public Domain, feel free to share as you see fit
#
#Author: Roy Schestowitz

search_news() {
        STRING=$1
        echo
        echo
        echo "           =========================== Input string: $1"
        echo
        echo

        grep -A0 -B0 --ignore-case  --no-group-separator -- \
                $STRING /home/roy/rss-tools/outlines.html
}

search_news_inverted() {
        STRING=$1

        grep -A0 -B0 --ignore-case --no-group-separator -v -- \
                $STRING /home/roy/rss-tools/outlines-subset.html
}

sort_rss() {
        SEARHFTERM=$1

        echo "\n\n" >> ~/rss-tools/sorted.html
        echo "      ================================ Input string: $1" \
        >> ~/rss-tools/sorted.html
        echo "\n\n" >> ~/rss-tools/sorted.html

        FULLDATE0=$(date +"%F")
        FULLDATE1=$(date --date="$FULLDATE0 -1 days" +"%F")
        FULLDATE2=$(date --date="$FULLDATE0 -2 days" +"%F")
        FULLDATE3=$(date --date="$FULLDATE0 -3 days" +"%F")
        FULLDATE4=$(date --date="$FULLDATE0 -4 days" +"%F")
        FULLDATE5=$(date --date="$FULLDATE0 -5 days" +"%F")
        FULLDATE6=$(date --date="$FULLDATE0 -6 days" +"%F")
        FULLDATE7=$(date --date="$FULLDATE0 -7 days" +"%F")
        FULLDATE8=$(date --date="$FULLDATE0 -8 days" +"%F")
        FULLDATE9=$(date --date="$FULLDATE0 -9 days" +"%F")

        search_news $SEARHFTERM \
                | grep $FULLDATE0 \
                >> ~/rss-tools/sorted.html
        search_news $SEARHFTERM \
                | grep $FULLDATE1 \
                | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE2 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE3 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE4 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE5 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE6 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE7 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE8 \ | sed 's/
  • > ~/rss-tools/sorted.html search_news $SEARHFTERM \ | grep $FULLDATE9 \ | sed 's/
  • > ~/rss-tools/sorted.html cp ~/rss-tools/outlines.html ~/rss-tools/outlines-subset.html search_news_inverted $SEARHFTERM > ~/rss-tools/outlines.html # Legacy (manual): # search_news russia >> sorted.html # cp ~/rss-tools/outlines.html ~/rss-tools/outlines-subset.html # ~/search-news-inverted.sh russia > ~/rss-tools/outlines.html } for w in 'russia' 'tiktok' 'ukrai' 'xkcd.com' 'fsfe.org' 'twit.tv' \ 'distrowatch' 'security' 'copyright' 'tllts' 'linuxmadesimple' \ 'makeuseof' 'yewtu.be' 'youtube' 'how-to' 'linux' 'apple' \ 'microsoft' 'databreaches.net' 'gnu' 'ubuntu' 'bsd' 'banking' \ 'banks' 'patent' 'schestow' 'techrights' 'climate' 'energy' \ 'speech' 'censor' 'suse' 'syria' 'saudi' 'turkey' 'redhat.com' \ 'redhat' 'photo' 'uprising' 'ctrl.blog' 'unix' 'utcc' 'server' \ 'canada' 'africa' 'twitter' 'facebook' 'telesurenglish' \ 'dw.com' 'debian' 'perl' 'ipkitten' do sort_rss "${w}" done exit 0
  • Links/convert-latest-links.sh

    # techrights 
    clear
    
    echo Today in Techrights
    echo Some of the latest articles
    echo
    echo Over at Tux Machines...
    echo GNU/Linux news for the past day
    
    
    sed -z  -e 's/
     <\/dd>/

    New<\/h4> /g' \ -e 's/--/

    New<\/h4> /g' \ -e 's/
    /

    Updated This Past Day<\/h4>
      /g' \ -e 's/
      /<\/h5>/g' \ -e 's/
      /<\/blockquote><\/li>/g' \ -e 's/\/n\/202/\http:\/\/techrights.org\/n\/202/g' \ ~/Desktop/Text_Workspace/groups-links.html echo echo '---------------------------' echo # tuxmachines sed -z -e 's/
       <\/dd>/

      New<\/h4> /g' \ -e 's/--/

      New<\/h4> /g' \ -e 's/
      /

      Updated This Past Day<\/h4>
        /g' \ -e 's/
        /<\/h5>/g' \ -e 's/
        /<\/blockquote><\/li>/g' \ -e 's/\/n\/202/\http:\/\/news.tuxmachines.org\/n\/202/g' \ ~/Desktop/Text_Workspace/groups-links.html

    Links/template.html

    
    
    
    
    
    
    
    Links for the day
    
    • GNU/Linux

      • Desktop/Laptop

      • Server

      • Audiocasts/Shows

      • Kernel Space

      • Graphics Stack

      • Benchmarks

      • Applications

      • Instructionals/Technical

      • WINE or Emulation

      • Games

      • Desktop Environments/WMs

        • K Desktop Environment/KDE SC/Qt

        • GNOME Desktop/GTK

    • Distributions and Operating Systems

      • Reviews

      • New Releases

      • Screenshots/Screencasts

      • BSD

      • PCLinuxOS/Mageia/Mandriva/OpenMandriva Family

      • Gentoo Family

      • SUSE/OpenSUSE

      • Slackware Family

      • Arch Family

      • Fedora Family / IBM

      • Devuan Family

      • Debian Family

      • Canonical/Ubuntu Family

      • Devices/Embedded

      • Open Hardware/Modding

      • Mobile Systems/Mobile Applications

    • Free, Libre, and Open Source Software

      • Events

      • Web Browsers/Web Servers

        • Chromium

        • Mozilla

      • SaaS/Back End/Databases

      • Productivity Software/LibreOffice/Calligra

      • Content Management Systems (CMS) / Static Site Generators (SSG)

      • Education

      • Funding

      • FSF

      • FSFE

      • GNU Projects

      • Licensing / Legal

      • Public Services/Government

      • Openness/Sharing/Collaboration

        • Open Data

        • Open Access/Content

      • Programming/Development

        • Perl / Raku

        • Python

        • Shell/Bash/Zsh/Ksh

        • Java/Golang

        • Rust

      • Standards/Consortia

    • Leftovers

      • Science

      • Career/Education

      • Hardware

      • Health/Nutrition/Agriculture

      • Proprietary/Artificial Intelligence (AI)

        • Windows TCO / Windows Bot Nets

      • Pseudo-Open Source

        • Openwashing

      • Privatisation/Privateering

      • Linux Foundation

      • Entrapment (Microsoft GitHub)

      • Security

        • Fear, Uncertainty, Doubt/Fear-mongering/Dramatisation

        • Integrity/Availability/Authenticity

        • Privacy/Surveillance

        • Confidentiality

      • Defence/Aggression

        • Overpopulation

    • Transparency/Investigative Reporting

    • Environment

      • Energy/Transportation

      • Wildlife/Nature

    • Finance

    • AstroTurf/Lobbying/Politics

      • Misinformation/Disinformation/Propaganda

    • Censorship/Free Speech

    • Freedom of Information / Freedom of the Press

    • Civil Rights/Policing

    • Internet Policy/Net Neutrality

    • Digital Restrictions (DRM)

    • Monopolies/Monopsonies

      • Patents

        • Kangaroo Courts

        • Software Patents

      • Trademarks

        • Right of Publicity

      • Copyrights

    • Gemini* and Gopher

      • Personal

      • Politics

      • Technical

        • Science

        • Internet/Gemini

        • Announcements

        • Programming


    * Gemini (Primer) links can be opened using Gemini software. It's like the World Wide Web but a lot lighter.

    Links/rrrrrr.py

    #!/usr/bin/python3
    
    """
    Copyright (C) 2024 Bytes Media.  This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.  You should have received a copy of the GNU Affero General Public License along with this program.  If not, see https://www.gnu.org/licenses/
    """
    
    from argparse import ArgumentParser, RawTextHelpFormatter
    from time import sleep, gmtime, strftime
    from lxml import etree as et
    import pprint
    import copy
    from urllib.request import urlopen, Request
    from urllib.error import URLError, HTTPError
    from ssl import SSLError
    from datetime import datetime, timezone, timedelta
    from time import strftime
    import feedparser
    import os
    from pathlib import Path as path
    from time import gmtime
    from multiprocessing.pool import ThreadPool
    import sqlite3
    import dateparser
    from collections import defaultdict      # not sorted
    from urllib.parse import urlparse, quote
    import gzip
    import re
    from html import unescape
    import os.path
    import sys
    from requests.structures import CaseInsensitiveDict
    
    # starting time of the script
    starttime = datetime.utcnow()
    
    # regex pattern characters allowed inside the ETag field
    # see https://datatracker.ietf.org/doc/html/rfc7232#section-2.3
    etagc = re.compile('^(W/)?"[%s]{1,90}"$' % "".join(k for k,_ in
                    {chr(e):1 for e in
                     list(range(33,33)) +
                     list(range(35,127)) +
                     list(range(128,254))}.items()))
    
    entitiesEscapeTable = {
        ">": ">",
        "<": "<",
    }
    
    def escape_entities(text):
        """Produce entities within text."""
        return ("".join(entitiesEscapeTable.get(c,c) for c in text))
    
    def import_dbpath():
        dbpath = os.environ.get('HOME') + '/.cache/rrrrrr/'
        try:
            path(dbpath).mkdir(parents=True, exist_ok=True)
        except FileExistsError as e:
            if verbosity > 1:
                print(f"Path P{dbpath} exists, but that's ok.")
        except FileNotFoundError as e:
            print(f"Path {dbpath} could not be created: {e}")
            exit(1)
    
        if not os.access(dbpath, os.R_OK):
            print(f"Path {dbpath} cannot be read: {e}")
            exit(1)
        elif not os.access(dbpath, os.W_OK):
            print(f"Path {dbpath} cannot be written: {e}")
            exit(1)
        elif not os.access(dbpath, os.X_OK):
            print(f"Path {dbpath} cannot be searched: {e}")
            exit(1)
    
        return(dbpath)
    
    def import_opml_files(importfiles: list, cursor):
        global verbosity
        global appendopml
    
        if verbosity:
            print("Reading: ", end='')
            pprint.pprint(importfiles)
    
        # read the first file
        try:
            infile = importfiles.pop()
            try:
                with open(infile) as xml_file:
                    feed = xml_file.read()
                if verbosity:
                    print(f"+ Importing from '{infile}'")
            except FileNotFoundError:
                print(f"Wrong file or file path 1: {infile}")
                sys.exit(1)
        except Exception:
            if verbosity:
                print("Placeholder OPML")
            # if no input OPML files exist, a placeholder is needed
            # to make the first part of the tree
            feed = """
    
    
            RRRRRRR
            Thu Feb 2 07:22:07 2023
    
    
    
    
    """
        else:
            # OPML file(s) exists for reading
            if not appendopml:
                cursor.execute("DELETE FROM opml")
                connection.commit()
    
        main_tree = et.XML(feed.encode("UTF-8"))
        dateModified = strftime('%a %b %d %H:%M:%S %p %Z %Y', gmtime())
        # Mon Sep 18 10:54:05 AM UTC 2023
        try:
            old_dateModified = main_tree.find('.//head/dateModified')
            old_dateModified.text = dateModified
        except Exception:
            if verbosity:
                print("Skipping")
    
        # read the rest, if there are more
        for infile in importfiles:
            if verbosity:
                print(f"+ Importing from '{infile}'")
            try:
                with open(infile) as xml_file:
                    feed = xml_file.read()
                opml = et.fromstring(feed.encode("UTF-8"))
                old_body = main_tree.find('.//body')
                for new_body in opml.findall('.//body/*'):
                    node2 = copy.deepcopy(new_body)
                    old_body.append(node2)
            except FileNotFoundError:
                print(f"Wrong file or file path 2: {infile}")
                sys.exit(1)
    
        # read OPML from db here
        cursor.execute('SELECT opml FROM opml LIMIT 1')
        try:
            dbopml, = cursor.fetchone()
            dbopml = et.fromstring(dbopml)
            old_body = main_tree.find('.//body')
            for new_body in dbopml.findall('.//body/*'):
                node2 = copy.deepcopy(new_body)
                old_body.append(node2)
        except Exception:
            dbopml = ""
    
        return(main_tree)
    
    def validate_last_modified(lm):
        try:
            datetime.strptime(lm, "%a, %d %b %Y %H:%M:%S GMT")
        except Exception:
            lm = ''
        return(lm)
    
    def validate_etag(etag):
        try:
            etagc.match(etag)
        except Exception:
            etag = ''
        return(etag)
    
    def initialize_db(cursor):
    
        initialization = list()
    
        initialization.append(
            # needed for cascade deletion
            'PRAGMA foreign_keys = yes;'
        )
        initialization.append(
            'DROP TABLE IF EXISTS status'
        )
        initialization.append(
            'DROP TABLE IF EXISTS modified'
        )
        initialization.append(
            'DROP TABLE IF EXISTS opml'
        )
        initialization.append(
            '''CREATE TABLE IF NOT EXISTS status (
                ttl INTEGER DEFAULT 0,
                tried   INTEGER DEFAULT 0,
                success INTEGER DEFAULT 0,
                status  INTEGER DEFAULT 0,
                url VARCHAR(256) NOT NULL PRIMARY KEY);'''
        )
        initialization.append(
            '''CREATE TABLE IF NOT EXISTS modified (
                url VARCHAR(256) NOT NULL PRIMARY KEY,
                lastmodified VARCHAR(29) DEFAULT NULL,
                etag TEXT DEFAULT NULL,
                CONSTRAINT fk_url
                  FOREIGN KEY (url)
                  REFERENCES status(url)
                  ON DELETE CASCADE);'''
        )
        initialization.append(
            'CREATE TABLE IF NOT EXISTS opml(opml TEXT NOT NULL);'
        )
        initialization.append(
            'CREATE UNIQUE INDEX IF NOT EXISTS urls ON status(url);'
        )
        initialization.append(
            'CREATE UNIQUE INDEX IF NOT EXISTS mods ON modified(url)'
        )
        for i in initialization:
            try:
                cursor.execute(i)
            except Exception:
                connection.rollback()
                print(f"4 Fail {i}")
                exit(1)
    
        connection.commit()
    
        return(True)
    
    def save_opml_into_db(opmlfeeds, cursor):
        initialization = list()
    
        opml = et.tostring(opmlfeeds, method="xml")
        data = (opml.decode("UTF-8"),)
    
        # clear the old OPML file
        query = 'DELETE FROM opml'
        try:
            cursor.execute(query)
        except NameError as e:
            connection.rollback()
            connection.close()
            print(f"1 Failed initialization\n {query}\n\t{e}")
            exit(1)
        except sqlite3.ProgrammingError as e:
            connection.rollback()
            connection.close()
            print(f"2 Failed initialization query\n {query}\n\t{e}")
            exit(1)
        connection.commit()
    
        # save the new OPML file
        opml = et.tostring(opmlfeeds, method="xml")
        data = (opml.decode("UTF-8"),)
        query = 'INSERT INTO opml (opml) VALUES (?)'
        try:
            cursor.execute(query, data)
        except NameError as e:
            connection.rollback()
            connection.close()
            print(f"3 Failed initialization\n {query}\n\t{e}")
            exit(1)
        except sqlite3.ProgrammingError as e:
            connection.rollback()
            connection.close()
            print(f"4 Failed initialization query\n {query}\n\t{e}")
            exit(1)
        connection.commit()
    
        return(True)
    
    def cull_database(cursor, starttime):
    
        startepoch = int(starttime.strftime("%s"))
    
        # clear the unused URLs
        query = 'DELETE FROM status WHERE tried < ?'
        try:
            cursor.execute(query, (startepoch,))
        except NameError as e:
            connection.rollback()
            connection.close()
            print(f"5 Failed cull initialization\n {query}\n\t{e}")
            exit(1)
        except sqlite3.ProgrammingError as e:
            connection.rollback()
            connection.close()
            print(f"6 Failed execution of cull query\n {query}\n\t{e}")
            exit(1)
        connection.commit()
    
        return(True)
    
    def export_opml_to_file(cursor, exportfile):
        global verbosity
    
        try:
            cursor.execute('SELECT opml FROM opml LIMIT 1')
            try:
                feeds, = cursor.fetchone()
            except Exception:
                print(f"Failed to retrieve OPML template from record")
                exit(1)
    
        except Exception:
            print(f"Failed to retrieve OPML template from db")
            exit(1)
    
        # main copy for conversion to XHTML at the end
        main_tree = et.XML(feeds.encode("UTF-8"))
    
        # alternation so that only one loop is needed
        for cruft in main_tree.findall('.//outline/ttl|.//outline/status'):
            cruft.getparent().remove(cruft)
    
        opml = et.tostring(main_tree, method="xml")
        if exportfile:
            try:
                with open(exportfile, 'w', encoding='utf-8') as f:
                    print(opml.decode("UTF-8"), file=f)
            except OSError as e:
                print(f"Some error: {e}")
                exit(1)
        else:
            print(opml.decode("UTF-8"))
    
        exit(0)
    
    def fetch_tree(cursor,oktime,exportlog):
        global verbosity
        global forcefetch
        init=0
    
        try:
            cursor.execute('SELECT opml FROM opml LIMIT 1')
            try:
                feeds, = cursor.fetchone()
            except Exception:
                print(f"2 Failed to retrieve OPML template from record")
                exit(1)
    
        except Exception:
            print(f"2 Failed to retrieve OPML template from db")
            exit(1)
    
        # main copy for conversion to XHTML at the end
        main_tree = et.XML(feeds.encode("UTF-8"))
        dateModified = strftime('%a %d %b %Y %H:%M:%S %Z', gmtime())
        try:
            old_dateModified = main_tree.find('.//head/dateModified')
        finally:
            old_dateModified = et.Element('dateModified')
            old_dateModified.text = dateModified
    
        now = datetime.utcnow().replace(microsecond=0)
        urls = []
        stale_urls = defaultdict()
    
        for outline in main_tree.findall('.//outline[@xmlUrl]'):
            url = outline.attrib['xmlUrl']
            try:
                result = urlparse(url)
                if not all([result.scheme, result.netloc]):
                    raise
            except Exception:
                print(f"Malformed URL: {url}")
                print(et.tostring(outline, method="xml").decode("UTF-8"))
                print("Repair the OPML file and try again.")
                exit(1)
    
            data = (url,)
            try:
                cursor.execute('SELECT status.url AS url,ttl,tried,success, \
                    status,lastmodified,etag \
                            FROM status \
                            LEFT JOIN modified ON status.url = modified.url \
                            WHERE status.url=?', data)
                try:
                    url,ttl,tried,success, status, \
                    lastmodified,etag = cursor.fetchone()
                except Exception:
                    # initialize this instead
                    ttl = 0
                    tried = 0
                    success = 0
                    status = 0
                    lastmodified = ''
                    etag = ''
            except Exception as e:
                print(f"Failed to retrieve db record for {url} {e}")
                exit(1)
    
            lastmodified = validate_last_modified(lastmodified)
            etag = validate_etag(etag)
    
            if verbosity:
                print('db rec:',
                      f'ttl: {ttl},',
                      f'tried: {tried},',
                      f'success: {success},',
                      f'status: {status},',
                      f'lastmodified: {lastmodified},',
                      f'etag: {etag},',
                      f'url: {url}')
    
            urls.append((url,ttl,tried,success,status,lastmodified,etag))
    
            if verbosity:
                print('Queuing for processing', url)
    
        if verbosity:
            print("Fetching feeds from list of URLs")
    
        # this number must be low (<15) for home networks
        pool = ThreadPool(threads)
        results = pool.imap_unordered(fetch_url, urls)
    
        pool.close()
        pool.join()
    
        main_tree = parse_results(main_tree, results, exportlog, cursor,
                                  connection, oktime, stale_urls)
    
        return(main_tree)
    
    def fetch_url(url):
        global verbosity
        global forefetch
    
        # inherited from SQL query
        url,ttl,tried,success,status,lastmodified,etag = url
    
        # reply info as a dictionary to save on return arguments
        reply =  {
            'ttl': ttl,
            'tried': datetime.utcnow().replace(microsecond=0),
            'success': success,     # integer
            'status': 0,            # integer
            'redirection': '',      # string
            'length': 0,            # integer
    
            # validate or clear Last-Modified and ETag values
            'lastmodified': validate_last_modified(lastmodified),
            'etag': validate_etag(etag),
        }
    
        if verbosity:
            print(f"HTTP fetch of {url} last tried {tried}")
    
        # declare feed so that 'None' is returned for errors by default
        feed = None
    
        counter = 2
    
        while (counter):
            counter = counter - 1
            # TTL is checked first to avoid even fetching before its time to do so
            # thus there are no headers, status, errors, etc because of no fetch
            t = datetime.fromtimestamp(success)
            n = datetime.utcnow()
            if not forcefetch and n - t < timedelta(minutes=ttl):
                # return(url, None, n, 0, 0, 'ttl')
                # return(url, None, ttl, n, success, 2,
                #       lastmodified, etag, '', 0)
                reply['status'] = 2
                return(url, feed, reply, 0)
    
            # build headers to request ETag and/or Last-Modified if available
            if lastmodified and etag and not forcefetch:
                requestHeaders = dict(
                    [
                        (
                            'User-Agent',
                            "Roy and Rianne's Righteously Royalty-free RSS Reader v 0.2",
                        ),
                        (
                            'If-None-Match', etag,
                        ),
                        (
                            'If-Modified-Since', lastmodified,
                        ),
                    ]
                )
            elif etag and not forcefetch:
                requestHeaders = dict(
                    [
                        (
                            'User-Agent',
                            "Roy and Rianne's Righteously Royalty-free RSS Reader v 0.2",
                        ),
                        (
                            'If-None-Match', etag,
                        ),
                    ]
                )
            elif lastmodified and not forcefetch:
                requestHeaders = dict(
                    [
                        (
                            'User-Agent',
                            "Roy and Rianne's Righteously Royalty-free RSS Reader v 0.2",
                        ),
                        (
                            'If-Modified-Since', lastmodified,
                        ),
                    ]
                )
            else:
                requestHeaders = dict(
                    [
                        (
                            'User-Agent',
                            "Roy and Rianne's Righteously Royalty-free RSS Reader v 0.2",
                        ),
                    ]
                )
    
            # try fetching actual feed
            url2 = quote(url, safe=":/=&?@,~`%+")
            if url != url2:
                print(f"Warning, odd URL: {url}")
    
            request = Request(url=url2, headers=requestHeaders)
            try:
                with urlopen(request, timeout=20) as response:
                    status = response.getcode()
                    try:
                        # it's probably UTF-8 Unicode
                        content = response.read().decode("UTF-8")
                    except UnicodeDecodeError as e:
                        # if the file was not UTF-8 Unicode, check if it
                        # was gzipped; some day .headers.get() might be deprecated
                        content_encoding = response.headers.get('Content-Encoding')
                        if content_encoding == 'gzip':
                            try:
                                content = gzip.decompress(response.read())
                            except:
                                content = response.read()
                        else:
                            content = response.read()
    
            except HTTPError as e:
                # server responded but the feed was not retrieved
                reply['status'] = e.code
                h = CaseInsensitiveDict(e.headers)
                try:
                    reply['lastmodified'] = h['Last-Modified']
                except Exception:
                    reply['lastmodified'] = ''
    
                try:
                    reply['etag'] = h['ETag']
                except Exception:
                    reply['etag'] = ''
    
                del h
                if verbosity:
                    print(f"Fetch HTTPError {e.code}, '{e}' : {url}")
                return(url, feed, reply, e)
            except URLError as e:
                # retry network errors up to value in 'counter'
                if (counter):
                    if verbosity:
                        print(f"Retrying URLError '{e}' : {url}")
                    sleep(1)
                    continue
                # host is not there, http daemon not responding,
                # or protocol unknown
                if verbosity:
                    print(f"Fetch URLError '{e}' : {url}")
                # SSLError kludge - python3-urllib3 pkg fails to recognize it
                if re.search('CERTIFICATE_VERIFY_FAILED', str(e)):
                    if re.search('certificate has expired', str(e)):
                        return(url, feed, reply, 'TLSExpired')
                    return(url, feed, reply, 'TLSError')
                elif re.search('SSL:', str(e)):
                    return(url, feed, reply, 'TLSError')
                # URLError
                return(url, feed, reply, 'URLError')
            except SSLError as e:
                if verbosity:
                    print(f"Fetch SSLError '{e}' : {url}")
                reply(url, feed, reply, 'TLSError')
            except OSError as e:
                if verbosity:
                    print(f"Fetch OSError '{e}' : {url}")
                return(url, feed, reply, 'OSError')
            except ConnectionResetError as e:
                print(f"Connection Reset.  Skipping feed: {url}")
                return(url, feed, reply, e)
            except Exception:
                e = os.sys.exc_info()[0]
                print(f"Fetch generally failed '{e}' : {url}")
                return(url, feed, reply, e)
    
            reply['status'] = status
            if status >= int(400) and int(status) < 500:
                return(url, feed, reply, 'Error')
    
            responseHeaders = CaseInsensitiveDict(response.getheaders())
    
            try:
                reply['lastmodified'] = \
                    validate_last_modified(responseHeaders['Last-Modified'])
            except Exception:
                reply['lastmodified'] = ''
    
            try:
                reply['etag'] = validate_etag(responseHeaders['ETag'])
            except Exception:
                reply['etag'] = ''
    
            reply['etag'] = validate_etag(reply['etag'])
            reply['length'] = len(content)
    
            try:
                feed = feedparser.parse(content)
            except Exception:
                feed = None
                return(url, feed, reply, 'Could not parse')
    
            if response.geturl() != url:
                reply['redirection'] = response.geturl()
                if verbosity:
                    print(f" Redirection {url} -> ${response.geturl()}")
                    # either permanent or temporary redirection, but not known
            else:
                reply['redirection'] = ''
    
            # everything was ok, exit loop
            break
    
        return(url, feed, reply, 0)
    
    def parse_results(main_tree, results, exportlog, cursor, connection,
                      oktime, stale_urls):
        global verbosity
        global forcefetch
        global forceclose
    
        logging = False
        if exportlog is True:
            log = None
            logging = True
        elif exportlog:
            try:
                log = open(exportlog, 'w', encoding='utf-8')
            except OSError as e:
                print(f"Some error opening logging: {e}")
                exit(1)
            logging = True
    
        if logging:
            # headers for log data
            print(f"status\tttl\ttimestamp\turl", file=log)
    
        if verbosity:
            print("Producing HTML from the results")
    
        for url, feed, reply, error in results:
    
            size = reply['length']
            ttl = reply['ttl']
            tried = reply['tried']
            success = reply['success']      # integer
            status = reply['status']
            lastmodified = reply['lastmodified']
            etag = reply['etag']
            redirection = reply['redirection']
            tried = tried.strftime("%s")
    
            try:
                ttl = feed['feed']['ttl']
            except Exception:
                ttl
    
            if logging:
                print(f"{status}\t{ttl}\t{tried}\t{url}", file=log)
    
            if verbosity:
                print(f"Processing {status} : {url} : {error}")
    
            if error == 'OSError' or error == 'URLError':
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 4
            elif error == 'TLSError':
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 6
            elif error == 'TLSExpired':
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 7
            elif status == 404:
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 404
            elif status == 403:
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 403
            elif status == 304:
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 304
            elif status == 2:
                # TTL
                now = datetime.utcnow().replace(microsecond=0)
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 2
                stale_urls[url]['ttl'] = datetime.fromtimestamp(reply['success']) \
                    +timedelta(minutes=ttl)
            elif isinstance(feed, type(None)):
                # malformed feed
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 5
    
            try:
                stale_urls[url]
                stale_urls[url]['lastmodified'] = \
                    validate_last_modified(lastmodified)
            except Exception:
                True
    
            if error:
                data = (url, ttl, status, tried)
                try:
                    cursor.execute("REPLACE INTO status \
                                    (url,ttl,status,tried) \
                                    VALUES (?,?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"Could not replace or update status error {url}")
                    exit(1)
    
                data = (url, lastmodified, etag)
                try:
                    cursor.execute("REPLACE INTO modified \
                                    (url,lastmodified,etag) \
                                    VALUES (?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"Could not replace or update modified error {url}")
                    exit(1)
    
                if verbosity:
                    print(f"Skipping because of error: {status}, {error}, {url}")
                continue
    
            elif status == 2:
                # ttl
                data = (ttl,tried,success,status,url)
                try:
                    cursor.execute("REPLACE INTO status \
                                    (ttl,tried,success,status,url) \
                                    VALUES (?,?,?,?,?)", data)
                    connection.commit()
                except sqlite3.Error as e:
                    print(f"Could not replace or update status empty feed {url}")
                    print(f"\t",e.sqlite_errorname)
                    exit(1)
    
                data = (url, lastmodified, etag)
                try:
                    cursor.execute("REPLACE INTO modified \
                                    (url,lastmodified,etag) \
                                    VALUES (?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"Could not replace or update modified empty feed {url}")
                    exit(1)
    
                if verbosity:
                    print(f"Skipping because of empty feed: {url}")
                continue
    
            elif isinstance(feed, type(None)):
                data = (url,ttl,status,tried)
                try:
                    cursor.execute("REPLACE INTO status \
                                    (url,ttl,status,tried) \
                                    VALUES (?,?,?,?)", data)
                    connection.commit()
                except sqlite3.Error as e:
                    print(f"Could not replace or update status empty feed {url}")
                    print(f"\t",e.sqlite_errorname)
                    exit(1)
    
                data = (url, lastmodified, etag)
                try:
                    cursor.execute("REPLACE INTO modified \
                                    (url,lastmodified,etag) \
                                    VALUES (?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"Could not replace or update modified empty feed {url}")
                    exit(1)
    
                if verbosity:
                    print(f"Skipping because of empty feed: {url}")
                continue
    
            elif feed.bozo and not redirection:
                data = (url,int(tried),int(status))
                try:
                    cursor.execute("REPLACE INTO status \
                                    (url,tried,status) \
                                    VALUES (?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"A) Could not replace or update malformed feed {url}")
                    exit(1)
    
                data = (url, lastmodified, etag)
                try:
                    cursor.execute("REPLACE INTO modified \
                                    (url,lastmodified,etag) \
                                    VALUES (?,?,?)", data)
                    connection.commit()
                except Exception:
                    print(f"B) Could not replace or update malformed feed {url}")
                    exit(1)
    
                if verbosity:
                    print("Skipping because of malformed feed: {url}")
                # malformed feed
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 5
                stale_urls[url]['lastmodified'] = \
                    validate_last_modified(lastmodified)
                continue
    
            try:
                feed['feed']['title']
            except Exception:
                stale_urls[url] = {}
                stale_urls[url]['redirection'] = redirection
                stale_urls[url]['code'] = 1
                stale_urls[url]['lastmodified'] = \
                    validate_last_modified(lastmodified)
                if verbosity:
                    print("Skipping because of bad feed: {url}")
                continue
    
            try:
                ttl = feed['feed']['ttl']
            except Exception:
                ttl = ttl
    
            # normal update
            data = (url,int(ttl),int(tried),int(tried),int(status))
            try:
                cursor.execute("REPLACE INTO status \
                                (url,ttl,tried,success,status)\
                                VALUES (?,?,?,?,?)", data)
                connection.commit()
            except Exception:
                print(f"Could not replace or update {url}")
                exit(1)
    
            data = (url,str(lastmodified),str(etag))
            try:
                cursor.execute("REPLACE INTO modified \
                                (url,lastmodified,etag)\
                                VALUES (?,?,?)", data)
                connection.commit()
            except Exception:
                print(f"Could not replace or update {url}")
                exit(1)
    
            # begin to process results for the feed
            p = './/outline[@xmlUrl="' + url + '"]'
            outline = main_tree.find(p)
            if isinstance(outline, type(None)):
                print(f'Error: "{url}"', file=sys.stderr)
                continue
    
            ul = et.Element('ul')
            if not isinstance(feed, type(None)):
                # because of the massive inconsistencies in how
                # sites mismanage date formats, it is necessary
                # to standardize the date format.  move to own function some day
                countAllEntries = 0
                for post in feed.entries:
                    countAllEntries = countAllEntries + 1
                    # in practice dates vary in format and are non-standard
                    dd = False
                    try:
                        d = dateparser.parse(post.updated,
                                             languages=['en'])
                    except Exception:
                        try:
                            d = dateparser.parse(post.pubdate, languages=['en'])
                        except Exception:
                            try:
                                d = dateparser.parse(post.published,
                                                     languages=['en'])
                            except Exception:
                                d = datetime.utcnow()
    
                    try:
                        d = d.date()
                    except Exception:
                        d = datetime.utcnow()
                        d = d.date()
                        dd = True
    
                    # Wed, 02 Oct 2002 13:00:00 GMT
                    post.updated = d.strftime('%a, %d %b %Y %T %z')
                    post.internaldate = d
    
                # here is where the sorting by date happens
                latestEntry = datetime(1,1,1).date()
                countOkEntries = 0
                countTitles = 0
                for post in sorted(feed.entries,
                                   key=lambda x: x.internaldate,
                                   reverse=True):
                    d = post.internaldate
    
                    # track what the most recent entry was, even if it is not used
                    if d > latestEntry:
                        latestEntry = d
    
                    # keep the entry if it is new enough
                    if d >= oktime:
                        pub = d.strftime("%F")
                        li = et.SubElement(ul, 'li')
                        anchor = et.SubElement(li, 'a')
                        span = et.Element('span')
                        span.attrib['class'] = 'date'
                        span.text = pub
                        try:
                            # anchor.text = html.escape(post.title, quote=False)
                            anchor.text = escape_entities(post.title)
                        except Exception:
                            anchor.text = 'n/a'
                            anchor.attrib['href'] = 'wonky'
                            anchor.set('title', 'wonky: title missing')
                            outline.set('class','wonky')
                        else:
                            if re.search(r'\w', anchor.text):
                                countTitles = countTitles + 1
    
                                # allow a few markup elements through
                                anchor.text = re.sub(r'\<(/?em)\>',
                                                     r'<\1>', anchor.text)
                                anchor.text = re.sub(r'\<(/?cite)\>',
                                                     r'<\1>', anchor.text)
                                anchor.text = re.sub(r'\<(/?b)\>',
                                                     r'<\1>', anchor.text)
                                anchor.text = re.sub(r'\<(/?strong)\>',
                                                     r'<\1>', anchor.text)
    
                        anchor.insert(0,span)
                        try:
                            anchor.attrib['href'] = post.link
                        except Exception:
                            anchor.attrib['href'] = 'wonky'
                            anchor.set('title', 'wonky: link missing')
                            outline.set('class','wonky')
                        else:
                            outline.set('class','ok')
                            if size > 1000000:
                                outline.set('oversize', bytesToUnits(size))
                            elif size:
                                outline.set('size', bytesToUnits(size))
    
                        outline.append(ul)
                        countOkEntries = countOkEntries + 1
    
                if not countOkEntries:
                    stale_urls[url] = {}
                    stale_urls[url]['redirection'] = redirection
                    stale_urls[url]['code'] = 3
                    stale_urls[url]['lastmodified'] = \
                        validate_last_modified(lastmodified)
    
                    li = et.SubElement(ul, 'li')
                    if (success):
                        if countAllEntries:
                            li.text='No feed entries newer than '+\
                            latestEntry.strftime("%F")+',' \
                            +' last successful fetch was '\
                            + datetime.fromtimestamp(int(success)).strftime("%F")
                        else:
                            li.text='No feed entries.' \
                            +' Last successful fetch was '\
                            + datetime.fromtimestamp(int(success)).strftime("%F")
                    else:
                        li.text='No feed entries or no feed entries newer than '+\
                            oktime.strftime("%F")+', no successful fetch yet'
                    outline.append(ul)
                else:
                    if countTitles != countOkEntries:
                        outline.set('class', 'wonky')
                        if countTitles:
                            outline.set('title', 'wonky: some titles missing')
                        else:
                            outline.set('title', 'wonky: all titles missing')
    
                    if not forceclose:
                        outline.set('open', '1')
    
            # show that there was some kind of Redirection 1/2
            if redirection:
                outline.attrib['redirectUrl'] = redirection
                outline.append(ul)
                outline.attrib['sup'] = 'redirection'
                outline.set('class','redirect')
    
        if verbosity:
            print("Annotating URLs with TTL remaining")
    
        for url in stale_urls:
            p = './/outline[@xmlUrl="' + url + '"]'
            outline = main_tree.find(p)
            if isinstance(outline, type(None)):
                print(f'Error: "{url}"', file=sys.stderr)
                continue
    
            su = stale_urls[url]['code']
    
            if su == 304:
                outline.attrib['sup'] = 'Unmodified'
                outline.set('class','unmodified')
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                try:
                    if stale_urls[url]['lastmodified']:
                        li.text = 'Unmodified since last visit.  ' + \
                            'Allegedly Last-Modified: ' + \
                            stale_urls[url]['lastmodified']
                    else:
                        li.text = 'Unmodified since last visit.'
                except Exception:
                    False
                outline.append(ul)
            elif su == 1:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Broken feed'
                outline.append(ul)
                outline.attrib['sup'] = 'Broken Feed'
                outline.set('class','broken')
            elif su == 2:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='TTL not expired, check back at ' \
                    + str(stale_urls[url]['ttl']) + ' UTC'
                outline.append(ul)
                outline.attrib['sup'] = 'TTL not expired.'
                outline.set('class','ttl')
            elif su == 3:
                outline.attrib['sup'] = 'No recent feeds.'
                outline.set('class','recent')
            elif su == 4:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Site not available.'
                outline.append(ul)
                outline.attrib['sup'] = 'Site not available.'
                outline.set('class','network')
            elif su == 5:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Malformed or empty feed.'
                outline.append(ul)
                outline.attrib['sup'] = 'Malformed or empty feed.'
                outline.set('class','malformed')
            elif su == 6:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Site TLS certificate error.'
                outline.append(ul)
                outline.attrib['sup'] = 'Site TLS certififcate error.'
                outline.set('class','tlserror')
            elif su == 7:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Site TLS certificate has expired.'
                outline.append(ul)
                outline.attrib['sup'] = 'Site TLS certififcate has expired.'
                outline.set('class','tlserror')
            elif su == 404:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Missing remote feed file. '
                span = et.SubElement(li, 'span')
                span.text = url
                outline.append(ul)
                outline.attrib['sup'] = 'Missing File'
                outline.set('class','missing')
            elif su == 403:
                ul = et.Element('ul')
                li = et.SubElement(ul, 'li')
                li.text='Access denied.'
                outline.append(ul)
                outline.attrib['sup'] = 'Access denied'
                outline.set('class','access')
            elif su == 2:
                try:
                    pt = stale_urls[url]['ttl']
                    t = 'Check back later at '+pt.strftime("%F %T")+' UTC'
                except Exception:
                    t = 'Check back later.'
    
                li = et.SubElement(outline, 'li')
                li.text = t
                outline.attrib['sup'] = t
                outline.set('class','ttl')
            else:
                try:
                    pt = stale_urls[url]['ttl']
                    t = 'Check back later at '+pt.strftime("%F %T")+' UTC'
                except Exception:
                    t = 'Check back later.'
                para.text = t
                outline.attrib['sup'] = t
                outline.set('class','recent')
    
            # show that there was some kind of Redirection 2/2
            if stale_urls[url]['redirection']:
                outline.attrib['redirectUrl'] = stale_urls[url]['redirection']
                outline.append(ul)
                outline.attrib['sup'] = 'redirection'
                outline.set('class','redirect')
    
        # this XPath is slow
        if verbosity:
            print("Culling empty nodes")
    
        for ok in main_tree.xpath('.//outline[descendant::outline[@class="ok"]]|.//outline[descendant::outline[@class="redirect"]]'):
            ok.set('class', 'ok')
            if not forceclose:
                ok.set('open', '1')
    
        # close nodes labeled as Defunct
        for defunct in main_tree.xpath('.//outline[contains(@text,"Defunct")]'):
            defunct.attrib.pop('open', None)
    
        # for empty in main_tree.xpath('.//outline[not(descendant::ul[li]) and not(descendant::p)]'):
        #    empty.set('class', 'broken')
    
        if verbosity > 2:
            print(et.tostring(main_tree, method="xml").decode("UTF-8"))
    
        if exportlog and log:
            log.close()
        elif logging:
            exit(0)
    
        return(main_tree)
    
    def output_css():
        css=''':root {
    	--body-bg-lt: #fff;
    	--body-bg-dk: #111;
    	--summary-bg-lt: #eee;
    	--summary-bg-dk: #777;
    	--details-bg-lt: #bbb;
    	--details-bg-dk: #555;
    	--details-bg-open-lt: #eee;
    	--details-bg-open-dk: #999;
    	--li-even-bg-lt: #c8c8c8;
    	--li-even-bg-h-lt: #aa6;
    	--li-even-bg-dk: #777;
    	--li-even-bg-h-dk: #770;
    	--li-odd-bg-dk: #888;
    	--li-odd-bg-h-dk: #880;
    	--li-odd-bg-lt: #d8d8d8;
    	--li-odd-bg-h-lt: #996;
    	--a-visited-date-lt: #777;
    	--a-visited-date-dk: #444;
    	--a-site-lt: #888;
    	--a-site-dk: #888;
    	--a-site-open-lt: #666;
    	--a-site-open-dk: #666;
    	--dt-ttl-a-lt: #333;
    	--dt-ttl-a-dk: #333;
    
    	--text-color-lt: #000;
    	--text-color-dk: #ccc;
    }
    
    body:has(input.mode) {
    	/* light mode */
    	--body-bg: var(--body-bg-lt);
    	--text-color: var(--text-color-lt);
    	--li-even-bg: var(--li-even-bg-lt);
    	--li-odd-bg:  var(--li-odd-bg-lt);
    	--details-bg: var(--details-bg-lt);
    	--details-bg-open: var(--details-bg-open-lt);
    	--a-visited-date: var(--a-visited-date-lt);
    	--dt-ttl-a: var(--dt-ttl-a-lt);
    	--li-even-bg-h: var(--li-even-bg-h-lt);
    	--li-odd-h-bg: var(--li-odd-bg-h-lt);
    	--a-site: var(--a-site-lt);
    	--a-site-open: var(--a-site-open-lt);
    }
    body:has(input.mode:checked) {
    	/* dark mode */
    	--body-bg: var(--body-bg-dk);
    	--text-color: var(--text-color-dk);
    	--li-even-bg: var(--li-even-bg-dk);
    	--li-odd-bg:  var(--li-odd-bg-dk);
    	--details-bg: var(--details-bg-dk);
    	--details-bg-open: var(--details-bg-open-dk);
    	--a-visited-date: var(--a-visited-date-dk);
    	--dt-ttl-a: var(--dt-ttl-a-dk);
    	--li-even-bg-h: var(--li-even-bg-h-dk);
    	--li-odd-h-bg: var(--li-odd-bg-h-dk);
    	--a-site: var(--a-site-dk);
    	--a-site-open: var(--a-site-open-dk);
    }
    
    body { background-color: var(--body-bg); }
    
    /* floating toggle switch */
    p#togglemode {
    	float: left;
    }
    
    label.toggle {
    	position : relative ;
    	display : inline-block;
    	width : 2.4em;
    	height : 4.4em;
    	background-color: #000;
    	border-radius: 2em;
    	border: 0.1em solid #aaa;
    }
    
    /* After slide changes */
    label.toggle:after {
    	content: '';
    	position: absolute;
    	width: 2em;
    	height: 2em;
    	border-radius: 2em;
    	background-color: #aaa;
    	margin: 0.1em;
    	padding: 0.1em;
    	transition:  all 0.5s;
    }
    
    /* Checkbox checked effect */
    input.mode:checked + label.toggle::after {
    	top: 2em;
    }
    
    /* Checkbox checked toggle label bg color */
    input.mode:checked + label.toggle {
    	background-color: #eee;
    }
    
    /* Checkbox vanished */
    input.mode {
    	display : none;
    }
    
    h1, h2, h3, h4, h5 {
    	padding: 0.2em;
    	text-align: center;
    	font-family: sans-serif;
    	color: var(--text-color);
    	/* border-bottom: thin solid #333; */
    }
    
    /* html body dl dt details dd details ul li */
    dl {
    	margin-left:    1.5em;
    	margin-right:   1.5em;
    	padding-bottom: 0.5em;
    }
    
    dt.broken {
    	color: #444;
    }
    
    dd > details > ul {
    	margin-bottom: 0.3em;
    }
    
    details > dl > ul > li {
    	border-top-left-radius:     0.2em 0.2em;
    	border-bottom-left-radius:  0.2em 0.2em;
    	border-bottom-right-radius: 0.2em 0.2em;
    	border-top-right-radius:    0.2em 0.2em;
    	margin-right: 1em;
    	padding-left: 0.5em;
    	text-indent: -0.5em;
    	list-style: none; }
    
    li > a {
    	border-top-left-radius:     0.2em 0.2em;
    	border-bottom-left-radius:  0.2em 0.2em;
    	border-bottom-right-radius: 0.2em 0.2em;
    	border-top-right-radius:    0.2em 0.2em;
    	padding-left: 0.5em;
    	padding-right: 0.5em;
    }
    
    li:nth-child(even) > a:hover { background-color: var(--li-even-bg-h);}
    li:nth-child(odd) > a:hover  { background-color: var(--li-odd-h-bg);}
    
    li:nth-child(even) { background-color: var(--li-even-bg);}
    li:nth-child(odd)  { background-color: var(--li-odd-bg);}
    
    summary {
    	font-weight: bold;
    	list-style: none; }
    
    /* not modified since last check (304) */
    dt.unmodified details > summary::before {
    	content: "◷";
    }
    dt.unmodified details[open] > summary::before {
    	content: "◶";
    }
    
    /* site down, network, or other OSError */
    /* ttl has not expired */
    dt.network details > summary::before {
    	content: "⊚";
    }
    dt.network details[open] > summary::before {
    	content: "⊚";
    }
    
    dt.ttl details > summary::before {
    	content: "⧖";
    }
    dt.ttl details[open] > summary::before {
    	content: "⧗";
    }
    
    /* no recent entries */
    dt.recent details > summary::before {
    	content: "▷";
    }
    dt.recent details[open] > summary::before {
    	content: "▽";
    }
    
    dt.broken details > summary::before {
    	content: "◌";
    }
    
    dt.broken details[open] > summary::before {
    	content: "◌";
    }
    
    /* feed missing */
    dt.missing details > summary::before {
    	content: "○";
    }
    dt.missing details[open] summary::before {
    	content: "○";
    }
    
    /* redirecton */
    dt.redirect details > summary::before {
    	content: "▸";
    	color: #a44;
    }
    dt.redirect details[open] summary::before {
    	content: "▾";
    	color: #a44;
    }
    
    /* tls error */
    dt.tlserror details > summary::before {
    	content: "▸";
    	color: #000;
    }
    dt.tlserror details[open] summary::before {
    	content: "▾";
    	color: #000;
    }
    
    /* url works but feed malformed */
    dt.broken details > summary > a {
    	color: #333;
    }
    /* feed malformed or empty */
    dt.malformed details > summary::before {
    	content: "⦼";
    }
    dt.malformed details[open] summary::before {
    	content: "⨸";
    }
    
    /* access forbidden */
    dt.access details > summary::before {
    	width: 3em;
    	content: "◍";
    }
    dt.access details[open] > summary::before {
    	content: "◍";
    }
    
    details {
    	border-top-left-radius:     0.3em 0.3em;
    	border-bottom-left-radius:  0.3em 0.3em;
    	border-bottom-right-radius: 0.3em 0.3em;
    	border-top-right-radius:    0.3em 0.3em;
    	margin-bottom: 0.5em;
    	border: thin solid #222;
    	background-color: var(--details-bg);
    }
    
    details[open] {
    	background-color: var(--details-bg-open);
    }
    
    dt.ok > details > summary::before {
    	content: "▶";
    }
    
    dt.wonky > details > summary::before {
    	content: "⨻";
    	transform: rotate(60deg);
    	color: #600;
    }
    
    dt.wonky > details[open] > summary::before {
    	content: "⨻";
    	transform: rotate(180deg);
    	color: #600;
    }
    
    dt > details > summary::before {
    	padding-left: 0.5em;
    	padding-right: 0.5em;
    	content: "▷";
    	color: #000;
    	font-size: 150%;
    	font-weight: bold;
    }
    
    details[open] > summary {
    	border-top-right-radius:    0.3em 0.3em;
    	border-top-left-radius:     0.3em 0.3em;
    	border-bottom-right-radius: 0.3em 0.3em;
    	border-bottom-left-radius:  0.3em 0.3em;
    	border-bottom: thin solid #444;
    	margin-bottom: 0.3em;
    	background-color: var(--summary-bg);
    }
    
    dt.ok > details[open] > summary::before {
    	content: "▼";
    }
    
    dt > details[open] > summary::before {
    	padding-left: 0.5em;
    	padding-right: 0.5em;
    	/* content: "►"; */
    	content: "▽";
    	border-top-left-radius:     0.2em 0.2em;
    	border-bottom-left-radius:  0.2em 0.2em;
    	border-top-right-radius:    0.2em 0.2em;
    	border-bottom-right-radius: 0.2em 0.2em;
    	font-size: 150%;
    	font-weight: bold;
    }
    
    details > dl > dd {
    	padding: 1em;
    	margin-right: 2em;
    	border-bottom: thin solid #444;
    }
    
    span.date {
    	font-family: monospace;
    	font-weight: bold;
    	color: #333;
    }
    
    a:visited span.date {
    	color: var(--a-visited-date);
    }
    
    dl dt.ttl a {
    	color: var(--dt-ttl-a);
    }
    
    dt a.redirection {
    	text-decoration: none;
    	color: #0000EE;
    }
    
    /* lll */
    dt a.oversize {
    	text-decoration: none;
    	color: #444;
    }
    
    dt > details > summary > span > a.site {
    	text-decoration: none;
    	color: var(--a-site);
    }
    
    dt > details > summary > span > a.feed {
    	text-decoration: none;
    	color: var(--a-site);
    }
    
    dt > details[open] > summary > span > a.site {
    	text-decoration: none;
    	color: var(--a-site-open);
    }
    
    dt > details[open] > summary > span > a.feed {
    	text-decoration: none;
    	color: var(--a-site-open);
    }
    
    dt.ok > details[open] > summary > span a.site {
    	text-decoration: none;
    	color: #000;
    }
    
    dt.ok > details[open] > summary > span a.feed {
    	text-decoration: none;
    	color: #000;
    }
    
    
    '''
        return(css)
    
    def xml_to_html(feeds):
        global verbosity
    
        xsl = '''
    
    
    
    
    
    
     RRRRRR
     
    
    
     

    R.R.R.R.R.R.

    site feed Redirection: redirection oversize
  • ''' # print(et.tostring(feeds, method="xml").decode("UTF-8")) xslt = et.XML(xsl) transform = et.XSLT(xslt) dom2 = transform(feeds) xhtml = et.tostring(dom2,pretty_print=True) xhtml = unescape(xhtml.decode('utf-8')) return(xhtml) def xml_to_citation(feeds): global verbosity xsl = ''' RRRRRR

    R.R.R.R.R.R.

    ''' # print(et.tostring(feeds, method="xml").decode("UTF-8")) xslt = et.XML(xsl) transform = et.XSLT(xslt) dom2 = transform(feeds) xhtml = et.tostring(dom2,pretty_print=True) xhtml = unescape(xhtml.decode('utf-8')) return(xhtml) def initialize_date(startdate): if startdate: try: oktime = datetime.strptime(startdate, '%Y-%m-%d') except Exception: try: oktime = dateparse.parse(start.date, fuzzy=True) except Exception: print("Malformed or invalid date") exit(1) else: oktime = datetime.utcnow().replace(microsecond=0) \ - timedelta(days=2) oktime = oktime.date() return(oktime) def bytesToUnits(bytes: int): unit = 0 si =['', 'B', 'kB', 'MB', 'GB', 'TB'] while bytes > 1: unit = unit + 1 old = int(bytes) bytes = bytes / 1000 if unit >= len(si): return("large, odd size") return(f"{old} {si[unit]}") def getOutputDirectory(outputfile): if (outputfile): outputdirectory = re.sub('/[^/]+$', '', outputfile) else: outputdirectory = os.environ.get("XDG_RUNTIME_DIR") if (outputdirectory is None): outputdirectory = os.getcwd() if outputdirectory is None: outputdirectory = '.' if not os.path.isdir(outputdirectory): if not quiet: sys.stderr.write(outputdirectory + " is not a directory\n") sys.exit(1); return(outputdirectory) def CSSOutputFile(outputdirectory): # create the CSS file in the output directory, if needed cssoutputfile = outputdirectory + "/rrrrrr.css" if not os.path.exists(cssoutputfile): try: with open(cssoutputfile, "w") as css_file: css = output_css() css_file.write(css) css_file.close() except PermissionError: print(f"File or directory unwritable: {cssoutputfile}") sys.exit(1) except FileNotFoundError: print(f"Wrong file or file path 3: {cssoutputfile}") sys.exit(1) elif not os.path.isfile(cssoutputfile): if not quiet: sys.stderr.write(cssoutputfile + " is not a file\n") if not os.path.islink(cssoutputfile): if not quiet: sys.stderr.write(outputdirectory \ + " is not a symbolic link either\n") sys.exit(1); return(cssoutputfile) # main script dbpath = import_dbpath() if not dbpath: print(f"Path '{dbpath}' unavailable") exit(1) # read ARGV into options variable parser = ArgumentParser( prog='PROG', description="This script fetches updated RSS and Atom feeds as HTML.", formatter_class=RawTextHelpFormatter) parser.add_argument("-o", "--output", dest="outputfile", type=str, help="destination path for resulting HTML file, defaults XDG_RUNTIME_DIR if it exists or to current working directpry otherwise", default=None) parser.add_argument("-s", "--stdout", dest="stdout", action="store_true", help="send output to stdout instead of a file", default=False) parser.add_argument("--append", dest="append", action="store_true", help="append new OPML data instead of overwritig, default off", default=False) parser.add_argument("--citation", dest="citationformat", action="store_true", help="format HTML output for citation, default off", default=False) parser.add_argument("-c", "--clear", dest="clearopml", action="store_true", default=False, help="clear existing OMPL cache") parser.add_argument("-d", "--date", dest="startdate", type=str, help="date to start from yyyy-mm-dd", default=None) parser.add_argument("-e", "--export", dest="exportfile", type=str, nargs='?', help="output OPML file to stdout, or to optional file if named", default=False) parser.add_argument("-q", "--quiet", dest="quiet", action="store_true", default=False, help="suppress messages to stderr") parser.add_argument("--threads", dest="threads", type=int, default=10, help="number of threads to run concurrently, default 10, must be low (<15) on home networks.") parser.add_argument("--css", dest="exportcss", action="store_true", default=False, help="print matching CSS to stdout") parser.add_argument("--force", dest="forcefetch", action="store_true", default=False, help="try to fetch all URLs regardless of past errors") parser.add_argument("--close", dest="forceclose", action="store_true", default=False, help="force all detail elements to be close initially, the default is open.") parser.add_argument("--log", dest="exportlog", metavar='log_file', nargs="?", type=str, default=False, help="log connection info to file, or to stdout if no file given, may be combined with --force to list all missing or broken URLs ") parser.add_argument('importfiles', metavar='OPML_file', type=str, nargs='*', help='OPML files to import', default='') parser.add_argument("-v", "--verbose", dest="verbosity", action='count', help="increase verbosity of reporting.", default=0) parser.epilog=''' Fetch eligible RSS and Atom feeds and send them to a file as XHTML. A different destination can be designated with the -o option, or stdout with -s. A matching CSS file will be created in the same directory if it does not already exists. Before any feeds can be fetched they must first be loaded by passing an OPML-formatted file as a positional argument: rrrrrr.py feeds.opml Using a positional argument loads that OPML structure into the configuration. Loading overwrites the old configuration each time. Without options or positional arguments the script fetches the eligible feeds which have passed their TTL, from those feeds it listrs the available entries if they are fresher than last two days and prints them as XHTML. The default is to print to a file, but there is also the -o option: rrrrrr.py --stdout > feed.output.html or rrrrrr.py --output feed.output.html The start date can be overidden by the -d option with a date in the yyyy-mm-dd format: rrrrrr.py -d 2023-02-03 -o feed.output.html The script can also extract and print the OPML from its configuration as well as produce the CSS file matching the resulting HTML. ''' # get run time options options = parser.parse_args() verbosity = options.verbosity outputfile = options.outputfile appendopml = options.append exportfile = options.exportfile importfiles = options.importfiles startdate = options.startdate exportcss = options.exportcss exportlog = options.exportlog forcefetch = options.forcefetch forceclose = options.forceclose clearopml = options.clearopml stdout = options.stdout quiet = options.quiet threads = options.threads citationformat = options.citationformat if exportcss: print(output_css()) exit(0) if exportlog is None: exportlog = True if exportfile is None: exportfile = True if verbosity: print("
    ")
    
    db = dbpath + 'status.sqlite3'
    
    connection = sqlite3.connect(db)
    cursor = connection.cursor()
    # has to be configured for each and every connection
    # it is needed for the cascade deletion
    cursor.execute('PRAGMA foreign_keys = yes')
    
    try:
        cursor.execute("SELECT * FROM opml LIMIT 1")
        tmp, = cursor.fetchone()
    except Exception:
        try:
            initialize_db(cursor)
            if verbosity:
                print("Intitalizing database 1")
        except Exception:
            print("Intitalizing database failed 1")
            exit(1)
    
    if clearopml:
        cursor.execute("DELETE FROM opml")
        cursor.execute("DELETE FROM status")
        connection.commit()
        if verbosity:
            print("OPML cleared from database cache")
    
    opmltree = import_opml_files(importfiles, cursor)
    save_opml_into_db(opmltree, cursor)
    
    try:
        cursor.execute("SELECT * FROM opml LIMIT 1")
        try:
            tmp, = cursor.fetchone()
            if verbosity:
                print("OPML present in database")
        except Exception:
            print("Specify an OPML file 1")
            exit(3)
    except Exception:
        print("Specify an OPML file 2")
        exit(4)
    
    oktime = initialize_date(startdate)
    
    if verbosity:
        print("
    ") if exportfile: print(f"Exporting OPML to '{exportfile}'") export_opml_to_file(cursor, exportfile) exit(0) elif outputfile: # check for location of output files before processing feeds # first use default file name if only a directory was given if os.path.isdir(outputfile): outputdirectory = re.sub('/+$', '', outputfile) outputfile = outputdirectory + '/rrrrrr.html' if not quiet: print(f"Saving feed output to '{outputfile}'") if not os.access(outputdirectory, os.W_OK): sys.stderr.write(outputdirectory + " is not writable 1\n") sys.exit(1) if os.path.isfile(outputfile): # if the file exists, make sure it is writable if not os.access(outputfile, os.W_OK): sys.stderr.write(outputfile + " is not writable\n") sys.exit(1) outputdirectory = getOutputDirectory(outputfile) else: # if it does not exist, make sure the directory is writable outputdirectory = getOutputDirectory(outputfile) if not os.access(outputdirectory, os.W_OK): sys.stderr.write(outputdirectory + " is not writable 2\n") sys.exit(1) cssoutputfile = CSSOutputFile(outputdirectory) else: outputdirectory = os.environ.get("XDG_RUNTIME_DIR") if verbosity > 1: print(f" saving to {outputdirectory}") if not outputdirectory is None: if not os.path.isdir(outputdirectory): if not quiet: sys.stderr.write(outputdirectory + " is not a directory\n") exit(1); else: if (outputfile is None): try: outputdirectory = os.getcwd() except Exception: outputdirectory = '.' outputdirectory = re.sub('/+$', '', outputdirectory) outputfile = outputdirectory + '/rrrrrr.html' cssoutputfile = CSSOutputFile(outputdirectory) if not quiet and not stdout: sys.stderr.write(f"Saving to default location: {outputfile}\n") if outputfile: if verbosity and stdout: print("
    ")
        oktime = initialize_date(startdate)
        feeds = fetch_tree(cursor,oktime,exportlog)
        if verbosity:
            print(f"Saving feed output")
        if verbosity and stdout:
            print("
    ") if stdout: if verbosity: print(f"Sending feed output to stdout") if not citationformat: xhtml = xml_to_html(feeds) print(xhtml) else: xhtml = xml_to_citation(feeds) print(xhtml) else: if not citationformat: xhtml = xml_to_html(feeds) with open(outputfile, 'w') as out: out.write(xhtml) else: xhtml = xml_to_citation(feeds) with open(outputfile, 'w') as out: out.write(xhtml) cull_database(cursor,starttime) exit(0)

    Links/rrrrrr.README

    This Python3 script is distributed by Bytes Media UK
    under the Affero General Public License (AGPL) version 3.
    
    It is still in rather early stages and may change a bit.
    
    Output currently defaults to what is specified by the environment
    variable XDG_RUNTIME_DIR if it is available.  The output can
    be redirected to another file with --output or to stdout with
    the --stdout option if the output is to be captured using a
    redirection.  In order to initialize the script, export its CSS
    rules to a file, then load OPML data, then read the result using
    a web browser:
    
     ./rrrrrr.py feeds.opml
     firefox ${XDG_RUNTIME_DIR}/rrrrrr.html
    
    A matching CSS file is also generated there on first run.  The
    script's tracking of each feed is kept in an SQLite3 database
    in ${HOME}/.config/rrrrrr.sqlite3 by default.
    
    Thereafter the script can be run without specifying a data
    file and it will use the OPML data from its cache.
    
     ./rrrrrr.py
     firefox ${XDG_RUNTIME_DIR}/rrrrrr.html
    
    When loading a new OPML file, the default action is to use the
    new feeds from the new file, but keep retain the old records in the
    state tables when an entry already exists for a given feed.  The
    state table can be cleared with --clear or overwritten with --force.
    
    The browser itself will track whether or not a link has been
    visited or not.
    
    The script will skip feeds which have not changed since the last pass
    by tracking the ETag and Last-Modified headers in the HTTP response.
    
    The idea is for one to make one complete pass through the resulting HTML
    file in a single pass when reading the feeds.  That is inspired by the
    time management principle of processing any given document or task once
    and only once if possible.  Furthermore, reloading the feeds more than
    once a day is generally fruitless.
    
    See the --help option for more details.
    
    Bug reports welcome.
    Feature requests will at least be listened to. ;)

    Links/daily-supplementary.feeds

    # keep up to date in Git!
    
    https://www.gamingonlinux.com/article_rss.php
    https://opensource.com/feed
    # blocked by js : https://developers.redhat.com/blog/feed/
    https://opensourcesecurity.io/blog/feed
    https://www.redhat.com/en/rss/blog
    https://blog.mozilla.org/feed/
    https://news.opensuse.org/feed
    http://insights.ubuntu.com/feed
    http://linuxgizmos.com/feed
    https://puri.sm/feed/
    https://kubernetes.io/feed.xml
    https://www.archlinux.org/feeds/news
    http://feeds.feedburner.com/LnuxTech-lb
    # http://feeds.feedburner.com/tecmint
    http://feeds.feedburner.com/Ubuntubuzz
    https://vitux.com/feed
    https://www.fossmint.com/rss
    http://www.linuxbuzz.com/rss
    https://linuxhandbook.com/rss
    https://www.rosehosting.com/blog/feed/
    http://www.linuxtechi.com/feed/
    https://www.tecmint.com/feed/
    https://www.unixmen.com/feed
    https://feeds.feedburner.com/Ostechnix
    https://www.linuxandubuntu.com/feed
    https://www.linuxcloudvps.com/blog/feed
    

    Links/tr-merge-daily-links.sh

    #!/bin/sh
    
    PATH=/usr/local/bin:/usr/bin:/bin
    
    # see Git
    set -evx
    
    closure() {
        test -d ${tmpdir} || exit 1
        echo "Erasing temporary directory (${tmpdir}) and its files."
        rm -f ${tmpdir}/feed-tmp.*
        rmdir ${tmpdir}
    }
    
    cancel() {
        echo "Cancelled."
        closure
        exit 2
    }
    
    # trap various signals to be able to erase temporary files
    trap "cancel" 1 2 15
    
    d=$(date +"%F");
    
    read -t 120 -p "Enter a date or press return for $d: " dt;
    
    linkshome="/home/links"
    feeds=${linkshome}/Links/daily.feeds
    
    export PERL5LIB=${linkshome}/lib/
    
    # cd ${HOME}/Git/tr-git/Links/; git pull; cd -
    # update perl libraries from Git
    git --no-pager --git-dir /home/git/techrights.org.git/ \
    	show master:Links/lib/Links/MetaData.pm \
    	> ${PERL5LIB}/Links/MetaData.pm
    
    git --no-pager --git-dir /home/git/techrights.org.git/ \
    	show master:Links/lib/Links/SpamSites.pm \
    	> ${PERL5LIB}/Links/SpamSites.pm
    
    git --no-pager --git-dir /home/git/techrights.org.git/ \
            show master:Links/daily.feeds \
    	> ${feeds}
    
    if [ -n ${dt} ]; then
            dt=${dt:-$d};
            d=$(date -d ${dt} +"%F") || exit 1;
    	echo ${d};
    fi;
    
    datepath=$(date -d ${d} +"m%Y-%m")
    
    linksdir="${linkshome}/Links/${datepath}/"
    mergedfile="${linkshome}/Links/${datepath}/${d}-merged.html"
    
    srcfile="${linkshome}/Links/tmp/${d}.html"
    automatedfile="${linkshome}/Links/tmp/${d}-automated.html"
    otherlinks="${linkshome}/Links/tmp/other-links-${d}.txt"
    
    if ! test -e ${dir}; then
        if ! mkdir -p ${dir}; then
    	echo "problem making or finding'${dir}'"
            exit 1
        fi
    fi
    
    # verify camelCase variants for all URL-generated "tags" in manual file
    tr-links-check-camelcase.pl ${srcfile} || exit 1
    
    # validate XHTML in the manual file
    echo "Checking for '$srcfile'"
    test -e $file || exit 1;
    tidy -errors -quiet -xml ${srcfile} || exit 1;
    echo "Ok";
    
    echo "Checking if way is clear for new '${mergedfile}'"
    test -e ${mergedfile} && exit 1;
    echo "Ok";
    
    umask 027
    
    tmpdir=$(mktemp -d /tmp/feeds-tmp.XXXXXX)
    tmpfile=$(mktemp -p ${tmpdir} feed-tmp.XXXXXXX)
    
    # remove empty nodes from the manually collected links
    # and generate a table of contents
    tr-links-cull-empty.pl ${srcfile} > ${tmpfile}
    # do TOC separately in case links-cull-empty.pl fails
    test -d ${linksdir} || mkdir ${linksdir}
    cat ${tmpfile} | tr-links-toc.pl > ${mergedfile}
    rm  ${tmpfile}
    
    echo
    
    start=$(date -d "$d yesterday" +"%F")
    
    echo "Loading automated feeds"
    while read feed; do
    	tmpfile=$(mktemp -p ${tmpdir} feed-tmp.XXXXXXX)
        	tr-rss-since-scraper.pl -d $start -o ${tmpfile} ${feed} &
    done < ${automatedfile}
    
    # clear signal trapping
    trap - 1 2 15
    
    # remove temporary files
    closure
    
    cat ${automatedfile} >> ${mergedfile}
    
    dl=$(date -d "${d} last month" +"m%Y-%m")
    dn=$(date -d "${d}" +"m%Y-%m")
    p="/home/links/Links"
    
    # check this month and last month for duplicates, remove those found
    tr-links-de-duplicate.pl -w ${mergedfile}
    
    chmod 644 ${mergedfile}
    
    dir="/home/links/Links/${datepath}/"
    
    if test -e ${otherlinks}; then
            chmod 644 ${otherlinks}
            cp -p ${otherlinks} $dir && rm ${otherlinks}
    fi
    
    # insert citations formatted for social control media
    # links-interleave-social-control-media.pl -w ${mergedfile}
    
    exit 0
    

    Links/lib/Links/.directory-listing-ok

    Links/lib/Links/MetaData.pm

    package MetaData 0.1;
    
    use utf8;
    use parent qw(Exporter);
    use strict;
    use warnings;
    use feature qw(state);
    
    our @EXPORT = qw(camelCase cleanQuery);
    
    # 2021-01-24
    # convert "tag" to camelCase
    # updated: see Git history at Techrights.org (HTTP/S) or gemini://gemini.techrights.org
    
    state %siteLookup = (
        "tilde.town" => "",
        "washbear.neocities.org" => "",
        "neko314.hatenablog.com" => "ねこものがたり",
        "マリウス.com" => "マリウス",
        "xn--caaba8k0b0a7jzpccc.com" => "マリウス", # XXX: merge w/above
        "00f.net" => "00f",
        "0x65.dev" => "0x65",
        "100daystooffload.com" => "100 Days To Offload",
        "100r.co" => "Hundred Rabbits",
        "www.11ty.dev" => "11ty",
        "12daysofweb.dev" => "12 Days of Web",
        "blog.1password.com" => "1Password",
        "2600.com" => "2600",
        "2022.internethealthreport.org" => "Mozilla",
        "32bit.cafe" => "32-Bit Cafe",
        "37signals.com" => "37signals LLC",
        "www.404media.co" => "404 Media",
        "82mhz.net" => "Andreas",
        "8billiontrees.com" => "8 Billion Trees",
        "world.hey.com" => "37signals LLC",
        "www.2600.com" => "2600",
        "www.nokiamobilephonenews.co.uk" => "2S Media",
        "www.2-spyware.com" => "2spyware",
        "3dprintingindustry.com" => "3D Printing Industry",
        "www.3dprintingmedia.network" => "3D Printing Media Network",
        "www.3dsourced.com" => "3DSourced",
        "4mlinux.blogspot.com" => "4M Linux",
        "www.channelnews.com.au" => "4Square Media Pty Ltd",
        "4state.news" => "4StateNews",
        "7news.com.au" => "7NEWS",
        "celebrity.nine.com.au" => "9Celebrity",
        "9elements.com" => "9Elements GmbH",
        "www.9news.com.au" => "9NEWS",
        "9to5google.com" => "9to5Google",
        "9to5linux.com" => "9to5Linux",
        "99percentinvisible.org" => "99% Invisible",
        "www.majorcadailybulletin.com" => "Majorca, Spain",
        "major.io" => "Major Hayden",
        "archlinux.org" => "ArchLinux",
        "bbs.archlinux.org" => "ArchLinux",
        "ubuntustudio.org" => "Ubuntu Studio",
        "dissociatedpress.net" => "Joe Brockmeier",
        "www.kitguru.net" => "KitGuru",
        "rockylinux.org" => "Rocky Linux",
        "rmi.org" => "Rocky Mountain Institute",
        "arstechnica.com" => "Ars Technica",
        "blog.remirepo.net" => "Remi Collet",
        "www.motherjones.com" => "Mother Jones",
        "motherduck.com" => "MotherDuck",
        "www.mother.ly" => "Motherly Inc",
        "fossweekly.beehiiv.com" => "FOSS Weekly",
        "informatique-libre.be" => "Sébastien Wilmet",
        "sparkylinux.org" => "Sparky GNU/Linux",
        "feaneron.com" => "Georges Basile Stavracas Neto",
        "blog.thefinalzone.net" => "Luya Tshimbalanga",
        "librearts.org" => "Libre Arts",
        "learnubuntu.com" => "Learn Ubuntu",
        "mauikit.org" => "MauiKit",
        "guyabel.com" => "Guy Abel",
        "www.eyrie.org" => "Russ Allbery",
        "research.swtch.com" => "Russ Cox",
        "russ.garrett.co.uk" => "Russ Garrett",
        "tube.kockatoo.org" => "KDE Videos",
        "blog.urukproject.org" => "The Uruk Project Blog",
        "lists.fedoraproject.org" => "Fedora",
        "ubports.com" => "UBports",
        "www.montanalinux.org" => "Montana Linux",
        "www.gadgetbridge.com" => "Gadget Bridge",
        "nokiapoweruser.com" => "Nokia Power User",
        "paulmck.livejournal.com" => "Paul E. McKenney",
        "linux.slashdot.org" => "Slashdot",
        "www.fosslinux.com" => "FOSSLinux",
        "linuxconfig.org" => "LinuxConfig",
        "www.linuxbuzz.com" => "Linux Buzz",
        "thelinuxexp.com" => "The Linux Experiment",
        "dwaves.de" => "dwaves.de",
        "news.netcraft.com" => "Netcraft",
        "www.netcraft.com" => "Netcraft",
        "www.rosehosting.com" => "RoseHosting",
        "linuxize.com" => "Linuxize",
        "www.tuxmachines.org" => "Tux Machines",
        "neuroblog.fedoraproject.org" => "NeuroFedora",
        "www.gnunet.org" => "GNUnet",
        "www.gnupg.org" => "The GNU Privacy Guard",
        "containerjournal.com" => "Container Journal",
        "winbuzzer.com" => "WinBuzzer",
        "pxlnv.com" => "Nick Heer",
        "nhigham.com" => "Nick Higham",
        "egoslike.us" => "Nick Holland",
        "itsubuntu.com" => "It's Ubuntu",
        "pimylifeup.com" => "Pi My Life Up",
        "nextgentips.com" => "NextGenTips",
        "kde.org" => "KDE",
        "genode.org" => "Genode",
        "open-web-advocacy.org" => "Open Web Advocacy",
        "en.opensuse.org" => "OpenSUSE",
        "news.opensuse.org" => "OpenSUSE",
        "phoboslab.org" => "Dominic Szablewski",
        "dominique.leuenberger.net" => "Dominique Leuenberger",
        "www.collaboraoffice.com" => "Collabora",
        "collabfund.com" => "Collaborative Fund Management LLC",
        "wordpress.org" => "WordPress",
        "www.project-disco.org" => "CCIA",
        "blogs.gnome.org" => "GNOME",
        "kifarunix.com" => "Kifarunix",
        "feed.jupiter.zone" => "JupiterMedia",
        "linuxstans.com" => "LinuxStans",
        "fex-emu.com" => "FEX",
        "cpldcpu.com" => "Tim's Blog",
        "tim.siosm.fr" => "Timothée Ravier",
        "en.euro-linux.com" => "EuroLinux",
        "insidehpc.com" => "insideHPC",
        "utkarsh2102.com" => "Utkarsh Gupta",
        "ubuntu-news.org" => "Ubuntu News",
        "fridge.ubuntu.com" => "Ubuntu Fridge",
        "apachelog.wordpress.com" => "Harald Sitter",
        "www.pentestpartners.com" => "Pen Test Partners",
        "www.pcquest.com" => "PCQuest",
        "patentblog.kluweriplaw.com" => "Kluwer Patent Blog",
        "www.juve-patent.com" => "JUVE",
        "patentlyo.com" => "Dennis Crouch/Patently-O",
        "flightaware.com" => "FlightAware",
        "flutterfoundation.dev" => "Flock",
        "www.fosspatents.com" => "Florian Müller",
        "sha256.net" => "Florian Obser",
        "tlakh.xyz" => "Florian Obser",
        "linuxnightly.com" => "Linux Nightly",
        "thisweek.gnome.org" => "This Week in GNOME",
        "people.skolelinux.org" => "Petter Reinholdtsen",
        "www.livescience.com" => "Live Science",
        "koutoupis.com" => "Petros Koutoupis",
        "spaceref.com" => "SpaceRef",
        "www.clickorlando.com" => "Click Orlando",
        "fortune.com" => "Fortune",
        "www.tipsonunix.com" => "Tips On UNIX",
        "www.gimp.org" => "GNU Image Manipulation Program (GIMP)",
        "randomnerdtutorials.com" => "Random Nerd Tutorials",
        "randomoracle.wordpress.com" => "Random Oracle",
        "blog.passwordclass.xyz" => "RandomNixFix",
        "raphaelhertzog.com" => "Raphaël Hertzog",
        "www.rapid7.com" => "Rapid7 LLC",
        "www.reallinuxuser.com" => "Real Linux User",
        "blog.iconfactory.com" => "The Iconfactory",
        "fex-emu.org" => "FEX",
        "mintcast.org" => "mintCast Podcast",
        "www.os2museum.com" => "OS/2 Museum",
        "osinter.dk" => "OSINTer Blog",
        "ostechnix.com" => "OSTechNix",
        "peppe8o.com" => "peppe8o",
        "blog.simos.info" => "Simos Xenitellis",
        "thecyberwire.com" => "The Cyber Wire",
        "patch.com" => "Patch",
        "newsupdate.uk" => "News Update",
        "mightygadget.co.uk" => "Mighty Gadget",
        "www.winehq.org" => "WINE Project (Official)",
        "nairobiwire.com" => "Nairobi Wire Media",
        "blog.namangoel.com" => "Naman Goel",
        "prose.nsood.in" => "Naman Sood",
        "nate.mecca1.net" => "Nate",
        "pointieststick.com" => "Nate Graham",
        "www.volkerkrause.eu" => "Volker Krause",
        "maximullaris.com" => "Volodymyr Gubarkov",
        "voltrondata.com" => "Voltron Data",
        "erock.io" => "Eric Bower's Blog",
        "intel471.com" => "Intel 471",
        "internetfreedom.in" => "Internet Freedom Foundation",
        "www.isc.org" => "Internet Systems Consortium",
        "blogs.coreboot.org" => "Coreboot (Official)",
        "techhq.com" => "TechHQ",
        "techjury.net" => "TechJury",
        "technologizer.com" => "Technologizer",
        "tmb.apaopen.org" => "Technology, Mind, and Behavior",
        "www.technologynetworks.com" => "Technology Networks",
        "www.moneycontrol.com" => "MoneyControl",
        "embeddedartistry.com" => "Embedded Artistry LLC",
        "www.embedded.com" => "Embedded.com",
        "content.dictionary.com" => "Dictionary.com LLC",
        "www.dignited.com" => "Dignited",
        "gnuworldorder.info" => "GNU World Order (Audio Show)",
        "www.datasciencecentral.com" => "Tech Target Inc",
        "techtea.io" => "TechTea",
        "www.atechtown.com" => "Techtown",
        "www.hecticgeek.com" => "Hectic Geek",
        "www.openmandriva.org" => "OpenMandriva News",
        "debugpointnews.com" => "DebugPoint",
        "lpc.events" => "Linux Plumbers Conference (LPC)",
        "www.if-not-true-then-false.com" => "If Not True Then False",
        "www.ifixit.com" => "iFixit",
        "www.theserverside.com" => "The Server Side",
        "4mlinux-releases.blogspot.com" => "4MLinux Blog",
        "ipkitten.blogspot.com" => "IP Kat",
        "www.unifiedpatents.com" => "Unified Patents",
        "thettablog.blogspot.com" => "TTAB Blog",
        "www.linuxtechi.com" => "LinuxTechi",
        "www.linuxtuto.com" => "LinuxTuto",
        "owlhowto.com" => "Own HowTo",
        "blog.jabberhead.tk" => "Paul Schaub",
        "mschlander.wordpress.com" => "The Blog is Hot",
        "diffoscope.org" => "Diffoscope",
        "lhspodcast.info" => "Linux in the Ham Shack",
        "www.omglinux.com" => "OMG! Linux",
        "lists.freedesktop.org" => "Free Desktop",
        "kubernetes.io" => "Kubernetes Blog",
        "store.steampowered.com" => "Steam",
        "9to5mac.com" => "9to5Mac",
        "www.a10networks.com" => "A10 Networks, Inc",
        "aag-it.com" => "AAG",
        "advances.sciencemag.org" => "AAAS",
        "eurekalert.org" => "AAAS",
        "science.sciencemag.org" => "AAAS",
        "www.eurekalert.org" => "AAAS",
        "www.sciencemag.org" => "AAAS",
        "www.science.org" => "AAAS",
        "blog.8bit.lol" => "Aadi Desai",
        "cwa.omg.lol" => "Aaron Aiken",
        "if50.substack.com" => "Aaron A Reed",
        "redsymbol.net" => "Aaron Maxwell",
        "aaronparecki.com" => "Aaron Parecki",
        "lofi.limo" => "Aaron Parks",
        "www.aaronswartzday.org" => "Aaron Swartz Day",
        "www.abajournal.com" => "ABAJournal",
        "6abc.com" => "ABC",
        "abc7.com" => "ABC",
        "abc7chicago.com" => "ABC",
        "abc7news.com" => "ABC",
        "abc7ny.com" => "ABC",
        "abc13.com" => "ABC",
        "abc17news.com" => "ABC",
        "abc30.com" => "ABC",
        "abcnews.go.com" => "ABC",
        "abcnews4.com" => "ABC",
        "www.abc27.com" => "ABC",
        "www.klkntv.com" => "ABC",
        "www.wkbw.com" => "ABC",
        "www.finanznachrichten.de" => "ABC New Media AG",
        "tuxdigital.com" => "Tux Digital",
        "trendoceans.com" => "Trend Oceans",
        "www.netfilter.org" => "Linux",
        "www.linux.org" => "Linux.org",
        "www.linuxcapable.com" => "Linux Capable",
        "unixdigest.com" => "UNIXdigest",
        "unixcop.com" => "UNIX Cop",
        "blog.irvingwb.com" => "IBM Old Timer",
        "fivethirtyeight.com" => "ABC",
        "kvia.com" => "ABC",
        "projects.fivethirtyeight.com" => "ABC",
        "www.abc12.com" => "ABC",
        "www.abc15.com" => "ABC",
        "www.abcactionnews.com" => "ABC",
        "www.abc.net.au" => "ABC",
        "www.denver7.com" => "ABC",
        "www.news5cleveland.com" => "ABC",
        "www.abetterinternet.org" => "ABetterInternet",
        "aboutbsd.net" => "About BSD",
        "www.aboutchromebooks.com" => "AboutChromebooks",
        "aboutfeeds.com" => "AboutFeeds",
        "toroid.org" => "Abhijit Menon-Sen",
        "blog.codingconfessions.com" => "Abhinav Upadhyay",
        "codeconfessions.substack.com" => "Abhinav Upadhyay",
        "notes.abhinavsarkar.net" => "Abhinav Sarkar",
        "abilitymagazine.com" => "Ability Magzine",
        "blog.meain.io" => "Abin Simon",
        "arkoinad.com" => "Abhinav Gopalakrishnan",
        "abishekmuthian.com" => "Abishek Muthian",
        "news.abplive.com" => "ABP",
        "www.access-info.org" => "Access Info Europe",
        "accessipos.com" => "Access IPOs",
        "www.accessnow.org" => "AccessNow",
        "www.activesustainability.com" => "Acciona S A",
        "www.acjps.org" => "ACJPS",
        "www.aclumich.org" => "ACLU",
        "www.aclu.org" => "ACLU",
        "awards.acm.org" => "ACM",
        "cacm.acm.org" => "ACM",
        "dl.acm.org" => "ACM",
        "learning.acm.org" => "ACM",
        "queue.acm.org" => "ACM",
        "www.acm.org" => "ACM",
        "www.sigops.org" => "ACM",
        "acn.lol" => "ACN",
        "www.adbusters.org" => "Ad Busters Magazine",
        "www.adexchanger.com" => "AdExchanger",
        "www.adafruitdaily.com" => "Adafruit",
        "adafruit-playground.com" => "Adafruit",
        "blog.adafruit.com" => "Adafruit",
        "learn.adafruit.com" => "Adafruit",
        "www.adafruit.com" => "Adafruit",
        "adamfortuna.com" => "Adam Fortuna",
        "lubieniebieski.pl" => "Adam Nowak",
        "www.imperialviolet.org" => "Adam Langley",
        "admccartney.mur.at" => "Adam McCartney",
        "maxamillion.sh" => "Adam Miller",
        "notes.neatnik.net" => "Adam Newbold",
        "blog.adamretter.org.uk" => "Adam Retter",
        "www.adamsmith.org" => "Adam Smith",
        "archaeologist.dev" => "Adam Thalhammer",
        "adam.younglogic.com/" => "Adam Young",
        "www.adamsdesk.com" => "Adamsdesk",
        "www.addictivetips.com" => "AddictiveTips",
        "addisoncrump.info" => "Addison Crump",
        "addyosmani.com" => "Addy Osmani",
        "indaily.com.au" => "Adelaide",
        "adele.pages.casa" => "Adële",
        "uxpioneers.com" => "Adlin Inc",
        "blog.adnansiddiqi.me" => "Adnan Siddiqi",
        "ochagavia.nl" => "Adolfo Ochagavía",
        "www.linuxinsider.com" => "LinuxInsider",
        "www.laprensalatina.com" => "La Prensa Latina",
        "www.plenglish.com" => "La Prensa Latina",
        "www.youtube.com" => "YouTube",
        "www.thisiscolossal.com" => "Colossal",
        "www.collabora.com" => "Collabora",
        "www.sitepoint.com" => "SitePoint",
        "knro.blogspot.com" => "KStar Development",
        "kdenlive.org" => "Kdenlive",
        "dot.kde.org" => "KDE Official",
        "www.electropages.com" => "Electropages",
        "technative.io" => "TechNative",
        "blog.opensource.org" => "OSI Blog",
        "www.figuiere.net" => "Hubert Figuière",
        "www.southgatearc.org" => "Southgate",
        "adtmag.com" => "ADTmag",
        "www.rumble.run" => "Rumble Inc",
        "blog.rust-lang.org" => "Rust Blog",
        "insideclimatenews.org" => "Inside Climate News",
        "www.insideradio.com" => "Inside Radio",
        "insidetowers.com" => "Inside Towers",
        "www.markaicode.com" => "markaicode by Mark",
        "www.influxdata.com" => "InfluxData Inc",
        "www.telecoms.com" => "Informa PLC",
        "www.informationweek.com" => "InformationWeek",
        "fictiontalk.com" => "Fiction Talk",
        "www.fiercevideo.com" => "Fierce Video",
        "baronhk.wordpress.com" => "DaemonFC (Ryan Farmer)",
        "www.slashgear.com" => "SlashGear",
        "www.ubuntubuzz.com" => "Ade Malsasa Akbar",
        "www.tecmint.com" => "TecMint",
        "atechtown.com" => "Techtown",
        "www.techrepublic.com" => "Tech Republic",
        "www.kdab.com" => "KDAB",
        "almalinux.org" => "AlmaLinux Official",
        "lubuntu.me" => "Lubuntu",
        "www.tuxedocomputers.com" => "TUXEDO Computers GmbH",
        "tuxphones.com" => "TuxPhones",
        "linuxsecurity.com" => "LinuxSecurity",
        "www.bsdnow.tv" => "The BSD Now Podcast",
        "www.tlltsarchive.org" => "The TLLTS Podcast",
        "linuxopsys.com" => "LinuxOpSys",
        "www.scummvm.org" => "ScummVM",
        "linuxtechlab.com" => "LinuxTechLab",
        "www.pclinuxos.com" => "PCLOS Official",
        "www.the-diy-life.com" => "The DIY Life",
        "this-week-in-rust.org" => "Rust Weekly Updates",
        "www.cloudbooklet.com" => "Cloudbooklet",
        "www.debugpoint.com" => "DebugPoint",
        "linuxhostsupport.com" => "Linux Host Support",
        "www.linuxcloudvps.com" => "Linux Cloud VPS",
        "uapi-group.org" => "Linux Userspace API (UAPI) Group",
        "9to5toys.com" => "9 to 5 Toys",
        "www.suse.com" => "SUSE's Corporate Blog",
        "www.toolbox.com" => "Toolbox",
        "margin.re" => "Margin Research",
        "memex.marginalia.nu" => "Marginalia",
        "www.themarginalian.org" => "The Marginalian",
        "blog.ploeh.dk" => "Mark Seeman",
        "www.marketscreener.com" => "Market Screener",
        "htmhell.dev" => "Markup from Hell",
        "mhatta.substack.com" => "Masayuki Hatta",
        "mhatta.medium.com" => "Masayuki Hatta",
        "maskray.me" => "MaskRay",
        "www.sammobile.com" => "SamMobile",
        "fudzilla.com" => "FUDZilla",
        "informationsecuritybuzz.com" => "Information Security Buzz",
        "www.bankinfosecurity.com" => "Information Security Media Group, Corporation",
        "www.spiceworks.com" => "Ziff Davis",
        "www.zdnet.com" => "ZDNet",
        "www.faqforge.com" => "FAQForge",
        "arcadeblogger.com" => "The Arcade Blogger",
        "arcan-fe.com" => "Arcan",
        "www.newhamrecorder.co.uk" => "Archant Community Media Ltd",
        "arcolinux.com" => "Arco Linux",
        "dev.arie.bovenberg.net" => "Arie Bovenberg",
        "arktimes.com" => "Arkansas Times",
        "www.arkansasonline.com" => "Arkansas Democrat-Gazette Inc",
        "www.artnews.com" => "Art Media LLC",
        "www.theartnewspaper.com" => "The Art Newspaper",
        "artemis.sh" => "Artemiseverfree",
        "quuxplusone.github.io" => "Arthur O'Dwyer",
        "forum.artixlinux.org" => "Artix Linux Forum",
        "news.artnet.com" => "Artnet Worldwide Corporation",
        "about.ascension.org" => "Ascension",
        "labnotes.org" => "Assaf Arkin",
        "tecadmin.net" => "TecAdmin",
        "www.bustle.com" => "BDG",
        "www.inverse.com" => "BDG",
        "bytecellar.com" => "Byte Cellar",
        "bytexd.com" => "ByteXD",
        "www.linuxshelltips.com" => "Linux Shell Tips",
        "linuxbuz.com" => "LinuxBuz",
        "blog.ipfire.org" => "IPFire Official Blog",
        "communityblog.fedoraproject.org" => "Fedora Project",
        "fedoraproject.org" => "Fedora Project",
        "opensource.com" => "OpenSource.com",
        "developers.redhat.com" => "Red Hat",
        "blog.drogue.io" => "Red Hat",
        "www.gadgets360.com" => "Red Pixels Ventures Ltd",
        "rednafi.com" => "Redowan Delowar",
        "etbe.coker.com.au" => "Russell Coker",
        "www.sevarg.net" => "Russell Graves",
        "blogs.fsfe.org" => "FSFE",
        "fsfe.org" => "FSFE",
        "www.fosslife.org" => "FOSSLife",
        "hub.fosstodon.org" => "The Fosstodon Hub",
        "openssf.org" => "OpenSSF (Linux Foundation)",
        "openjsf.org" => "OpenJS Foundation (Linux Foundation)",
        "events.linuxfoundation.org" => "Linux Foundation",
        "servo.org" => "Servo (Linux Foundation)",
        "www.linux.com" => "Linux Foundation",
        "www.r-consortium.org" => "Linux Foundation",
        "www.linuxfoundation.org" => "Linux Foundation's Site/Blog",
        "www.linuxfoundation.org" => "Linux Foundation's Site/Blog",
        "linuxfoundation.org" => "Linux Foundation's Site/Blog",
        "www.cncf.io" => "CNCF (Linux Foundation)",
        "www.cf.org" => "CF.org",
        "www.bleepingcomputer.com" => "Bleeping Computer",
        "aaka.sh" => "Aakash Patel",
        "adf-magazine.com" => "ADF",
        "www.adl.org" => "ADL",
        "www.adminbyaccident.com" => "AdminByAccident",
        "www.adn.com" => "ADN",
        "euroquis.nl" => "Adriaan de Groot",
        "alic.dev" => "Adrian Alic",
        "adrienplazas.com" => "Adrian Plazas",
        "adriansieber.com" => "Adrian Sieber",
        "adrianroselli.com" => "Adriaan Roselli",
        "blog.bithole.dev" => "Adriaan Zhang",
        "ariadnavigo.xyz" => "Adriadna Vigo",
        "adriano.fyi" => "Adriano Caloiaro",
        "aduros.com" => "Aduros",
        "www.lonestarlive.com" => "Advance Local Media LLC",
        "advanced-television.com" => "AdvancedTelevision",
        "adventofcode.com" => "AdventOfCode",
        "www.wbiw.com" => "AdVenture Media",
        "www.advrider.com" => "Adventure Rider",
        "martypc.blogspot.com" => "Adventures in PC Emulation",
        "www.advicegoddess.com" => "Advice Goddess",
        "news.adobe.com" => "Adobe Inc",
        "www.adweek.com" => "AdWeek",
        "www.aei.org" => "AEI",
        "www.economicliberties.us" => "AELP",
        "www.windturbinestar.com" => "Aeolos Wind Energy Ltd",
        "aeon.co" => "Aeon Media Group Ltd",
        "areomagazine.com" => "Aero Magazine",
        "zone.dog" => "Aeva",
        "unitedafa.org" => "AFA",
        "afjc.media" => "Afghanistan Journalists Center",
        "factcheck.afp.com" => "AFP",
        "www.afp.com" => "AFP",
        "afkgaming.com" => "AFK Gaming",
        "www.afnic.fr" => "French Network Information Centre (Afnic)",
        "www.afr.com" => "AFR",
        "africacenter.org" => "Africa Center for Strategic Studies",
        "africacheck.org" => "Africa Check",
        "africahousingnews.com" => "Africa Housing News",
        "www.africanews.com" => "Africa News",
        "aftermath.site" => "Aftermath Site LLC",
        "lists.ag-projects.com" => "AG Projects",
        "agupubs.onlinelibrary.wiley.com" => "AGU",
        "www.agweb.com" => "Ag Web",
        "newsroom.heart.org" => "AHA",
        "www.theahafoundation.org" => "AHA",
        "healthjournalism.org" => "AHCJ",
        "alfy.blog" => "Ahmad Alfy",
        "ishadeed.com" => "Ahmad Shadeed",
        "english.ahram.org.eg" => "Ahram Online",
        "ahvalnews.com" => "Ahval",
        "www.aier.org" => "AIER",
        "analyticsindiamag.com" => "AIM",
        "aina.org" => "AINA",
        "www.aina.org" => "AINA",
        "artificialintelligence-news.com" => "AI News",
        "aigarius.com" => "Aigars Mahinovs",
        "www.airforcetimes.com" => "Air Force Times",
        "airqualitynews.com" => "Air Quality News",
        "blog.airsequel.com" => "Airsequel",
        "www.aithority.com" => "AIthority",
        "www.aitrends.com" => "AI Trends",
        "aj.bourg.family" => "AJ Bourg",
        "www.andrewjvpowell.com" => "AJVP",
        "www.akamai.com" => "Akamai",
        "akselmo.dev" => "Akseli Lahtinen",
        "www.akselmo.dev" => "Akseli Lahtinen",
        "oppi.li" => "Akshay",
        "peppe.rs" => "Akshay",
        "www.al.com" => "Alabama",
        "alabamareflector.com" => "Alabama Reflector",
        "www.homeautomationguy.io" => "Alan Byrne",
        "www.ajournalofmusicalthings.com" => "Alan Cross",
        "blog.ayjay.org" => "Alan Jacobs",
        "popey.com" => "Alan Pope",
        "www.turing.ac.uk" => "The Alan Turing Institute",
        "alaskabeacon.com" => "Alaska Beacon",
        "www.alaraby.co.uk" => "Al Araby",
        "www.albawaba.com" => "Al Bawaba",
        "threkk.medium.com" => "Alberto de Murga",
        "www.abqjournal.com" => "Albuquerque Journal",
        "alecmuffett.com" => "Alec Muffet",
        "aplus.rs" => "Aleksandar Vacić",
        "www.aleksandra.codes" => "Aleksandra Sikora",
        "www.alternet.org" => "AlerNet",
        "alediaferia.com" => "Alessandro Diaferia",
        "apogliaghi.com" => "Alessandro Pogliaghi",
        "aleteia.org" => "Aleteia",
        "www.flu0r1ne.net" => "Alex",
        "mango.pdf.zone" => "Alex",
        "alexcabal.com" => "Alex Cabal",
        "alexwlchan.net" => "Alex Chan",
        "blog.alexewerlof.com" => "Alex Ewerlöf",
        "alexgarcia.xyz" => "Alex Garcia",
        "alexgaynor.net" => "Alex Gaynor",
        "blog.alexgilleran.com" => "Alex Gilleran",
        "blog.infected.systems" => "Alex Haydock",
        "unplannedobsolescence.com" => "Alex Petros",
        "infrequently.org" => "Alex Russell",
        "smallhacks.wordpress.com" => "Alex Samorukov",
        "alexsirac.com" => "Alex Sirac",
        "alextheward.com" => "Alex Ward",
        "bluhm.genua.de" => "Alexander Bluhm",
        "blog.aschoch.ch" => "Alexander Schoch",
        "solovyov.net" => "Alexander Solovyov",
        "alexandrawolfe.ca" => "Alexandra Wolfe",
        "alexink.micro.blog" => "Alexandra Wolfe",
        "xojoc.pw" => "Alexandru Cojocaru",
        "alexn.org" => "Alexandru Nedelcu",
        "scvalex.net" => "Alexandru Scvorțov",
        "alexba.in" => "Alex Bain",
        "alex.dzyoba.com" => "Alex Dzyoba",
        "blog.alexellis.io" => "Alex Ellis",
        "blog.alexgleason.me" => "Alex Gleason",
        "alex.kleydints.com" => "Alex Kleydints",
        "alexschroeder.ch" => "Alex Schroeder",
        "moreati.org.uk" => "Alex Willmer",
        "www.algemeiner.com" => "Algemeiner",
        "algorithmwatch.org" => "AlgorithmWatch",
        "blog.alicegoldfuss.com" => "Alice Goldfuss",
        "hyti.org" => "Ali Reza Hayati",
        "alirezahayati.com" => "Ali Reza Hayati",
        "www.aljazeera.com" => "Al Jazeera",
        "alinpanaitiu.com" => "Alin Panaitiu",
        "allafrica.com" => "All Africa",
        "www.gbnews.uk" => "All Perspectives Ltd",
        "all-things-linux.blogspot.com" => "All Things Linux",
        "www.allthingssecured.com" => "All Things Secured",
        "www.labouseur.com" => "Alan G Labouseur",
        "www.notus.org" => "Allbritton Journalism Institute",
        "www.allendowney.com" => "Allen Downey",
        "allenpike.com" => "Allen Pike",
        "www.law.com" => "ALM",
        "www.al-monitor.com" => "Al Monitor",
        "alpinelinux.org" => "Alpine Linux",
        "wiki.alpinelinux.org" => "Alpine Linux",
        "www.alpinelinux.org" => "Alpine Linux",
        "xenodium.com" => "Álvaro Ramírez",
        "www.thetelegraph.com" => "Alton Telegraph",
        "alvaromontoro.com" => "Alvaro Montoro",
        "rosenzweig.io" => "Alyssa Rosenzweig",
        "amanhimself.dev" => "Aman Mittal",
        "ambersettle.wordpress.com" => "Amber Settle",
        "aws.amazon.com" => "Amazon Inc",
        "community.aws" => "Amazon Inc",
        "www.amazon.science" => "Amazon Inc",
        "www.aol.com" => "America Online",
        "www.americamagazine.org" => "America: The Jesuit Review",
        "www.neurology.org" => "American Academy of Neurology",
        "www.psychguides.com" => "American Addiction Centers Inc",
        "americanaffairsjournal.org" => "American Affairs Journal",
        "cen.acs.org" => "American Chemical Society",
        "americandialect.org" => "American Dialect Society",
        "www.palladiummag.com" => "American Governance Foundation Inc",
        "www.aha.org" => "American Hospital Association",
        "acrl.ala.org" => "American Library Association",
        "libguides.ala.org" => "American Library Association",
        "www.ala.org" => "American Library Association",
        "americanmilitarynews.com" => "American Military News",
        "americanoversight.org" => "American Oversight",
        "www.americanoversight.org" => "American Oversight",
        "www.apa.org" => "American Psychological Association",
        "www.americanthinker.com" => "American Thinker",
        "www.amitgawande.com" => "Amit Gawande",
        "www.amitgawande.com" => "Amit Gawande",
        "www.redblobgames.com" => "Amit Patel",
        "amiunique.org" => "AmIUnique",
        "www.almasdarnews.com" => "AMN",
        "www.amnestyusa.org" => "Amnesty International",
        "amnesty.hosting.augure.com" => "Amnesty International",
        "securitylab.amnesty.org" => "Amnesty International",
        "www.amnesty.org" => "Amnesty International",
        "amnesty.ca" => "Amnesty International",
        "www.amnesty.org.uk" => "Amnesty International",
        "fasterthanli.me" => "Amos Wenger",
        "media.amtrak.com" => "Amtrak",
        "www.electoralcommission.ie" => "An Coimisiún Toghcháin",
        "www.inquiryintoislam.com" => "An Inquiry Into Islam",
        "www.anaconda.com" => "Anaconda Inc",
        "analogoffice.net" => "Analog Office",
        "www.anandtech.com" => "AnandTech",
        "blog.anavi.technology" => "ANAVI",
        "blog.cyborch.com" => "Anders Borch",
        "anderstrier.dk" => "Anders Trier",
        "andrealmeid.com" => "André Almeida",
        "andreldm.com" => "André Miranda",
        "staltz.com" => "André Staltz",
        "gwtf.it" => "Andrea Contino",
        "contino.com" => "Andrea Contino",
        "www.andreinc.net" => "Andrei Ciobanu",
        "www.technollama.co.uk" => "Andrés Guadamuz",
        "andregarzia.com" => "Andre Alves Garzia",
        "andre.arko.net" => "André Arko",
        "abf.li" => "Andre Franca",
        "afhub.dev" => "Andre Franca",
        "floooh.github.io" => "Andre Weissflog",
        "andrewdomain.com" => "Andrew Domain",
        "andrewkelley.me" => "Andrew Kelley",
        "marble.onl" => "Andrew Marble",
        "hiandrewquinn.github.io" => "Andrew Quinn",
        "sheep.horse" => "Andrew Stephens",
        "andrewstiefel.com" => "Andrew Stiefel",
        "thermalcircle.de" => "Andrej Stender",
        "beza1e1.tuxen.de" => "Andreas Zwinkau",
        "blog.burntsushi.net" => "Andrew Gallant",
        "healeycodes.com" => "Andrew Healey",
        "ahelwer.ca" => "Andrew Helwer",
        "linuxjedi.co.uk" => "Andrew Hutchings",
        "huth.me" => "Andrew Huth",
        "aj.codes" => "Andrew Jorgensen",
        "matecha.net" => "Andrew Matecha",
        "blog.zarfhome.com" => "Andrew Plotkin",
        "androidkenya.com" => "Android",
        "androidnewstoday.com" => "Android",
        "www.androidauthority.com" => "Android Authority",
        "www.androidcentral.com" => "Android Central",
        "www.androidheadlines.com" => "Android Headlines",
        "source.android.com" => "Android Open Source Project",
        "www.androidpit.com" => "Android Pit",
        "www.androidpolice.com" => "Android Police",
        "www.anildash.com" => "Anil Dash",
        "waxy.org" => "Andy Baio",
        "piccalil.li" => "Andy Bell",
        "stuffandnonsense.co.uk" => "Andy Clarke",
        "andydote.co.uk" => "Andy Dote",
        "blog.koipond.org.uk" => "Andy Simpkins",
        "anfenglish.com" => "ANF News",
        "anfenglishmobile.com" => "ANF News",
        "triptico.com" => "Ángel Ortega",
        "angelusnews.com" => "Angelus",
        "www.aninews.in" => "ANI News",
        "en.annahar.com" => "An Nahar",
        "aadl.org" => "Ann Arbor District Library",
        "annarborobserver.com" => "Ann Arbor Observer",
        "anntelnaes.substack.com" => "Ann Telnaes",
        "annas-archive.org" => "Anna’s Archive",
        "annehelen.substack.com" => "Anne Helen Petersen",
        "weblog.anniegreens.lol" => "Anne Sturdivant",
        "anniemueller.com" => "Annie Mueller",
        "www.ansa.it" => "ANSA",
        "acco.io" => "Anthony Accomazzo",
        "tonybox.net" => "Anthony Biondo",
        "anthonyhobday.com" => "Anthony Hobday",
        "anthony.som.codes" => "Anthony Som",
        "a4kids.org" => "Anthropology for Kids",
        "cohost.org" => "Anti Software Software Club LLC",
        "antimaximalist.com" => "Antimaximalist",
        "antirez.com" => "Antirez",
        "antipolygraph.org" => "Anti Polygraph",
        "antixlinux.com" => "antiX Linux",
        "www.antipope.org" => "Antipope",
        "news.antiwar.com" => "AntiWar",
        "original.antiwar.com" => "AntiWar",
        "www.antiwar.com" => "AntiWar",
        "ane.iki.fi" => "Antoine Kalmbach",
        "mrsuh.com" => "Anton Sukhachev",
        "www.oftenpaper.net" => "Antonio Marquez Raygoza",
        "martinovic.blog" => "Antonio Martinović",
        "antonio.is" => "Antonio Rodrigues",
        "a3nm.net" => "Antoine Amarilli",
        "blog.sergeyev.info" => "Anton Sergeyev",
        "antonz.org" => "Anton Zhiyanov",
        "antranigv.am" => "Antranig Vartanian",
        "clubmate.fi" => "Antti Hiljá",
        "www.anxiousgeneration.com" => "The Anxious Generation",
        "blog.pecar.me" => "Anže Pečar",
        "www.aolium.com" => "Aolium",
        "programming-journal.org" => "AOSA",
        "blogs.apache.org" => "Apache Blog",
        "logging.apache.org" => "Apache Foundation",
        "apenwarr.ca" => "Apenwarr",
        "aphelis.net" => "Aphelis",
        "blog.apnic.net" => "APNIC",
        "www.apnic.net" => "APNIC",
        "www.apollo-magazine.com" => "Apollo Magazinex",
        "defaults.rknight.me" => "App Defaults",
        "developer.apple.com" => "Apple Inc",
        "discussions.apple.com" => "Apple Inc",
        "www.apple.com" => "Apple Inc",
        "appleinsider.com" => "AppleInsider",
        "forums.appleinsider.com" => "AppleInsider",
        "appletrack.com" => "AppleTrack",
        "appomni.com" => "AppOmni",
        "www.approachwithalacrity.com" => "Approach with Alacrity",
        "blog.appsignal.com" => "AppSignal BV",
        "www.april.org" => "April",
        "grayduck.mn" => "April King",
        "thearabdailynews.com" => "Arab Daily News",
        "arablit.org" => "Arab Lit Quarterly",
        "www.arabnews.com" => "Arab News",
        "thearabweekly.com" => "Arab Weekly",
        "ar.al" => "Aral Balkan",
        "www.arcweb.com" => "ARC",
        "www.arcanoae.com" => "Arca Noae",
        "www.architecturaldigest.com" => "Architectural Digest",
        "arcticportal.org" => "Arctic Portal",
        "archipylago.dev" => "Archipylago",
        "archive.is" => "Archive Today",
        "blog.arctype.com" => "Arctype",
        "blog.arduino.cc" => "Arduino",
        "content.arduino.cc" => "Arduino",
        "discover.hubpages.com" => "Arena Group",
        "meidasnews.com" => "Arena Group",
        "housingsklave.at" => "Ari",
        "ariadne.space" => "Ariadne Conill",
        "www.americanbanker.com" => "Arizent",
        "arizonadailyindependent.com" => "Arizona Independent LLC",
        "arjenkamphuis.eu" => "Arjen Kamphuis",
        "arjenwiersma.nl" => "Arjen Wiersma",
        "www.arm.com" => "Arm Limited",
        "armenpress.am" => "Armenpress",
        "armenianweekly.com" => "Armenian Weekly",
        "lucumr.pocoo.org" => "Armin Ronacher",
        "www.arnnet.com.au" => "ARN",
        "www.draketo.de" => "Arne Babenhauserheide",
        "arne.me" => "Arne Bahlo",
        "raku-musings.com" => "Arne Sommer",
        "arnon.dk" => "Arnon Shimoni",
        "www.aroged.com" => "Aroged",
        "www.arrl.org" => "ARRL",
        "artdaily.com" => "Art",
        "nationaltoday.com" => "Art",
        "www.artfixdaily.com" => "Art Fix Daily",
        "theartofmachinery.com" => "Art Of Machinery",
        "rushter.com" => "Artem Golubin",
        "www.classicalite.com" => "Arts",
        "www.artshub.com.au" => "ArtsHub",
        "www.artsjournal.com" => "ArtsJournal",
        "ral-arturo.org" => "Arturo Borrero",
        "www.artshub.co.uk" => "ArtsHub and Screenhub",
        "arunraghavan.net" => "Arun Raghavan",
        "arxiv.org" => "arXiv",
        "www.asa.org.uk" => "Advertising Standards Authority Ltd",
        "ashfurrow.com" => "Ash Furrow",
        "ashishb.net" => "Ashish Bhatia",
        "amissing.link" => "Ashlen",
        "www.asiafinancial.com" => "Asia Financial",
        "www.asianews.it" => "Asia News",
        "www.asiaone.com" => "Asia One",
        "asiapacificreport.nz" => "Asia Pacific Report",
        "asiatimes.com" => "Asia Times",
        "www.aspeninstitute.org" => "Aspen Institute",
        "inews.co.uk" => "Associated News Ltd",
        "apnews.com" => "Associated Press",
        "www.apnews.com" => "Associated Press",
        "prologyear.logicprogramming.org" => "Association for Logic Programming",
        "www.arl.org" => "Association of Research Libraries",
        "aster.cloud" => "AsterCloud",
        "www.aanda.org" => "Astronomy  & Astrophysics",
        "blog.astropad.com" => "Astropad",
        "atlantadailyworld.com" => "Atlanta Daily World",
        "atlanticbusinesssystems.com" => "Atlantic Business Systems",
        "www.atlanticcouncil.org" => "Atlantic Council",
        "www.atlasobscura.com" => "Atlas Obscura",
        "atlasvpn.com" => "Atlas VPN",
        "community.atlassian.com" => "Atlassian",
        "www.atlassian.com" => "Atlassian",
        "atthis.link" => "At This Link",
        "www.lamborghini.com" => "Audi Group",
        "www.audubon.org" => "Audubon Society",
        "augmentedcode.io" => "Augmented Code",
        "agateau.com" => "Aurélien Gâteau",
        "blog.aurel32.net" => "Aurélien Jarno",
        "www.austinchronicle.com" => "Austin Chronicle",
        "austingil.com" => "Austin Gil",
        "austinkleon.com" => "Austin Kleon",
        "austinkleon.substack.com" => "Austin Kleon",
        "austinhenley.com" => "Austin Z Henley",
        "austinwhite.org" => "Austin White",
        "www.greenleft.org.au" => "Australian Green Left",
        "ministers.ag.gov.au" => "Australia",
        "www.aihw.gov.au" => "Australia",
        "www.pm.gov.au" => "Australia",
        "thenewdaily.com.au" => "Australia",
        "www.aph.gov.au" => "Australia",
        "www.dailytelegraph.com.au" => "Australia",
        "www.brisbanetimes.com.au" => "Australia",
        "www.cyber.gov.au" => "Australia",
        "www.echo.net.au" => "Australia",
        "www.liverpoolchampion.com.au" => "Australia",
        "www.pc.gov.au" => "Australia",
        "www.perthnow.com.au" => "Australia",
        "www.themonthly.com.au" => "Australia",
        "www.autoevolution.com" => "Auto Evolution",
        "www.theautopian.com" => "The Autopian",
        "www.autodidacts.io" => "The Autodidacts",
        "www.automology.com" => "Automology",
        "www.automotiveworld.com" => "Automotive World Ltd",
        "blog.avast.com" => "Avast",
        "decoded.avast.io" => "Avast",
        "www.aviationanalysis.net" => "Aviation Analysis",
        "www.aviationtoday.com" => "Aviation Today",
        "www.aviation24.be" => "Aviation24.be",
        "www.avitrader.com" => "Avi Trader",
        "avi.im" => "Avinash Sajjanshetty",
        "awk.dev" => "AWK",
        "a.wholelottanothing.org" => "A Whole Lotta Nothing",
        "axcient.com" => "Axcient",
        "noone.org" => "Axel Beckert",
        "www.axios.com" => "Axios",
        "www.agwa.name" => "Ayer",
        "aylo6061.com" => "Aylo",
        "johncarlosbaez.wordpress.com" => "Azimuth Project",
        "badluckhotrocks.com" => "Bad Luck, Hot Rocks",
        "www.ranum.com" => "Badger Forge",
        "backlightblog.com" => "Backlight",
        "badgerherald.com" => "The Badger Herald",
        "gebna.gg" => "BahaaZidan",
        "www.baldengineer.com" => "Bald Engineer",
        "www.baldurbjarnason.com" => "Baldur Bjarnason",
        "ballotpedia.org" => "Ballotpedia",
        "thebalochistanpost.net" => "Balochistan Post",
        "balochistantimes.com" => "Balochistan Times",
        "blog.balthazar-rouberol.com" => "Balthazar Rouberol",
        "www.baltictimes.com" => "The Baltic Times",
        "www.thebaltimorebanner.com" => "The Baltimore Banner",
        "banfossilfuelads.org" => "Ban Fossil Fuel Ads",
        "daily.bandcamp.com" => "Bandcamp",
        "diejimcrow.bandcamp.com" => "Bandcamp",
        "keleketla.bandcamp.com" => "Bandcamp",
        "bdnews24.com" => "Bangladesh",
        "bangordailynews.com" => "Bangor Daily News",
        "www.boz.zm" => "Bank of Zambia",
        "www.bankrate.com" => "Bankrate LLC",
        "www.banklesstimes.com" => "Bankless Times",
        "www.bangkokpost.com" => "Bankok Post",
        "www.baptistpress.com" => "Baptist Press",
        "bariweiss.substack.com" => "Bari Weiss",
        "www.barnabasaid.org" => "Barnabas Aid",
        "barnabasfund.org" => "Barnabas Fund",
        "www.barnabasfund.org" => "Barnabas Fund",
        "news.barnabasfund.org" => "Barnabas Fund",
        "www.barrons.com" => "Barrons",
        "bkhome.org" => "Barry Kauler",
        "pika.bjhess.com" => "Barry Hess",
        "bjhess.pika.page" => "Barry Hess",
        "bjhess.bearblog.dev" => "Barry Hess",
        "bjhess.com" => "Barry Hess",
        "www.brightball.com" => "Barry W Jones",
        "barrysampson.net" => "Barry Sampson",
        "bartwronski.com" => "Bart Wronski",
        "ciechanow.ski" => "Bartosz Ciechanowski",
        "bartoszmilewski.com" => "Bartosz Milewski",
        "bastianallgeier.com" => "Bastian Allgeier",
        "planetradio.co.uk" => "Bauer Media Group",
        "www.bbc.com" => "BBC",
        "www.bbc.co.uk" => "BBC",
        "news.bbc.co.uk" => "BBC",
        "www.historyextra.com" => "BBC",
        "www.bcs.org" => "BCS",
        "beagleboard.org" => "BeagleBoard",
        "www.comicsbeat.com" => "The Beat",
        "www.thebeaverton.com" => "The Beaverton",
        "www.beckershospitalreview.com" => "Becker's Hospital Review",
        "becomeawritertoday.com" => "Become A Writer Today",
        "beebom.com" => "Beebom",
        "beepb00p.xyz" => "BeepB00p",
        "beej.us" => "Beej",
        "beets.readthedocs.io" => "Beets",
        "behavioralscientist.org" => "Behavioral Scientist",
        "www.belfasttelegraph.co.uk" => "Belfast Telegraph",
        "www.bellingcat.com" => "Bellingcat",
        "www.belowthefold.news" => "Below The Fold",
        "benjamincongdon.me" => "Ben Congdon",
        "bencrump.com" => "Ben Crump Law",
        "3fx.ch" => "Ben Fiedler",
        "benfrain.com" => "Ben Frain",
        "www.benfrederickson.com" => "Ben Frederickson",
        "benedicthenshaw.com" => "Ben Henshaw",
        "benhoyt.com" => "Ben Hoyt",
        "werd.io" => "Ben Werdmuller",
        "bentsai.org" => "Ben Tsai",
        "bvisness.me" => "Ben Visness",
        "www.hardill.me.uk" => "Benjamin John Hardill",
        "zoobab.wikidot.com" => "Benjamin Henrion",
        "www.benjaminlipp.de" => "Benjamin Lipp",
        "mako.cc" => "Benjamin Mako Hill",
        "mental-reverb.com" => "Benjamin Richner",
        "www.sandofsky.com" => "Benjamin Sandofsky",
        "benjaminwil.info" => "Benjamin Wil",
        "www.benji.dog" => "Benji Encalada Mora",
        "blog.benjojo.co.uk" => "Ben Jojo",
        "www.bentasker.co.uk" => "Ben Tasker",
        "bentsai.pika.page" => "Ben Tsai",
        "www.ben-evans.com" => "Benedict Evans",
        "www.timesnownews.com" => "Bennett, Coleman & Company Ltd",
        "bentsukun.ch" => "Benny Siegert",
        "www.benton.org" => "Benton Institute",
        "works.bepress.com" => "Bepress",
        "berk.es" => "Bèr Kessels",
        "www.noemamag.com" => "Berggruen Insitute",
        "newscenter.lbl.gov" => "Berkeley Lab",
        "www.berklix.com" => "Berklix",
        "berthub.eu" => "Bert Hubert",
        "bert.org" => "Bertrand Fan",
        "bertrandmeyer.com" => "Bertrand Meyer",
        "bestgamingpro.com" => "Best Gaming Pro",
        "www.bestgizindia.com" => "Best Of Giz India",
        "betanews.com" => "Beta News",
        "better.fyi" => "Better",
        "betterstack.com" => "Better Stack Inc",
        "betterbird.eu" => "Betterbird",
        "betterprogramming.pub" => "Better Programming",
        "bgr.com" => "BGR",
        "bhamnow.com" => "Bham Now",
        "bianet.org" => "BIA Net",
        "m.bianet.org" => "BIA Net",
        "static.bianet.org" => "BIA Net",
        "www.bigbinary.com" => "Big Binary LLC",
        "bigbluebutton.org" => "Big Blue Button",
        "www.mynaparrot.com" => "Big Blue Button",
        "www.bigcommerce.com" => "BigCommerce Pty Ltd",
        "www.bigmessowires.com" => "Big Mess O Wires",
        "www.bikeboom.info" => "Bike Boom",
        "bikepacking.com" => "Bikepacking",
        "bikeportland.org" => "BikePortland",
        "www.bikobatanari.art" => "Bikobatanari",
        "billmckibben.substack.com" => "Bill McKibben",
        "notes.billmill.org" => "Bill Mill",
        "billmoyers.com" => "Bill Moyers",
        "billwadge.com" => "Bill Wadge",
        "billwillingham.substack.com" => "Bill Willingham",
        "www.sunherald.com" => "Biloxi Sun Herald",
        "blog.binarynights.com" => "BinaryNights LLC",
        "bmcmedethics.biomedcentral.com" => "Bio Med Central",
        "globalizationandhealth.biomedcentral.com" => "Bio Med Central",
        "bioone.org" => "BioOne Complete",
        "www.biometricupdate.com" => "Biometric Update",
        "www.biorxiv.org" => "BioRxiv",
        "birdhouse.org" => "Birdhouse Arts Collective",
        "birmingham.cmis.uk.com" => "Birmingham City Council",
        "www.birminghammail.co.uk" => "Birmingham Live",
        "bisco.org" => "Bisco",
        "bishopfox.com" => "Bishop Fox",
        "labs.bishopfox.com" => "Bishop Fox Labs",
        "bismarcktribune.com" => "Bismarck Tribune",
        "darkvisitors.com" => "Bit Flip LLC",
        "www.bitchmedia.org" => "Bitch Media",
        "www.bitdefender.com" => "Bitdefender",
        "www.bitecode.dev" => "Bite code",
        "news.bitcoin.com" => "Bitcoin",
        "bitcoinmagazine.com" => "Bitcoin Magazine",
        "businessinsights.bitdefender.com" => "Bitdefender",
        "www.bitestring.com" => "Bitestring",
        "bitmovin.com" => "Bitmovin Inc",
        "www.bitsondisk.com" => "Bits On Disk",
        "bitterwinter.org" => "Bitter Winter",
        "bjoern.brembs.net" => "Bjoern Brembs",
        "borud.no" => "Björn Borud",
        "www.ognibeni.de" => "Björn Ognibeni",
        "warmedal.se" => "Björn Wärmedal",
        "goblackcat.com" => "Black Cat",
        "www.blackenterprise.com" => "Black Enterprise",
        "www.blackhat.com" => "Black Hat",
        "blogs.blackberry.com" => "BlackBerry",
        "windsornewstoday.ca" => "Blackburn Media",
        "blackwinghq.com" => "Blackwing Intelligence",
        "blakerain.com" => "Blake Rain",
        "blakewatson.com" => "Blake Watson",
        "code.blender.org" => "Blender",
        "www.blender.org" => "Blender",
        "blindsa.org.za" => "Blind SA",
        "the-blindspot.com" => "The Blind Spot",
        "www.blinkenlights.com" => "Blinkenlights",
        "blinry.org" => "Blinry",
        "blog.blissos.org" => "BlissOS",
        "blocksandfiles.com" => "Situation Publishing",
        "blogsystem5.substack.com" => "Blog System/5",
        "blogsofwar.com" => "Blogs of War",
        "bloodyelbow.com" => "Bloody Elbow",
        "www.bloodyelbow.com" => "Bloody Elbow",
        "news.bloomberglaw.com" => "Bloomberg",
        "news.bloombergtax.com" => "Bloomberg",
        "www.bloomberg.com" => "Bloomberg",
        "blog.bloonface.com" => "Bloonface",
        "www.thesouthafrican.com" => "Blue Sky Publications",
        "cybermagazine.com" => "BMG",
        "manufacturingdigital.com" => "BMG",
        "www.bmj.com" => "BMJ",
        "www.bmjv.de" => "BMVJ",
        "www.bnaibrith.ca" => "Bnai Brith",
        "www.intellinews.com" => "BNE IntelliNews",
        "www.bnnbloomberg.ca" => "BNN",
        "cromwell-intl.com" => "Bob Cromwell",
        "www.bawbgale.com" => "Bob Gale",
        "bobmonsour.com" => "Bob Monsour",
        "www.bobmonsour.com" => "Bob Monsour",
        "journal.stuffwithstuff.com" => "Bob Nystrom",
        "www.bodhilinux.com" => "Bodhi Linux",
        "bitboxer.de" => "Bodo Tasche",
        "www.bogieland.com" => "BogieLand",
        "boilingsteam.com" => "Boiling Steam",
        "boingboing.net" => "BoingBoing",
        "bokwoon.com" => "Bokwoon",
        "www.bollyinside.com" => "Bollyinside",
        "bootcamp.uxdesign.cc" => "UX Collective",
        "bookriot.com" => "Book Riot",
        "bootlin.com" => "Bootlin",
        "www.boredpanda.com" => "Bored Panda",
        "borgenproject.org" => "Borgen Project",
        "notso.boringsql.com" => "BoringSQL",
        "www.boristhebrave.com" => "Boris The Brave",
        "borncity.com" => "Born City",
        "borneobulletin.com.bn" => "Borneo",
        "www.boston.com" => "Boston Globe",
        "www.bostonglobe.com" => "Boston Globe",
        "www.bostonherald.com" => "Boston Herald",
        "www.bostonreview.net" => "Boston Review",
        "www.bu.edu" => "Boston University",
        "www.csk.gov.in" => "Botnet Cleaning and Malware Analysis Centre, India",
        "boucek.me" => "Marian Bouček",
        "bowero.nl" => "Bowero",
        "www.bgca.org" => "Boys & Girls Clubs of America",
        "batsov.com" => "Bozhidar Batsov",
        "metaredux.com" => "Bozhidar Batsov",
        "techblog.bozho.net" => "Bozhidar Bozhanov",
        "www.bizpacreview.com" => "BPR",
        "bra.se" => "BRÅ",
        "bradfitz.com" => "Brad Fitzpatrick",
        "bt.ht" => "Brad Taunt",
        "btxx.org" => "Brad Taunt",
        "www.abortretry.fail" => "Bradford Morgan White",
        "tdarb.org" => "Bradley Taunt",
        "www.brainerddispatch.com" => "Brainerd Dispatch",
        "thelittleengineerthatcould.blogspot.com" => "Bram Stolk",
        "brandons-journal.com" => "Brandon",
        "brandonwrites.xyz" => "Brandon",
        "wand3r.net" => "Brandon",
        "quakkels.com" => "Brandon Quakkelaar",
        "www.brandonpugh.com" => "Brandon Pugh",
        "brandur.org" => "Branur Leach",
        "www.brasilwire.com" => "Brasil Wire",
        "brave.com" => "Brave Browser",
        "riotimesonline.com" => "Brazil",
        "breachmedia.ca" => "Breach Media",
        "breakingdefense.com" => "Breaking Defense",
        "abovethelaw.com" => "Breaking Media Inc",
        "breckyunits.com" => "Breck Yunits",
        "brendangregg.com" => "Brendan Gregg",
        "www.brendangregg.com" => "Brendan Gregg",
        "inessential.com" => "Brent Simmons",
        "briancallahan.net" => "Brian Callahan",
        "briandouglas.ie" => "Brian Douglas",
        "bnet.substack.com" => "Brian Feldman",
        "bytes.zone" => "Brian Hicks",
        "brianlovin.com" => "Brian Lovin",
        "www.bloodinthemachine.com" => "Brian Merchant",
        "remotesynthesis.com" => "Brian Rinaldi",
        "www.sholis.com" => "Brian Sholis",
        "briansmith.org" => "Brian Smith",
        "brica.de" => "BRICA",
        "www.michigan.gov" => "The State of Michigan",
        "www.bridgemi.com" => "Bridge Michigan",
        "www.lansingcitypulse.com" => "Michigan",
        "mijournalismhalloffame.org" => "The Michigan Journalism Hall of Fame",
        "www.michiganreview.com" => "The Michigan Review",
        "www.michiganpublic.org" => "Michigan Radio",
        "www.michiganradio.org" => "Michigan Radio",
        "www.wkar.org" => "Michigan State University",
        "www.michbar.org" => "State Bar of Michigan",
        "stateline.org" => "States Newsroom",
        "bright-green.org" => "Bright Green",
        "brightlinewatch.org" => "Bright LineWatch",
        "brightly.eco" => "Brightly",
        "www.brightonandhovenews.org" => "Brighton And Hove",
        "brilliantmaps.com" => "Brilliant British Ltd",
        "brioche.dev" => "Brioche",
        "www.bristolpost.co.uk" => "Bristol UK",
        "www.bristol247.com" => "Bristol UK",
        "en.irinkwire.com" => "Brinkwire",
        "www.britishasianchristians.org" => "British Christians",
        "blogs.bl.uk" => "British Library",
        "www.bl.uk" => "British Library",
        "www.britishpakistanichristians.org" => "British Pakistani Christian Association",
        "learnenglish.britishcouncil.org" => "British Council",
        "broadbandbreakfast.com" => "Broadband Breakfast",
        "www.brookings.edu" => "Brookings Institution",
        "www.bklynlibrary.org" => "Brooklyn Public Library",
        "www.browndailyherald.com" => "Brown Daily Herald",
        "fingerprintjs.com" => "Browser Fingerprint JS",
        "onlinetexttools.com" => "Browserling Inc",
        "brr.fyi" => "Brr",
        "perens.com" => "Bruce Perens",
        "www.schneier.com" => "Bruce Schneier",
        "www.brodrigues.co" => "Bruno Rodrigues",
        "bryanapperson.com" => "Bryan Apperson",
        "bryanapperson.com" => "Bryan Apperson",
        "bcantrill.dtrace.org" => "Bryan Cantrill",
        "lunduke.locals.com" => "Bryan Lunduke",
        "lunduke.substack.com" => "Bryan Lunduke",
        "www.bryanshalloway.com" => "Bryan Shalloway",
        "brycevandegrift.xyz" => "Bryce Vandegrift",
        "www.brycewray.com" => "Bryce Wray",
        "lists.nycbug.org" => "NYC BUG",
        "www.nycbug.org" => "NYC BUG",
        "kristaps.bsd.lv" => "BSD",
        "www.asahi.com" => "The Asahi Shimbun Company",
        "2023.asiabsdcon.org" => "AsiaBSDCon",
        "2024.asiabsdcon.org" => "AsiaBSDCon",
        "2025.asiabsdcon.org" => "AsiaBSDCon",
        "bsdly.blogspot.com" => "BSDly",
        "blog.bsdcan.org" => "BSDCan",
        "lists.bsdcan.org" => "BSDCan",
        "www.bsdcan.org" => "BSDCan",
        "bsandro.tech" => "Bsandro",
        "www.bucksfreepress.co.uk" => "Bucks Free Press",
        "buffalonews.com" => "Buffalo News",
        "builtin.com" => "Built In",
        "thebulletin.org" => "Bulletin",
        "www.thebulwark.com" => "Bulwark Media",
        "www.bunniestudios.com" => "Bunnie Huang",
        "www.thebureauinvestigates.com" => "The Bureau of Investigative Journalism",
        "embeddeduse.com" => "Burkhard Stubert",
        "www.businessworld.in" => "BW Businessworld Media Pvt Ltd",
        "www.businessoffashion.com" => "The Business of Fashion",
        "www.businessghana.com" => "Business Ghana",
        "markets.businessinsider.com" => "Business Insider",
        "www.businessinsider.com" => "Business Insider",
        "www.businessinsider.com.au" => "Business Insider",
        "www.businessinsider.de" => "Business Insider",
        "www.businessinsider.fr" => "Business Insider",
        "www.businessinsider.in" => "Business Insider",
        "www.businessinsider.nl" => "Business Insider",
        "www.businessinsider.co.za" => "Business Insider",
        "www.insider.com" => "Business Insider",
        "www.businesslive.co.za" => "Business Live",
        "www.business-standard.com" => "Business Standard",
        "businesstech.co.za" => "BusinessTech, South Africa",
        "www.tbsnews.net" => "The Business Standard",
        "www.businesstoday.in" => "Business Today",
        "www.businesswire.com" => "Business Wire",
        "bwcio.businessworld.in" => "Business World",
        "businessworld.in" => "Business World",
        "www.bworldonline.com" => "Business World",
        "buttondown.email" => "Buttondown",
        "buttondown.com" => "Buttondown LLC",
        "www.huffpost.com" => "BuzzFeed Inc",
        "www.buzzfeednews.com" => "Buzz Feed",
        "blog.code.horse" => "Bytewave",
        "c3.handmade.network" => "C3",
        "www.c4isrnet.com" => "C4ISRNET",
        "www.c-span.org" => "C-SPAN",
        "cado-nfs.gforge.inria.fr" => "CADONFS",
        "linksiwouldgchatyou.substack.com" => "Caitlin Dewey",
        "caitlinjohnstone.com" => "Caitlin Johnstone",
        "www.cajnewsafrica.com" => "CAJ News",
        "www.cajnews.co.za" => "CAJ News",
        "calnewport.com" => "Cal Newport",
        "calebhearth.com" => "Caleb Hearth",
        "manual.calibre-ebook.com" => "Calibre",
        "www.ppic.org" => "Public Policy Institute of California",
        "www.pleasantonweekly.com" => "Pleasanton California",
        "missionlocal.org" => "San Francisco, California",
        "leginfo.legislature.ca.gov" => "California",
        "californianewstimes.com" => "California",
        "calmatters.org" => "California",
        "sd15.senate.ca.gov" => "California",
        "www.independent.com" => "California",
        "www.sacbee.com" => "California",
        "www.gov.ca.gov" => "California",
        "www.dir.ca.gov" => "California Department of Industrial Relations",
        "california18.com" => "California18",
        "www.calfac.org" => "California Faculty Association",
        "www.californialawreview.org" => "California Law Review",
        "sundial.csun.edu" => "California State University Northridge",
        "calpaterson.com" => "Cal Paterson",
        "calteches.library.caltech.edu" => "Caltech Magazine",
        "magazine.caltech.edu" => "Caltech Magazine",
        "dictionary.cambridge.org" => "Cambridge Dictionary",
        "www.camg.me" => "Cameron Gaertner",
        "schoonens.social" => "Camiel Schoonens",
        "can-newsletter.org" => "CAN",
        "campustechnology.com" => "1105 Media Inc",
        "securitytoday.com" => "1105 Media Inc",
        "news.gov.bc.ca" => "Canada",
        "bc.ctvnews.ca" => "Canada",
        "barrie.ctvnews.ca" => "Canada",
        "edmonton.ctvnews.ca" => "Canada",
        "winnipeg.ctvnews.ca" => "Canada",
        "canadianinquirer.net" => "Canada",
        "www.pm.gc.ca" => "Canada",
        "www.calgarylibrary.ca" => "Canada",
        "www.winnipegfreepress.com" => "Canada",
        "www.thespec.com" => "Canada",
        "www.ugdsb.ca" => "Canada",
        "www.canada.ca" => "Canada",
        "canadatoday.news" => "Canada Today",
        "www.yrp.ca" => "Canada",
        "canion.blog" => "Canion dot Blog",
        "canalys.com" => "Canalys",
        "www.canberratimes.com.au" => "Canberra Times",
        "canonical.com" => "Canonical",
        "blog.can.ac" => "Can Bölük",
        "www.canva.dev" => "Canva Engineering Blog",
        "canvatechblog.com" => "Canva Engineering Blog",
        "caolan.uk" => "Caolan",
        "capwatkins.com" => "Cap Watikins",
        "cap5.nl" => "Cap5 B V",
        "www.capegazette.com" => "Cape Gazette",
        "www.capetalk.co.za" => "Cape Talk",
        "capitalaspower.com" => "Capital As Power",
        "www.carandbike.com" => "Car And Bike",
        "www.smartcard-hsm.com" => "CardContact Systems GmbH",
        "www.edmunds.com" => "CarMax Inc",
        "git.carcosa.net" => "Carcosa Git",
        "www.carinsurance.org" => "Car Insurance",
        "carlbarenbrug.com" => "Carl Barenbrug",
        "carlchenet.com" => "Carl Chenet",
        "serc.carleton.edu" => "Carleton College",
        "carlosbecker.com" => "Carlos Becker",
        "cfenollosa.com" => "Carlos Fenollosa",
        "carlschwan.eu" => "Carl Schwan",
        "datagubbe.se" => "Carl Svensson",
        "www.datagubbe.se" => "Carl Svensson",
        "tashian.com" => "Carl Tashian",
        "www.carscoops.com" => "Car Scoops",
        "www.thedrum.com" => "Carnyx Group Ltd",
        "www.cartoonbrew.com" => "Cartoon Brew",
        "www.cartooningforpeace.org" => "Cartooning for Peace",
        "cartoonistsrights.org" => "Cartooonists Rights Network International",
        "www.caryinstitute.org" => "Cary Institute",
        "csscade.com" => "The Cascade",
        "www.caseyliss.com" => "Casey Liss",
        "www.platformer.news" => "Casey Newton",
        "cprimozic.net" => "Casey Primozic",
        "cassidoo.co" => "Cassidy Williams",
        "catfox.life" => "The Cat Fox Life",
        "www.catalyst.net.nz" => "Catalyst",
        "catalystcloud.nz" => "Catalyst Cloud",
        "blog.webpagetest.org" => "Catchpoint Systems",
        "catvalente.substack.com" => "Catherynne M Valente",
        "blog.cathoderaydude.com" => "Cathod Ray Dude",
        "catholicdaily.com" => "Catholic Daily",
        "catholicherald.co.uk" => "Catholic Herald",
        "www.catholicnewsagency.com" => "Catholic NewsAgency",
        "www.catholicregister.org" => "Catholic Register",
        "www.catholicworldreport.com" => "Catholic World Report",
        "humanprogress.org" => "The Cato Institute",
        "www.cato.org" => "The Cato Institute",
        "www.cbc.ca" => "CBC",
        "www1.cbn.com" => "CBN",
        "www.cbr.com" => "CBR",
        "www.cbronline.com" => "CBR",
        "boston.cbslocal.com" => "CBS",
        "detroit.cbslocal.com" => "CBS",
        "dfw.cbslocal.com" => "CBS",
        "losangeles.cbslocal.com" => "CBS",
        "miami.cbslocal.com" => "CBS",
        "minnesota.cbslocal.com" => "CBS",
        "newyork.cbslocal.com" => "CBS",
        "sacramento.cbslocal.com" => "CBS",
        "sanfrancisco.cbslocal.com" => "CBS",
        "www.8newsnow.com" => "CBS",
        "www.cbsnews.com" => "CBS",
        "www.cbssports.com" => "CBS",
        "www.wusa9.com" => "CBS",
        "events.ccc.de" => "CCC",
        "fahrplan.events.ccc.de" => "CCC",
        "media.ccc.de" => "CCC",
        "www.ccc.de" => "CCC",
        "www.cdc.gov" => "CDC",
        "www.cedricbonhomme.org" => "Cédric Bonhomme",
        "www.cell.com" => "Cell Press",
        "celso.io" => "Celso Martinho",
        "cendyne.dev" => "Cendyne Naga",
        "www.autosec.org" => "Center for Automotive Embedded Systems Security",
        "climateintegrity.org" => "Center for Climate Integrity",
        "counterhate.com" => "Center for Countering Digital Hate (CCDH)",
        "cdt.org" => "Center for Democracy & Technology",
        "cepa.org" => "Center for European Policy Analysis (CEPA)",
        "www.cima.ned.org" => "Center for International Media Assistance",
        "revealnews.org" => "The Center for Investigative Reporting",
        "www.medialit.org" => "The Center for Media Literacy",
        "www.cnas.org" => "Center for a New American Security",
        "democraticmedia.org" => "The Center for Digital Democracy",
        "blog.centos.org" => "CentOS",
        "www.centos.org" => "CentOS",
        "tibet.net" => "Central Tibetan Administration",
        "corporateeurope.org" => "CEO",
        "www.cepsa.com" => "Cepsa",
        "computinged.wordpress.com" => "CER",
        "indico.cern.ch" => "CERN",
        "ceur-ws.org" => "CEUR",
        "centerforinquiry.org" => "CFI",
        "womeninjournalism.org" => "CFWIJ",
        "america.cgtn.com" => "CGTN America",
        "mathr.co.uk" => "Claude Heiland-Allen",
        "claytonerrington.com" => "Clayton Errington",
        "txt.cohere.com" => "Cohere",
        "www.makeworld.space" => "Cole",
        "assembly.coe.int" => "Council of Europe",
        "www.cfr.org" => "Council on Foreign Relations",
        "www.whio.com" => "Cox Media Group",
        "www.wpxi.com" => "Cox Media Group",
        "chadaustin.me" => "Chad Austin",
        "openpath.quest" => "Chad Whitacre",
        "openpath.chadwhitacre.com" => "Chad Whitacre",
        "ny.chalkbeat.org" => "Chalkbeat",
        "www.change.org" => "Change.org PBC",
        "changelog.com" => "Changelog",
        "sg.channelasia.tech" => "Channel Asia",
        "www.channable.com" => "Channable",
        "podcast.chaoss.community" => "CHAOSS",
        "chapel-lang.org" => "The Chapel Parallel Programming Language",
        "fishbowl.pastiche.org" => "Charles Miller",
        "www.charlespetzold.com" => "Charles Petzold",
        "researchoutput.csu.edu.au" => "Charles Sturt University",
        "www.charlestonchronicle.net" => "Charleston Chronicle",
        "nullsweep.com" => "Charlie",
        "www.charlieharrington.com" => "Charlie Harrington",
        "chartscss.org" => "ChartCSS",
        "baynews9.com" => "Charter Communications",
        "spectrumlocalnews.com" => "Charter Communications",
        "chatcontrol.dk" => "ChatControl DK",
        "www.tri-cityherald.com" => "Chatham Asset Management",
        "cheapskatesguide.org" => "Cheapskates Guide",
        "blog.checkpoint.com" => "Check Point Software Technologies Ltd",
        "blog.chef.io" => "Chef",
        "chelseatroy.com" => "Chelsea Troy",
        "chemospec.org" => "Chemometrics and Spectroscopy Using R",
        "chenhuijing.com" => "Chen HuiJing",
        "www.chess.com" => "Chess.com",
        "www.chiark.greenend.org.uk" => "Chiark",
        "chicagoreader.com" => "Chicago Reader",
        "www.ccsentinel.com" => "Chicago Sentinal",
        "chicago.suntimes.com" => "Chicago Sun Times",
        "www.chicagotribune.com" => "Chicago Tribune",
        "www.cdomagazine.tech" => "Chief Data Officer Magazine",
        "monkeywrench.email" => "Chinlock Holdings LLC",
        "www.chinaaid.org" => "China Aid",
        "chinadigitaltimes.net" => "China Digital Times",
        "news.cgtn.com" => "China Global Television Network",
        "www.chinalawblog.com" => "China Law Blog",
        "huyenchip.com" => "Chip Huyen",
        "chipsandcheese.com" => "Chips and Cheese",
        "blog.chiselstrike.com" => "ChiselStrike",
        "blog.toast.cafe" => "Chloé Vulquin", "vmac.ch" => "V Chris",
        "two-wrongs.com" => "Chris",
        "entropicthoughts.com" => "Chris",
        "boffosocko.com" => "Chris Aldrich",
        "blog.untrod.com" => "Chris Clark",
        "chriscoyier.net" => "Chris Coyier",
        "chrisdone.com" => "Chris Done",
        "chrisdown.name" => "Chris Down",
        "chrisenns.com" => "Chris Enns",
        "www.dlp.rip" => "Chris Fenner",
        "gomakethings.com" => "Chris Ferdinandi",
        "www.chrisfarris.com" => "Chris Ferris",
        "chrisglass.com" => "Chris Glass",
        "chrishannah.me" => "Chris Hannah",
        "chrishedges.substack.com" => "The Chris Hedges Report",
        "chrisholdgraf.com" => "Chris Holdgraf",
        "quii.dev" => "Chris James",
        "chrismcleod.dev" => "Chris McLeod",
        "chrisnager.com" => "Chris Nager",
        "odonnellweb.com" => "Chris O'Donnnell",
        "tuzz.tech" => "Chris Patuzzo",
        "pickard.cc" => "Chris Pickard",
        "chrispinnock.com" => "Chris Pinnock",
        "phanes.silogroup.org" => "Chris Punches",
        "thoughts.uncountable.uk" => "Chris Shaw",
        "chriswarrick.com" => "Chris Warrick",
        "nullprogram.com" => "Chris Wellons",
        "blog.haschek.at" => "Christian Haschek",
        "www.christian.org.uk" => "Christian Institute",
        "christiannews.net" => "Christian News",
        "www.christianitydaily.com" => "Christianity Daily",
        "www.christiantoday.com" => "Christian Today",
        "www.christiandaily.com" => "Christian Daily International",
        "www.christianpost.com" => "Christian Post",
        "www.christianitytoday.com" => "Christianity Today",
        "cjd.weblog.lol" => "Christopher Downer",
        "fleetwood.dev" => "Christopher Fleetwood",
        "christitus.com" => "Chris Titus",
        "chromeunboxed.com" => "Chrome Uboxed",
        "www.chronicle.com" => "Chronicle Of Higher Education",
        "www.chronicle-express.com" => "Chronicle Of Higher Education",
        "www.chronicle.ng" => "ChronicleNG, Nigeria",
        "www.chroniclesmagazine.org" => "Chronicles",
        "chuck.is" => "Chuck Carroll",
        "cagrimmett.com" => "Chuck Grimmett",
        "churchtechtoday.com" => "Church Tech Today",
        "www.churchtimes.co.uk" => "Church Times",
        "www.cicadamania.com" => "www.cicadamania.com",
        "www.cinia.fi" => "Cinia",
        "www.cioapplications.com" => "CIO Applications",
        "www.cioinsight.com" => "CIO Insight",
        "cioj.org" => "CIOJ",
        "notes.volution.ro" => "Ciprian Dorin Craciun",
        "www.circle-lang.org" => "Circle-Lang",
        "circleid.com" => "CircleID",
        "www.circleid.com" => "CircleID",
        "circuitcellar.com" => "Circuit Cellar",
        "cis.org" => "CIS",
        "www.cisa.gov" => "CISA",
        "www.splunk.com" => "Cisco Systems Inc",
        "talosintelligence.com" => "Cisco Systems Inc",
        "news.cision.com" => "Cision News",
        "www.cisomag.com" => "CISO Mag",
        "cissar.com" => "CISSAR",
        "citizenlab.ca" => "Citizen Lab",
        "www.citizensforethics.org" => "Citizens For Ethics",
        "citizix.com" => "Citizix",
        "toronto.citynews.ca" => "City News CA",
        "www.hel.fi" => "City of Helsinki",
        "www.cityofpensacola.com" => "City of Pensacola",
        "civicspacewatch.eu" => "Civic Space Watch",
        "www.liberties.eu" => "Civil Libeties Union",
        "civileats.com" => "Civil Eats",
        "curia.europa.eu" => "CJEU",
        "www.cjr.org" => "CJR",
        "clarionproject.org" => "Clarion Project",
        "www.classaction.org" => "Class Action",
        "www.classicpress.net" => "ClassicPress",
        "www.cleanenergywire.org" => "Clean Energy Wire",
        "cleanuptheweb.org" => "Clean Up The Web",
        "clearpathrobotics.com" => "Clearpath Robotics",
        "clemenswinter.com" => "Clemens Winter",
        "www.cleveland.com" => "Cleveland",
        "www.clickondetroit.com" => "Click On Detroit",
        "cliffle.com" => "Cliff L Biffle",
        "www.climatechangenews.com" => "Climate Change News",
        "climatenewsnetwork.net" => "Climate News Network",
        "climbtheladder.com" => "CLIMB",
        "dev.clintonblackburn.com" => "Clinton Blackburn",
        "cloudfour.com" => "Cloud Four Inc",
        "blog.cloudflare.com" => "Cloudflare",
        "www.cloudflare.com" => "Cloudflare",
        "www.farms.com" => "CME",
        "www.channelnewsasia.com" => "CNA",
        "www.cnbctv18.com" => "CNBC",
        "fm.cnbc.com" => "CNBC",
        "www.cnbc.com" => "CNBC",
        "www.cnbcafrica.com" => "CNBC",
        "www.cnet.com" => "CNET",
        "edition.cnn.com" => "CNN",
        "lite.cnn.com" => "CNN",
        "money.cnn.com" => "CNN",
        "us.cnn.com" => "CNN",
        "www.cnn.com" => "CNN",
        "www.cnx-software.com" => "CNX Software",
        "c2pa.org" => "Coalition for Content Provenance and Authenticity",
        "www.coastaldigest.com" => "Coastal Digest",
        "www.cockroachlabs.com" => "Cockroach Labs",
        "coconuts.co" => "Coconuts",
        "www.codastory.com" => "Coda Media Inc",
        "codeahoy.com" => "Code Ahoy",
        "code.likeagirl.io" => "Code Like A Girl",
        "anonimno.codeberg.page" => "Codeberg",
        "www.codedonut.com" => "Code Donut",
        "blog.codemagic.io" => "Code Magic",
        "code-maven.com" => "Code Maven",
        "codeberg.org" => "Codeberg",
        "blog.codeberg.org" => "Codeberg",
        "www.coiled.io" => "Coiled Computing",
        "www.coindesk.com" => "Coin Desk",
        "www.coin-operated.com" => "Coin Operated",
        "coinmarketcal.com" => "CoinMarketCal",
        "cointelegraph.com" => "Cointelegraph",
        "coldstreams.com" => "Cold Streams",
        "www.colino.net" => "Colin Leroy-Mira",
        "colinwalker.blog" => "Colin Walker",
        "collider.com" => "Collider",
        "www.mcmillen.dev" => "Collin McMillen",
        "boulderweekly.com" => "Colorado",
        "coloradosun.com" => "Colorado",
        "coloradosupremecourt.com" => "Colorado",
        "www.courts.state.co.us" => "Colorado",
        "www.greeleytribune.com" => "Colorado",
        "www.coloradopolitics.com" => "Colorado Politics",
        "www.cpr.org" => "Colorado Public Radio",
        "www.columbian.com" => "The Columbian",
        "eu.dispatch.com" => "Columbus Ohio",
        "comicbook.com" => "Comic Book",
        "boundingintocomics.com" => "Comics",
        "www.commondreams.org" => "Common Dreams",
        "www.commonsensemedia.org" => "Common Sense Media",
        "www.commonwealmagazine.org" => "Commonweal Magazine",
        "www.commonwealthclub.org" => "Commonweatlh Club",
        "www.commonwealthfund.org" => "The Commonweatlh Fund",
        "www.communia-association.org" => "Communia",
        "www.news-gazette.com" => "Community Media Group",
        "www.comparitech.com" => "Comparitech Ltd",
        "www.computerconservationsociety.org" => "Computer Conservation Society",
        "computerhistory.org" => "Computer History",
        "www.softwarepreservation.org" => "Computer History Museum",
        "computer.rip" => "Computers Are Bad",
        "www.computerweekly.com" => "Computer Weekly",
        "www.computerworld.com" => "Computer World",
        "www2.computerworld.co.nz" => "Computer World",
        "www.computing.co.uk" => "Computing UK",
        "confused.ai" => "Confused AI",
        "concurrencyfreaks.blogspot.com" => "Concurrency Freaks",
        "pitchfork.com" => "Condé Nast",
        "conduition.io" => "Conduition",
        "www.ctpost.com" => "Conneticut Post",
        "www.ctpublic.org" => "Conneticut Public",
        "www.connexionfrance.com" => "The Connexion",
        "connortumbleson.com" => "Connor Tumbleson",
        "www.conservation.org" => "Conservation International",
        "www.conservationinstitute.org" => "Conservation Institute",
        "www.conservativewoman.co.uk" => "Conservative Woman",
        "console.dev" => "Console Dev Tools",
        "consortiumnews.com" => "Consortium News",
        "advocacy.consumerreports.org" => "Consumer Reports",
        "innovation.consumerreports.org" => "Consumer Reports",
        "www.consumerreports.org" => "Consumer Reports",
        "opensource.contentauthenticity.org" => "Content Authenticity Intiative",
        "conversationalist.org" => "Conversationalist",
        "stack.convex.dev" => "Convex Inc",
        "cooltechzone.com" => "Cool Tech Zone",
        "cphpost.dk" => "Copenhagen Post",
        "visitorservice.kk.dk" => "Copenhagen Visitor Service",
        "www.copticsolidarity.org" => "Coptic Solidarity",
        "corecursive.com" => "CoRecursive",
        "www.coreystephan.com" => "Corey Stephan",
        "www.zotero.org" => "Corporation for Digital Scholarship",
        "correctiv.org" => "Correctiv",
        "craphound.com" => "Cory Doctorow",
        "doctorow.medium.com" => "Cory Doctorow",
        "pluralistic.net" => "CoryDoctorow",
        "coryd.dev" => "Cory Dransfeldt",
        "www.cosmopolitan.com" => "Cosmopolitan",
        "coss.fi" => "COSS ry",
        "rm.coe.int" => "Council Of Europe",
        "www.coe.int" => "Council Of Europe",
        "www.counterpunch.org" => "Counter Punch",
        "counterview.org" => "Counterview",
        "couragefound.org" => "Courage Found",
        "couriernewsroom.com" => "Courier Newsroom",
        "www.courthousenews.com" => "Court House News",
        "www.courtlistener.com" => "Court Listener",
        "storage.courtlistener.com" => "Free Law Project",
        "www.insideprivacy.com" => "Covington & Burling LLP",
        "am.covestro.com" => "Covestro",
        "www.coveware.com" => "Coveware",
        "api.docs.cpanel.net" => "cPanel",
        "www.competitionpolicyinternational.com" => "CPI",
        "cpj.org" => "CPJ",
        "www.cpomagazine.com" => "CPO Mag",
        "research.checkpoint.com" => "CPR",
        "cracked.com" => "Cracked",
        "www.cracked.com" => "Cracked",
        "craftofcoding.wordpress.com" => "Craft Of Coding",
        "www.craigabbott.co.uk" => "Craig Abbott",
        "furbo.org" => "Craig Hockenberry",
        "craigmod.com" => "Craig Mod",
        "www.craigmurray.org.uk" => "Craig Murray",
        "www.chicagobusiness.com" => "Crain Communications Inc",
        "minerva.crocs.fi.muni.cz" => "CRCS",
        "headrush.typepad.com" => "Creating Passionate Users",
        "www.creativeboom.com" => "Creative Boom Ltd",
        "creativecommons.org" => "Creative Commons",
        "www.cltampa.com" => "Creative Loafing Tampa Bay",
        "blog.cretaria.com" => "Cretaria",
        "techreflect.org" => "TechReflect",
        "www.crikey.com.au" => "Crickey",
        "www.cringely.com" => "I Cringely",
        "deadserious.beehiiv.com" => "I'm Dead Serious",
        "www.destinationcrm.com" => "CRM Mag",
        "www.crn.com" => "CRN",
        "crookedtimber.org" => "Crooked Timber",
        "www.crowdsupply.com" => "Crowd Supply",
        "www.crowdstrike.com" => "CrowdStrike",
        "www.crownpeak.com" => "Crownpeak Technology Inc",
        "www.cps.gov.uk" => "Crown Prosecution Service UK",
        "cruncher.ch" => "Cruncher",
        "safecurves.cr.yp.to" => "Crypto",
        "www.cryptomuseum.com" => "Crypto Museum",
        "cryptonewsbtc.org" => "Crypto News BTC",
        "eprint.iacr.org" => "Cryptology ePrints Archive",
        "cryptonews.com" => "Cryptonews",
        "the-crypto-syllabus.com" => "The Crypto [sic] Syllabus",
        "joyofcryptography.com" => "Cryptography",
        "blog.cryptographyengineering.com" => "Cryptography Engineering",
        "blog.cryptohack.org" => "Cryptohack",
        "cryptomoneyteam.co" => "CryptoMoney Team",
        "www.csa.gov.sg" => "CSA Singapore",
        "docs.csc.fi" => "CSC",
        "www.csc.fi" => "CSC",
        "www.csis.org" => "CSIS",
        "ezorigin.csmonitor.com" => "CS Monitor",
        "www.csmonitor.com" => "CS Monitor",
        "www.csoonline.com" => "CSO",
        "css-tricks.com" => "CSS Tricks",
        "csvbase.com" => "CSVbase",
        "carbontracker.org" => "CTI",
        "calgary.ctvnews.ca" => "CTV News",
        "kitchener.ctvnews.ca" => "CTV News",
        "montreal.ctvnews.ca" => "CTV News",
        "www.ctvnews.ca" => "CTV News",
        "havanatimes.org" => "Cuba",
        "cubiclenate.com" => "CubicleNate",
        "cujo.com" => "CUJOAI",
        "veilid.com" => "Cult Of The Dead Cow",
        "www.cultofmac.com" => "Cult Of Mac",
        "crumplab.com" => "CUNY",
        "cupalo.substack.com" => "Cupalo",
        "curl.se" => "cURL",
        "www.currentaffairs.org" => "Current Affairs",
        "curtmerrill.com" => "Curt Merrill",
        "www.cvbj.biz" => "CVBJ",
        "www.cxotoday.com" => "CXO Today",
        "cyber-itl.org" => "Cyber Independent Testing Lab",
        "www.cshub.com" => "Cyber Security Hub",
        "cybershow.uk" => "The Cyber Show",
        "cybergeeks.tech" => "Cybergeeks",
        "cybergibbons.com" => "Cybergibbons",
        "cybernews.com" => "Cybernews",
        "cyberprawn.net" => "Cyberprawn",
        "www.scmagazine.com" => "CyberRisk Alliance LLC",
        "www.cybertec-postgresql.com" => "Cybertec PostgreSQL International GmbH",
        "cybersecuritynews.com" => "Cyber Security News",
        "cyber.dabamos.de" => "The Cyber VanguarThe Cyber Vanguard",
        "cyble.com" => "Cyble Inc",
        "thecyberexpress.com" => "Cyble Inc",
        "cybleinc.com" => "Cyble Inc",
        "cyclonedx.org" => "CycloneDX",
        "www.cyentia.com" => "Cyentia Institute LLC",
        "www.cynet.com" => "Cynet Security Ltd",
        "franklywrite.com" => "Cynthia Franks",
        "blog.cynthia.re" => "Cynthias Blog",
        "cyprus-mail.com" => "Cyprus",
        "www.daemonology.net" => "Daemonology",
        "www.daghammarskjold.se" => "DagHammarskjöld",
        "dailycoin.com" => "Daily Coin",
        "www.dailydot.com" => "Daily Dot",
        "www.dailyherald.com" => "Daily Herald",
        "dailyinfographic.com" => "Daily Infographic",
        "www.dailykos.com" => "Daily Kos",
        "www.dailymail.co.uk" => "Daily Mail",
        "www.dailymaverick.co.za" => "Daily Maverick",
        "www.dailyo.in" => "Daily O",
        "dailypost.ng" => "Daily Post",
        "www.dailyrecord.co.uk" => "Daily Record",
        "www.dailysabah.com" => "Daily Sabah",
        "www.dailystar.co.uk" => "Daily Star",
        "www.dailytarheel.com" => "Daily Tar Heel",
        "dailytimes.com.pk" => "Daily Times",
        "www.dailywire.com" => "Daily Wire",
        "www.dailytrib.com" => "DailyTrib",
        "www.dallasnews.com" => "Dallas News",
        "dallincrump.com" => "Dallin Crump",
        "the-dam.org" => "The Dam",
        "desfontain.es" => "Damien Desfontaines",
        "dmathieu.com" => "Damien Mathieu",
        "www.damnsmalllinux.org" => "Damn Smalll Linux",
        "blog.djhaskin.com" => "Dan",
        "www.bricklin.com" => "Dan Bricklin",
        "www.dancowell.com" => "Dan Cowell",
        "blog.sunfishcode.online" => "Dan Gohman",
        "geer.tinho.net" => "Dan Geer",
        "dan.langille.org" => "Dan Langille",
        "danluu.com" => "Dan Luu",
        "www.danlynch.org" => "Dan Lynch",
        "mcfunley.com" => "Dan McKinley",
        "letterstoanewdeveloper.com" => "Dan Moore",
        "blog.nem.ec" => "Dan Nemec",
        "danq.me" => "Dan Q",
        "blog.danslimmon.com" => "Dan Slimmon",
        "danabyerly.com" => "Dana Byerly",
        "www.danfoss.com" => "Danfoss",
        "www.ctrl.blog" => "Daniel Aleksandersen",
        "cr.yp.to" => "Daniel J. Bernstein,",
        "danielbmarkham.com" => "Daniel B Markham",
        "danieldk.eu" => "Daniël de Kok",
        "dgross.ca" => "Daniel P Gross",
        "danielcompton.net" => "Daniel Compton",
        "code.dblock.org" => "Daniel Doubrovkine",
        "destevez.net" => "Daniel Estévez",
        "lipu.dgold.eu" => "Daniel Goldsmith",
        "theorangeduck.com" => "Daniel Holden",
        "chown.me" => "Daniel Jakots",
        "bitsplitting.org" => "Daniel Jalkut",
        "blog.danieljanus.pl" => "Daniel Janus",
        "daniel-lange.com" => "Daniel Lange",
        "lemire.me" => "Daniel Lemire",
        "www.daniloaz.com" => "Daniel López Azañ",
        "danielmiessler.com" => "Daniel Miessler",
        "daniel.industries" => "Daniel Miller",
        "www.daniel.industries" => "Daniel Miller",
        "nechtan.io" => "Daniel Nechtan",
        "www.danielpipes.org" => "Daniel Pipes",
        "danielpocock.com" => "Daniel Pocock",
        "danschmid.de" => "Daniel Schmid",
        "daniel.haxx.se" => "Daniel Stenberg",
        "bagder.github.io" => "Daniel Stenberg",
        "dxuuu.xyz" => "Daniel Xu",
        "danilafe.com" => "Daniel Fedorin",
        "goodbye.domains" => "Danielle Baskin",
        "redeem-tomorrow.com" => "Danilo Campos",
        "www.dannyguo.com" => "Danny Guo",
        "www.oblomovka.com" => "Danny O'Brien",
        "dannyvankooten.com" => "Danny van Kooten",
        "blog.lambda.cx" => "Dante Catalfamo",
        "danterobinson.dev" => "Dante Robinson",
        "bigdanzblog.wordpress.com" => "DanTheMan",
        "darekkay.com" => "Darek Kay",
        "www.darkreading.com" => "Dark Reading",
        "blog.darksky.net" => "Dark Sky",
        "www.darktable.org" => "Darktable",
        "darrenburns.net" => "Darren Burns",
        "darrengoossens.wordpress.com" => "Darren Goossens",
        "notes.darrenhester.com" => "Darren Hester",
        "dashbit.co" => "Dashbit",
        "databasearchitects.blogspot.com" => "Databases",
        "www.databreaches.net" => "Data Breaches",
        "www.databreachtoday.com" => "Data Breach Today",
        "www.dataprotection.ie" => "Data Protection Commission Ireland",
        "datasciencetut.com" => "Data Science Tutorials",
        "dtinit.org" => "Data Transfer Initiative",
        "thedatascientist.com" => "The Data Scientist",
        "datapopalliance.org" => "Data-Pop Alliance",
        "www.datacenterdynamics.com" => "DataCenter Dynamics",
        "datageeek.com" => "DataGeeek",
        "www.datanami.com" => "Datanami",
        "dataschool.com" => "Data School",
        "datastation.multiprocess.io" => "Data Station",
        "dataswamp.org" => "Data Swamp",
        "www.wgmd.com" => "DataTech Digital Inc",
        "datto.engineering" => "Datto",
        "airlied.blogspot.com" => "Dave Airlie",
        "blog.dave.tf" => "Dave Anderson",
        "www.dave.tf" => "Dave Anderson",
        "www.bennettnotes.com" => "Dave Bennett",
        "davedelong.com" => "Dave DeLong",
        "davelane.nz" => "Dave Lane",
        "daverupert.com" => "Dave Rupert",
        "intuitivestories.com" => "Dave Taylor",
        "davidamos.dev" => "David Amos",
        "davidben.net" => "David Benjamin",
        "www.da.vidbuchanan.co.uk" => "David Buchanan",
        "betterwithout.ai" => "David Chapman",
        "crawshaw.io" => "David Crawshaw",
        "darn.es" => "David Darnes",
        "blog.davidedmundson.co.uk" => "David Edmundson",
        "blog.dnmfarrell.com" => "David Farrell",
        "davidgerard.co.uk" => "David Gerard",
        "dgerrells.com" => "David Gerrells",
        "notes.1705.net" => "David H",
        "davidhamann.de" => "David Hamann",
        "davidhampgonsalves.com" => "David Hamp-Gonsalves",
        "dhh.dk" => "David Heinemeier Hansson",
        "dfarq.homeip.net" => "David L Farquhar",
        "davidjohnmead.com" => "David Mead",
        "www.davidrevoy.com" => "David Revoy",
        "blog.dshr.org" => "David Rosenthal",
        "thecrow.uk" => "David Rutland",
        "experimentalworks.net" => "David Soria Parra",
        "www.macsparky.com" => "David Sparks",
        "www.david-smith.org" => "David Smith",
        "davidsuzuki.org" => "David Suzuki Foundation",
        "davidltran.com" => "David Tran",
        "davidwalsh.name" => "David Walsh",
        "www.moczadlo.com" => "Dawid Moczadło",
        "herald.dawn.com" => "Dawn Media",
        "images.dawn.com" => "Dawn Media",
        "www.dawn.com" => "Dawn Media",
        "www.daytondailynews.com" => "Dayton Daily News",
        "spreadprivacy.com" => "DDG",
        "deadline.com" => "Deadline",
        "www.deadlinedetroit.com" => "Deadline Detroit",
        "www.deanwesleysmith.com" => "Dean Wesley Smith",
        "www.deathpenaltyproject.org" => "Death Penalty Project",
        "bits.debian.org" => "Debian",
        "forums.debian.net" => "Debian",
        "lists.debian.org" => "Debian",
        "wiki.debian.org" => "Debian",
        "www.debian.org" => "Debian",
        "thedebrief.org" => "The Debrief",
        "www.deccanchronicle.com" => "Deccan Chronicle",
        "www.deccanherald.com" => "Deccan Herald",
        "dt.gl" => "Decentralize Today",
        "decisiondata.org" => "Decision Data",
        "declassifieduk.org" => "Declassified UK",
        "decoded.legal" => "Decoded Legal",
        "decrypt.co" => "Decrypt",
        "www.dedoimedo.com" => "Dedoimedo",
        "defector.com" => "Defector",
        "www.defenceweb.co.za" => "Defence Web",
        "www.defensenews.com" => "Defense News",
        "www.defenseone.com" => "Defense One",
        "www.delawarepublic.org" => "Delaware Republic",
        "www.delcotimes.com" => "Delco Times",
        "delishably.com" => "Arena Media Brands LLC",
        "demandprogress.org" => "Demand Progress",
        "dawnmena.org" => "Democracy for the Arab World Now",
        "www.democracydocket.com" => "Democracy Docket",
        "www.democracynow.org" => "Democracy Now",
        "www.open-std.org" => "uni Technical University of Denmark",
        "easyperf.net" => "Denis Bakhvalov",
        "hookrace.net" => "Dennis Felsing",
        "yurichev.com" => "Dennis Yurichev",
        "deno.com" => "Deno Land Inc",
        "denverite.com" => "Denver",
        "www.denverpost.com" => "Denver",
        "www.thedenverchannel.com" => "Denver",
        "www.westword.com" => "Denver",
        "denvergazette.com" => "Denver Gazette",
        "blog.deref.io" => "Deref",
        "derekkedziora.com" => "Derek Kędziora",
        "sive.rs" => "Derek Sivers",
        "sivers.org" => "Derek Sivers",
        "blog.desdelinux.net" => "Desde Linux",
        "www.deseret.com" => "Deseret News",
        "desertification.wordpress.com" => "Desertification",
        "www.designboom.com" => "Designboom",
        "www.desmogblog.com" => "DeSmog",
        "www.desmog.com" => "DeSmog",
        "labs.detectify.com" => "DetectifyLabs",
        "www.onedetroitpbs.org" => "Detroit Public TV",
        "www.dw.com" => "Deutsche Welle",
        "devclass.com" => "Dev Class",
        "dev.to" => "DEV Community",
        "blog.devgenius.io" => "Dev Genius",
        "devd.me" => "Devdatta Akhawe",
        "www.devdiscourse.com" => "Dev Discourse",
        "www.developer-tech.com" => "Developer Tech",
        "www.devever.net" => "Devever",
        "www.devex.com" => "Devex",
        "www.devseccon.com" => "Dev Sec Con",
        "devicetests.com" => "DeviceTests",
        "devondundee.com" => "Devon Dundee",
        "devuan.org" => "Devuan",
        "www.devuan.org" => "Devuan",
        "dev1galaxy.org" => "Devuan",
        "www.dfs.ny.gov" => "DFS NY",
        "www.dhakatribune.com" => "Dhaka Tribune",
        "soatok.blog" => "Dhole Moments",
        "www.dhs.gov" => "DHS",
        "www.diabettech.com" => "Diabet Tech",
        "dianerehm.org" => "American University Radio",
        "blog.didierstevens.com" => "Didier Stevens",
        "diem25.org" => "DiEM25",
        "digiday.com" => "Digi Day",
        "www.digikey.co.uk" => "Digi-key Electronics",
        "www.digikey.com" => "Digi-key Electronics",
        "www.winxdvd.com" => "Digiarty Software",
        "diginomica.com" => "Diginomica",
        "www.digit.in" => "Digit.in",
        "www.digitalcameraworld.com" => "Digital Camera World",
        "digitalcontentnext.org" => "Digital Content Next",
        "eu.detroitnews.com" => "Digital First Media",
        "www.detroitnews.com" => "Digital First Media",
        "dfrlab.org" => "Digital Forensic Research Lab",
        "www.digitalhealth.net" => "Digital Health",
        "www.digitaljournal.com" => "Digital Journal",
        "www.digitalmusicnews.com" => "Digital Music News",
        "www.digitalocean.com" => "Digital Ocean",
        "www.dpreview.com" => "Digital Photography Review",
        "digitalprivacy.news" => "Digital Privacy News",
        "www.digitaltrends.com" => "Digital Trends",
        "www.oneindia.com" => "Digitech Media Pvt Ltd",
        "dillonmok.com" => "Dillon Mok",
        "notes.secretsauce.net" => "Dima Kogan",
        "dimamoroz.com" => "Dima Moroz",
        "dinesh.wiki" => "Dinesh Gowda",
        "dirk.eddelbuettel.com" => "Dirk Eddelbuettel",
        "dirkriehle.com" => "Dirk Riehle",
        "dismalswampwelcomecenter.com" => "Dismal Swamp Canal Welcome Center",
        "disconnect.blog" => "Disconnect.blog",
        "discord.com" => "Discord",
        "status.discordapp.com" => "Discord",
        "www.discourseblog.com" => "Discourse Blog",
        "disroot.org" => "Disroot",
        "www.consumerfinance.gov" => "US Consummer Financial Protection Bureau",
        "www.opn.ca6.uscourts.gov" => "US Court of Appeals, 6th Circuit",
        "cdn.ca9.uscourts.gov" => "US Court of Appeals, 9th Circuit",
        "www.ca9.uscourts.gov" => "US Court of Appeals, 9th Circuit",
        "media.cadc.uscourts.gov" => "US Court of Appeals, DC Circuit",
        "www.cadc.uscourts.gov" => "US Court of Appeals, D C Circuit",
        "www.govinfo.gov" => "US Government Publishing Office",
        "distrowatch.com" => "Distro Watch",
        "www.diyphotography.net" => "DIY Phototgraphy",
        "diziet.dreamwidth.org" => "Diziet",
        "qmacro.org" => "DJ Adams",
        "blog.cr.yp.to" => "DJ Bernstein",
        "viewpoints.dji.com" => "DJI",
        "www.linuxtechmore.com" => "Djalel Oukid",
        "fwslc.blogspot.com" => "DL Wicksell",
        "dbohdan.com" => "D Bohdan",
        "dlang.org" => "D Lang",
        "dkb.blog" => "Dmitri Brereton",
        "chshersh.com" => "Dmitrii Kovanikov",
        "zine.dev" => "Dmitry Chestnykh",
        "dmitry.gr" => "Dmitry Grinberg",
        "dolzhenko.me" => "Dmitry Dolzhenko",
        "dn42.cc" => "DN42",
        "www.dnaindia.com" => "DNA India",
        "www.dnalounge.com" => "DNA Lounge",
        "blog.darknedgy.net" => "DnE",
        "root-servers.org" => "DNS",
        "www.dns0.eu" => "DNS0.eu",
        "lists.thekelleys.org.uk" => "DNSmasq",
        "www.techzine.eu" => "Dolphin Publications B V",
        "doc.searls.com" => "Doc Searls",
        "docseuss.medium.com" => "Doc Burford",
        "s3.documentcloud.org" => "Document Cloud",
        "blog.documentfoundation.org" => "Document Foundation",
        "wiki.documentfoundation.org" => "Document Foundation",
        "dlvhdr.me" => "Dolev Hadar",
        "domainnamewire.com" => "Domain Namewire",
        "www.domaintools.com" => "DomainTools",
        "blog.domenic.me" => "Domenic Denicola",
        "freeston.me" => "Dominic Freeston",
        "lostfocus.de" => "Dominik Schwind",
        "www.donaldedavis.com" => "Don Davis",
        "blog.zgp.org" => "Don Marti",
        "www.donnfelker.com" => "Donn Felker",
        "dontextraditeassange.com" => "Don't Extradite Assange",
        "dominickm.com" => "Mike Dominick",
        "imapenguin.com" => "Mike Doornbos",
        "crashthearcade.com" => "Mike Haynes",
        "initialcharge.net" => "Mike Rockwell",
        "dotesports.com" => "Dot Esports",
        "www.dotmed.com" => "Dot Med",
        "dotsrc.org" => "Dotsrc",
        "dougbelshaw.com" => "Doug Bellshaw",
        "www.downtowndougbrown.com" => "Doug Brown",
        "doug.pub" => "Doug Jones",
        "dougallj.wordpress.com" => "Dougall J",
        "www.downtoearth.org.in" => "Down to Earth",
        "downtimeproject.com" => "Downtime Project",
        "dpk.land" => "DPK.land",
        "www.digitalresearch.biz" => "DR",
        "chainsawriot.com" => "Dr Chung-hong Chan",
        "leancrew.com" => "Dr Drang",
        "wiki.dragino.com" => "Dragino Technology Company, Ltd",
        "lists.dragonflybsd.org" => "DragonFly BSD",
        "www.dragonflydigest.com" => "DragonFly BSD Digest",
        "www.dremeljunkie.com" => "DremelJunkie",
        "www.dbreunig.com" => "Drew Breunig",
        "drewdevault.com" => "Drew DeVault",
        "drewsh.com" => "Drew Jose",
        "blog.drewolson.org" => "Drew Olson",
        "drew.shoes" => "Drew Schuster",
        "drexel.edu" => "Drexel University",
        "droidgazette.com" => "DroidGazzette",
        "www.thedronegirl.com" => "The Drone Girl",
        "diydrones.com" => "Drones",
        "dronedj.com" => "Drones",
        "blog.dropbox.com" => "Dropbox",
        "www.dsogaming.com" => "DSOG",
        "szoftveralapcsomag.hu" => "DSSP",
        "distincttoday.net" => "DT",
        "dt.iki.fi" => "DT",
        "dtrace.org" => "DTrace",
        "duckalignment.academy" => "Duck Alignment Academy",
        "duncanlock.net" => "Duncan Lock",
        "duo.com" => "Duo",
        "0xdstn.site" => "Dustin",
        "pa0rwe.nl" => "Dutch Amateur Radio Station PA0RWE",
        "www.dutchnews.nl" => "Dutch News",
        "www.duvarenglish.com" => "duvaR",
        "www.lafoo.com" => "Dwayne Lafleur",
        "www.dylanpaulus.com" => "Dylan Paulus",
        "lists.dyne.org" => "Dyne",
        "new.dyne.org" => "Dyne",
        "dys2p.com" => "Itermann Wansing GbR",
        "dzackgarza.com" => "DZack Garza",
        "dzone.com" => "DZone",
        "chiefio.wordpress.com" => "E M Smith",
        "eamon.wiki" => "Eamon Wiki",
        "text.eapl.mx" => "EAPL.mx",
        "earthjustice.org" => "Earth Justice",
        "earthly.dev" => "Earthly",
        "earth.org" => "EarthOrg",
        "earthsky.org" => "EarthSky",
        "www.eastidahonews.com" => "EastIdahoNews.com LLC",
        "eaton-works.com" => "Eaton Works",
        "www.libreture.com" => "EBooks",
        "www.ebu.ch" => "EBU",
        "www.echo-news.co.uk" => "Echo News",
        "eclecticlight.co" => "Eclectic Light Company",
        "www.eclipse.org" => "Eclipse Foundation",
        "eclypsium.com" => "Eclypsium",
        "www.eco-business.com" => "Eco-Business",
        "www.ecommercetimes.com" => "Ecommerce",
        "economist.com.na" => "Economist",
        "www.ecowatch.com" => "EcoWatch",
        "www.ecstuff4u.com" => "ECStuff4U",
        "www.technewsworld.com" => "ECT News Network Inc",
        "www.britannica.com" => "Encyclopedia Britannica",
        "www.theenergymix.com" => "Energy Mix Productions Inc",
        "lightbytes.es.net" => "Energy Sciences Network",
        "www.enterprisedb.com" => "EnterpriseDB Corporation",
        "edps.europa.eu" => "EDPS",
        "civicrm.edri.org" => "EDRI",
        "edri.org" => "EDRI",
        "www.edgrochowski.com" => "Ed Grochowski",
        "www.wheresyoured.at" => "Ed Zitron",
        "www.editorandpublisher.com" => "Editor and Publisher",
        "edsource.org" => "EdSource",
        "sizovs.net" => "Eduards Sizovs",
        "edwardbetts.com" => "Edward Betts",
        "hasbrouck.org" => "Edward Hasbrouck",
        "edwardsnowden.substack.com" => "Edward Snowden",
        "files.eric.ed.gov" => "Education Resources Information Center",
        "eric.ed.gov" => "Education Resources Information Center",
        "www.edweek.org" => "EducationWeek",
        "theta.eu.org" => "Eeeeeta",
        "www.eejournal.com" => "EE Journal",
        "eerielinux.wordpress.com" => "Eerie Linux",
        "news.err.ee" => "Eesti Rahvusringhääling",
        "iot.eetimes.com" => "EE Times",
        "www.eetimes.com" => "EE Times",
        "www.eetimes.eu" => "EE Times",
        "evangelicalfocus.com" => "EF",
        "act.eff.org" => "EFF",
        "toruniversity.eff.org" => "EFF",
        "w2.eff.org" => "EFF",
        "www.eff.org" => "EFF",
        "www.effectiveperlprogramming.com" => "The Effective Perler",
        "samizdat.dev" => "Egor Kovetskiy",
        "pages.egress.com" => "Egress Software Technologies Ltd",
        "www.egress.com" => "Egress Software Technologies Ltd",
        "www.egypttoday.com" => "Egypt Today",
        "emmahumphreys.org" => "EHMP",
        "ehrintelligence.com" => "EHR",
        "www.einnews.com" => "EIN Presswire",
        "www.eisfunke.com" => "Eisefunke",
        "www.ejinsight.com" => "EJI Insight",
        "www.ekioh.com" => "Ekioh",
        "www.ekora.io" => "EKORA",
        "blog.eldrid.ge" => "Eldridge Alexander",
        "electrek.co" => "Electrek",
        "electricliterature.com" => "Electric Lit",
        "www.electrive.com" => "Electrive",
        "www.rs-online.com" => "Electrocomponents PLC",
        "electrodacus.com" => "ElectroDacus",
        "www.electronicdesign.com" => "Electronic Design",
        "www.electronicsweekly.com" => "Electronics Weekly",
        "old.efn.no" => "Elektronisk Forpost Norge",
        "eli.thegreenplace.net" => "Eli Bendersky",
        "element.io" => "Element",
        "blog.dhsdevelopments.com" => "Elias Mårtenson",
        "www.elinux.co.in" => "ELinux",
        "elisehe.in" => "Elise Hein",
        "elixir-lang.org" => "The Elixir Team",
        "www.elixir-finland.org" => "ELIXIR",
        "www.elysian.press" => "Elle Griffin",
        "www.elliotcsmith.com" => "Elliot C Smith",
        "www.econotimes.com" => "Elmin Media",
        "eloydegen.com" => "Eloy Degen",
        "english.elpais.com" => "El País",
        "elpais.com" => "El País",
        "elronnd.net" => "Elron ND",
        "www.ombudsman.europa.eu" => "European Ombudsman",
        "www.esa.int" => "European Space Agency",
        "www.ema.europa.eu" => "EMA",
        "www.emergency-live.com" => "Emergency Live",
        "www.emerald.com" => "Emerald Publishing Ltd",
        "emerg-in.co.uk" => "Emerging Risks",
        "emaggiori.com" => "Emmanuel Maggiori",
        "crisal.io" => " Emilio Cobos Álvarez ",
        "emilymstark.com" => "Emily M Stark",
        "www.emsisoft.com" => "Emisoft Ltd",
        "www.en24.news" => "EN24 News",
        "endsoftwarepatents.org" => "End Software Patents",
        "wiki.endsoftwarepatents.org" => "End Software Patents",
        "forum.endeavouros.com" => "EndeavourOS",
        "www.enea.com" => "Enea",
        "www.pv-magazine.com" => "Energy",
        "www.energystar.gov" => "Energy Star",
        "enews.com.ng" => "Enews Nigeria",
        "www.engadget.com" => "Engadget",
        "engineerzero.blog" => "Engineer Zero",
        "www.englishpen.org" => "English Pen",
        "blog.yossarian.net" => "Eno Such",
        "www.engprax.com" => "Engprax Ltd",
        "enterprisersproject.com" => "Enterprisers Project",
        "www.enterprisesecuritytech.com" => "Enterprise Security Tech",
        "enterprisetalk.com" => "Enterprise Talk",
        "ew.com" => "Entertainment Weekly",
        "www.entrepreneur.com" => "Entrepeneur",
        "www.entropicengineering.com" => "Entropic Engineering",
        "env.fail" => "Env.Fail",
        "www.environment911.org" => "Environment",
        "www.theearthneedslove.com" => "Environment",
        "business.edf.org" => "Environmental Defense Fund",
        "www.epaoig.gov" => "EPA",
        "www.epa.gov" => "EPA",
        "epic.org" => "EPIC",
        "epicenter.works" => "epicenter.works",
        "www.epicgames.com" => "Epic Games",
        "www.europeanpharmaceuticalreview.com" => "EPR",
        "www.equaltimes.org" => "Equal Times",
        "ejona.ersoft.org" => "Eric Anderson",
        "ericwbailey.design" => "Eric Bailey",
        "ericwbailey.website" => "Eric Bailey",
        "bloi.ericgoldman.org" => "Eric Goldman",
        "alien.slackbook.org" => "Eric Hameleers",
        "macadie.info" => "Eric MacAdie",
        "erikmcclure.com" => "Eric McClure",
        "pauley.me" => "Eric Pauley",
        "catb.org" => "Eric S Raymond",
        "esr.ibiblio.org" => "Eric S Raymond",
        "educatedguesswork.org" => "Eric Rescorla",
        "ericmwalk.blog" => "Eric Walker",
        "mcuoneclipse.com" => "Erich Styger",
        "erikbern.com" => "Erik Bernhardsson",
        "daedtech.com" => "Erik Dietrich",
        "erik.itland.no" => "Erik Itland",
        "erikarow.land" => "Erika Rowland",
        "erinkissane.com" => "Erin Kissane",
        "blog.erlend.sh" => "Erlend Sogge Heggen",
        "blog.erlang.org" => "Erlang",
        "www.erlang.org" => "Erlang",
        "garba.org" => "Ernesto Garbarino",
        "blog.erratasec.com" => "Errata Security",
        "ersei.net" => "Ersei",
        "www.esecurityplanet.com" => "eSecurity Planet",
        "hacks.esar.org.uk" => "Esar",
        "www.eset.com" => "ESET spol s r o",
        "eshelyaron.com" => "Eshel Yaron",
        "esn.org" => "ESN",
        "www.espn.com" => "ESPN",
        "www.catb.org" => "ESR",
        "www.espressif.com" => "Espressif Systems",
        "www.esquire.com" => "Esquire",
        "www.esrl.noaa.gov" => "ESRL",
        "www.wionews.com" => "Essel Group",
        "kapo.ee" => "Estonia",
        "www.riigikogu.ee" => "Estonia",
        "www.valisluureamet.ee" => "Estonian Foreign Intelligence Service",
        "estonianworld.com" => "Estonian World",
        "eta.st" => "Eta",
        "www.eternitynews.com.au" => "Eternity News",
        "etgarkeret.substack.com" => "Etgar Keret",
        "www.ethanhein.com" => "Ethan Hein",
        "ethanmarcotte.com" => "Ethan Marcotte",
        "thunderseethe.dev" => "Ethan Smith",
        "mccue.dev" => "Ethan McCue",
        "er4hn.info" => "Ethan Rahn",
        "www.oneusefulthing.org" => "Prof Ethan Mollick",
        "ethanzuckerman.com" => "Ethan Zuckerman",
        "ethanzuckerman.com" => "Ethan Zuckerman",
        "www.ethicaleditor.com" => "Ethical Editor",
        "ethz.ch" => "ETH Zürich",
        "comsec.ethz.ch" => "ETH Zürich",
        "etienne.depar.is" => "Étienne Deparis",
        "etienne.pflieger.bzh" => "Étienne Pflieger",
        "etno.eu" => "ETNO",
        "www.etuc.org" => "ETUC",
        "eur-lex.europa.eu" => "EU",
        "europa.eu" => "EU",
        "www.eua.eu" => "EUA",
        "eand.co" => "Eudaimonia",
        "spaf.cerias.purdue.edu" => "Eugene H Spafford",
        "eugeneyan.com" => "Eugene Yan",
        "euobserver.com" => "EU Observer",
        "www.euractiv.com" => "Euractive",
        "www.eurasiareview.com" => "Eurasia Review",
        "2020.eurobsdcon.org" => "EuroBSDCon",
        "2021.eurobsdcon.org" => "EuroBSDCon",
        "2022.eurobsdcon.org" => "EuroBSDCon",
        "2023.eurobsdcon.org" => "EuroBSDCon",
        "2024.eurobsdcon.org" => "EuroBSDCon",
        "2025.eurobsdcon.org" => "EuroBSDCon",
        "www.eurogamer.net" => "EuroGamer",
        "www.euronews.com" => "EuroNews",
        "frontex.europa.eu" => "European Border And Coast Guard Agency",
        "commission.europa.eu" => "European Commission",
        "ec.europa.eu" => "European Commission",
        "digital-strategy.ec.europa.eu" => "European Commission",
        "www.consilium.europa.eu" => "European Council",
        "www.edpb.europa.eu" => "European Data Protection Board",
        "www.efsa.europa.eu" => "European Food Safety Authority",
        "hudoc.echr.coe.int" => "European Court of Human Rights",
        "www.eurofound.europa.eu" => "European Foundation for the Improvement of Living and Working Conditions",
        "europarl.europa.eu" => "European Parliament",
        "www.europarl.europa.eu" => "European Parliament",
        "www.epc.eu" => "European Policy Centre",
        "www.eso.org" => "European Southern Observatory",
        "www.berec.europa.eu" => "European Union",
        "data.consilium.europa.eu" => "European Council",
        "european-union.europa.eu" => "European Union",
        "www.europol.europa.eu" => "Europol",
        "www.euroweeklynews.com" => "Euro Weekly News",
        "evanhahn.com" => "Evan Hahn",
        "verdagon.dev" => "Evan Ovadia",
        "evanstonroundtable.com" => "Evanston RoundTable Media NFP",
        "eev.ee" => "Evelyn Woods",
        "www.standard.co.uk" => "Evening Standard UK",
        "evertpot.com" => "Evert Pot",
        "www.everylaststation.co.uk" => "Every Last Station",
        "everythingsmarthome.co.uk" => "Everything Smart Home",
        "evilmartians.com" => "Evil Martians",
        "tesk.page" => "TheEvilSkeleton",
        "evrone.com" => "Evrone GmbH",
        "www.eweek.com" => "EWeek",
        "ewontfix.com" => "EWONTFIX",
        "global-tipping-points.org" => "University of Exceter",
        "expertain.net" => "Expertain",
        "explainextended.com" => "Explain Extended",
        "www.exponential-e.com" => "Exponential-e Ltd",
        "research.exoticsilicon.com" => "Exotic Silicon",
        "exple.tive.org" => "Exple.Tive.Org",
        "explained-from-first-principles.com" => "Explained from First Principles",
        "www.explica.co" => "Explica",
        "explorersweb.com" => "Explorersweb",
        "www.exposedbycmd.org" => "Exposed By CMD",
        "www.express.co.uk" => "Express",
        "www.expressandstar.com" => "Express And Star",
        "www.expresspharma.in" => "Express Pharma",
        "floridapolitics.com" => "Extensive-Enterprises",
        "www.extremeelectronics.co.uk" => "Extreme Electronics",
        "www.extremetech.com" => "Extreme Tech",
        "beuke.org" => "Fabian Beuke",
        "fgiesen.wordpress.com" => "Fabian “ryg” Giesen",
        "fabiensanglard.net" => "Fabian Sanglard",
        "about.instagram.com" => "Facebook",
        "factmyth.com" => "Fact / Myth",
        "www.facultyfocus.com" => "Faculty Focus",
        "olano.dev" => "Facundo Olano",
        "re-factor.blogspot.com" => "Factor",
        "facts.net" => "FactsNet",
        "faineg.com" => "Faine Greenwood",
        "fair.org" => "FAIR",
        "www.fairobserver.com" => "Fair Observer",
        "www.fairtrials.org" => "Fair Trials International",
        "fair.work" => "Fair Work",
        "www.faithfreedom.org" => "Faith Freedom",
        "www.familyminded.com" => "FamilyMinded",
        "www.gamespot.com" => "Fandom Inc",
        "www.fao.org" => "FAO",
        "faroutmagazine.co.uk" => "Far Out Mag",
        "fs.blog" => "Farnam Street Media Inc",
        "road.cc" => "Farrelly Atkinson",
        "www.farsightsecurity.com" => "FarsightSecurity",
        "www.ficlaw.com" => "Faruki PLL",
        "sgp.fas.org" => "Federation of American Scientists",
        "fas.org" => "Federation of American Scientists",
        "uk.fashionnetwork.com" => "Fashion Network",
        "www.fastcompany.com" => "Fast Company",
        "www.fastly.com" => "Fastly",
        "www.fastmail.com" => "Fastmail",
        "www.fatherly.com" => "Fatherly",
        "f-droid.org" => "F-Droid",
        "www.ic3.gov" => "Federal Bureau of Investigation",
        "federalnewsnetwork.com" => "Federal News Network",
        "interiornewswire.com" => "Federal Newswire",
        "fcw.com" => "Government Media Executive Group LLC",
        "www.washingtontechnology.com" => "Government Media Executive Group LLC",
        "www.federaltimes.com" => "Federal Times",
        "consumer.ftc.gov" => "Federal Trade Commission",
        "www.ftc.gov" => "Federal Trade Commission",
        "irp.fas.org" => "Federation of American Scientists",
        "distro.f-91w.club" => "Fedizine",
        "darksi.de" => "Fedor Indutny",
        "fedoramagazine.org" => "Fedora Magazine",
        "www.feistyduck.com" => "Feisty Duck",
        "felixcrux.com" => "Felix Crux",
        "feldspaten.org" => "Felix Feldspaten",
        "www.feltpresence.com" => "Felt Presence LLC",
        "felix-knorr.net" => "Knorr",
        "krausefx.com" => "Felix Krause",
        "femtejuli.se" => "Femte Juli",
        "borretti.me" => "Fernando Borretti",
        "ferrous-systems.com" => "Ferrous Systems",
        "www.faylawfirm.com" => "FFA",
        "fiatjaf.com" => "Fiatjaf",
        "fidoalliance.org" => "FIDO Alliance",
        "www.fiercepharma.com" => "Fierce Pharma",
        "www.fifthdomain.com" => "Fifth Domain",
        "figbert.com" => "Figbert",
        "www.fightforthefuture.org" => "Fight For The Future",
        "0x46.net" => "Filip Borkiewicz",
        "filipe.kiss.ink" => "Filipe Kiss",
        "words.filippo.io" => "Filippo Valsorda",
        "filmdaily.co" => "Film Daily",
        "www.financialexpress.com" => "Financial Express",
        "today.thefinancialexpress.com.bd" => "Financial Express, Bangladesh",
        "financialpost.com" => "Financial Post",
        "www.fsb.org" => "Financial Stability Board",
        "www.financialstandard.com.au" => "Financial Standard",
        "www.ft.com" => "Financial Times",
        "supreme.findlaw.com" => "Find Law",
        "www.finextra.com" => "Finextra Research",
        "www.kansalliskirjasto.fi" => "The National Library of Finland",
        "um.fi" => "Finland",
        "valtioneuvosto.fi" => "Finland",
        "www.presidentti.fi" => "Finland",
        "www.ymparisto.fi" => "Finland",
        "tulli.fi" => "Finnish Customs Agency",
        "www.traficom.fi" => "Finnish Transport and Communications Agency",
        "blog.finnix.org" => "Finnix",
        "finnstats.com" => "Finnstats",
        "fintechzoom.com" => "FinTech Zoom",
        "www.fireeye.com" => "FireEye",
        "www.fsmatters.com" => "Fire Saftey Matters",
        "firstmonday.org" => "First Monday",
        "www.firstpost.com" => "Firstpost",
        "www.fr.com" => "Fish & Richardson",
        "fishshell.com" => "Fish Shell",
        "flamedfury.com" => "Flamed Fury",
        "www.flatpanelshd.com" => "FlatpanelsHD",
        "fleetstack.io" => "Fleetstack",
        "theflintcouriernews.com" => "The Flint Courier News",
        "fh4ntke.medium.com" => "Florian Hantke",
        "floridanewstimes.com" => "Florida",
        "jaxtrib.org" => "Florida",
        "www.floridabulldog.org" => "Florida Bulldog",
        "blog.floydhub.com" => "Floyd Hub",
        "fly.io" => "Fly",
        "www.flyingpenguin.com" => "Flyngpenguin",
        "www.surfacemag.com" => "FMG Inc",
        "www.freemalaysiatoday.com" => "FMT",
        "www.cfoi.org.uk" => "FOI",
        "www.followthecrypto.org" => "Follow The Crypto",
        "www.ftm.eu" => "Follow The Money",
        "blog.fontawesome.com" => "Font Awesome",
        "www.foodandwine.com" => "Food & Wine",
        "www.foodnotlawns.com" => "Food Not Lawns",
        "foodtank.com" => "FoodTank",
        "infosec-jobs.com" => "Foorilla LLC",
        "forwomen.scot" => "For Women Scotland",
        "www.forbes.com" => "Forbes",
        "www.forbrukerradet.no" => "Forbrukerrådet",
        "www.foreignaffairs.com" => "Foreign Affairs",
        "foreignpolicy.com" => "Foreign Policy",
        "forensicnews.net" => "Forensic News",
        "www.forever-wars.com" => "Forever Wars",
        "foreverwars.substack.com" => "Forever Wars",
        "forgefriends.org" => "Forge Friends",
        "forum.forgefriends.org" => "Forge Friends",
        "forgejo.org" => "Forgejo",
        "newsletter.goodtechthings.com" => "Forrest Brazeal",
        "www.fortmcmurraytoday.com" => "Fort McMurray Today",
        "www.fortmorgantimes.com" => "The Fort Morgan Times",
        "fortran-lang.org" => "Fortran Lang",
        "forward.com" => "Forward",
        "archive.fosdem.org" => "FOSDEM",
        "fosdem.org" => "FOSDEM",
        "blog.fossasia.org" => "FOSSASIA",
        "fossbytes.com" => "FOSSBytes",
        "fossi-foundation.org" => "FOSSi Foundation",
        "foss-north.se" => "FOSS North",
        "fosspost.org" => "FOSS Post",
        "www.fdd.org" => "Foundation for Defense of Democracies",
        "fee.org" => "Foundation for Economic Education",
        "ffii.org" => "Foundation for a Free Information Infrastructure",
        "www.fourmilab.ch" => "Fourmilab",
        "location.foursquare.com" => "Foursquare",
        "www.foxglove.org.uk" => "Foxglove",
        "freedom.press" => "FPF",
        "www.thefpsreview.com" => "FPS Review",
        "cyber.gouv.fr" => "France",
        "www.tribunal-de-paris.justice.fr" => "France",
        "www.diplomatie.gouv.fr" => "France",
        "observers.france24.com" => "France24",
        "www.france24.com" => "France24",
        "iamfran.com" => "Francesco",
        "ariis.it" => "Francesco Ariis",
        "mazzo.li" => "Francesco Mazzoli",
        "webtechie.be" => "Frank Delporte",
        "eponymouspickle.blogspot.com" => "Franz Dill",
        "www.franziskuskiefer.de" => "Franziskus Kiefer",
        "frankmeeuwsen.com" => "Frank Meeuwsen",
        "www.frc.org" => "FRC",
        "freakingrectangle.wordpress.com" => "Freaking Rectangle",
        "www.cambus.net" => "Frederic Cambus",
        "blog.fredrb.com" => "Frederico Bittencourt",
        "frederik-braun.com" => "Frederik Braun",
        "frederikbraun.de" => "Frederik Braun",
        "ferd.ca" => "Fred Herbert",
        "madhadron.com" => "Frederick J Ross",
        "www.thefp.com" => "Substack Inc",
        "www.freerangekids.com" => "Free-Range Kids",
        "freeourfeeds.com" => "Free Our Feeds",
        "cgit.freebsd.org" => "FreeBSD",
        "docs.freebsd.org" => "FreeBSD",
        "freebsdfoundation.org" => "FreeBSD",
        "kernelnomicon.org" => "FreeBSD",
        "lists.freebsd.org" => "FreeBSD",
        "reviews.freebsd.org" => "FreeBSD",
        "wiki.freebsd.org" => "FreeBSD",
        "www.freebsdfoundation.org" => "FreeBSD",
        "www.freebsd.org" => "FreeBSD",
        "wiki.lazarus.freepascal.org" => "Free Pascal",
        "www.freecodecamp.org" => "freeCodeCamp",
        "ffrf.org" => "Freedom From Religion Foundation",
        "freedomhouse.org" => "Freedom House",
        "www.freedomonthenet.org" => "Freedom House",
        "freesharing.eu" => "Freedom To Share",
        "freedom-to-tinker.com" => "Freedom To Tinker",
        "freem-blog.coherent-logic.com" => "FreeM",
        "freemarketdaily.com" => "Freemarket Daily",
        "www.freepress.net" => "Free Press",
        "www.freepress.net" => "Free Press",
        "www.freepressjournal.in" => "Free Press Journal",
        "magazine.fsf.org" => "Free Software Foundation",
        "www.defectivebydesign.org" => "Free Software Foundation",
        "bigthink.com" => "Freethink Media Inc",
        "www.cs1.tf.fau.de" => "Friedrich-Alexander-Universität",
        "fritzenlab.net" => "FritzenLab Electronics",
        "french75.net" => "French75",
        "news.cnrs.fr" => "French National Center for Scientific Research",
        "www.fresnobee.com" => "Fresno Bee",
        "blog.afoolishmanifesto.com" => "fREW Schmidt",
        "friendlyatheist.patheos.com" => "Friendly Atheist",
        "friendly-router.org" => "Friendly Router",
        "foe.org" => "Friends of Earth",
        "frontendmasters.com" => "Frontend Masters",
        "frontiergroup.org" => "Frontier Group",
        "www.frontiersin.org" => "Frontiers",
        "frontpageafricaonline.com" => "Front Page Africa",
        "www.frontpagemag.com" => "Frontpage Magazine",
        "www.fsdaily.com" => "FS Daily",
        "labs.f-secure.com" => "FSecure",
        "my.fsf.org" => "FSF",
        "www.fsf.org" => "FSF",
        "fudosecurity.com" => "Fudo Security",
        "www.fudzilla.com" => "Fudzilla",
        "fullcirclemagazine.org" => "Full Circle Magazine",
        "fullfact.org" => "Full Fact",
        "patternsinfp.wordpress.com" => "Functional Programming",
        "functionalsoftware.se" => "Functional Software Stockholm AB",
        "fundingthecommons.io" => "Funding the Commons",
        "www.furkantokac.com" => "Furkan Tokaç",
        "futo.org" => "FUTO",
        "www.futurecar.com" => "Future Car",
        "artificialintelligenceact.eu" => "Future of Life Institute",
        "www.mixonline.com" => "Future PLC",
        "www.t3.com" => "Future Publishing Limited",
        "www.loudersound.com" => "Future Publishing Limited",
        "www.theweek.co.uk" => "Future Publishing Limited",
        "futurism.com" => "Futurism",
        "g8rwg.uk" => "G8RWG",
        "radio.g4hsk.co.uk" => "G8GKA",
        "news.gab.com" => "Gab",
        "gabevenberg.com" => "Gabe Venberg",
        "gabz.blog" => "Gabriel",
        "www.gabriel.urdhr.fr" => "Gabriel Corona",
        "gabrielsieben.tech" => "Gabriel Sieben",
        "gabrielsimmer.com" => "Gabriel Simmer",
        "www.gadgetsnow.com" => "Gadgets Now",
        "gadgettendency.com" => "Gadget Tendency",
        "www.gainesvilletimes.com" => "Gainesville Times",
        "www.galacticstudios.org" => "Bob Alexander",
        "ikrima.dev" => "Gamedev Guide",
        "newsletter.gamediscover.co" => "Game Discover Co",
        "www.gameinformer.com" => "Game Informer",
        "game-news24.com" => "Game-News24",
        "gamerant.com" => "Game Rant",
        "gameworldobserver.com" => "Game World Observer",
        "gameoftrees.org" => "Game Of Trees",
        "www.gameoftrees.org" => "Game Of Trees",
        "www.thegamer.com" => "The Gamer",
        "www.thegamefox.net" => "The Game Fox",
        "www.rockpapershotgun.com" => "Gamer Network Limited",
        "www.gamesindustry.biz" => "Games",
        "www.gamesradar.com" => "Future US Inc",
        "www.gamingbible.co.uk" => "GAMINGbible",
        "www.gamingonlinux.com" => "GamingOnLinux",
        "eu.blueridgenow.com" => "Gannett",
        "eu.buckscountycouriertimes.com" => "Gannett",
        "eu.caller.com" => "Gannett",
        "eu.cincinnati.com" => "Gannett",
        "eu.commercialappeal.com" => "Gannett",
        "eu.delawareonline.com" => "Gannett",
        "eu.desertsun.com" => "Gannett",
        "eu.fayobserver.com" => "Gannett",
        "eu.galesburg.com" => "Gannett",
        "eu.hollandsentinel.com" => "Gannett",
        "eu.jacksonville.com" => "Gannett",
        "eu.jsonline.com" => "Gannett",
        "eu.lcsun-news.com" => "Gannett",
        "eu.news-journalonline.com" => "Gannett",
        "eu.njherald.com" => "Gannett",
        "eu.oklahoman.com" => "Gannett",
        "eu.petoskeynews.com" => "Gannett",
        "eu.providencejournal.com" => "Gannett",
        "eu.southcoasttoday.com" => "Gannett",
        "eu.statesman.com" => "Gannett",
        "eu.vcstar.com" => "Gannett",
        "www.irvinetimes.com" => "Gannet",
        "detroit.cbslocal.com" => "Gannett",
        "eu.app.com" => "Gannett",
        "eu.augustachronicle.com" => "Gannett",
        "eu.azcentral.com" => "Gannett",
        "eu.clarionledger.com" => "Gannett",
        "eu.courier-journal.com" => "Gannett",
        "eu.democratandchronicle.com" => "Gannett",
        "eu.desmoinesregister.com" => "Gannett",
        "eu.freep.com" => "Gannett",
        "eu.indystar.com" => "Gannett",
        "eu.knoxnews.com" => "Gannett",
        "eu.lansingstatejournal.com" => "Gannett",
        "eu.northjersey.com" => "Gannett",
        "eu.tallahassee.com" => "Gannett",
        "eu.tennessean.com" => "Gannett",
        "eu.theledger.com" => "Gannett",
        "eu.usatoday.com" => "Gannett",
        "www.freep.com" => "Gannett",
        "www.usatoday.com" => "Gannett",
        "www.garbageday.email" => "Garbage Day",
        "garrit.xyz" => "Garrit Franke",
        "garyfouse.blogspot.com" => "Gary Fouse",
        "cuddly-octo-palm-tree.com" => "Gary Verhaegen",
        "gatesofvienna.net" => "Gates Of Vienna",
        "www.gatestoneinstitute.org" => "Gatestone Institute",
        "www.thegatewaypundit.com" => "The Gateway Pundit",
        "computoid.com" => "Gavin Hayes",
        "gavinhoward.com" => "Gavin Howard",
        "www.wgbh.org" => "GBH",
        "greenchristian.org.uk" => "GC",
        "gcc.gnu.org" => "GCC",
        "connect.geant.org" => "GÉANT",
        "www.gearnews.com" => "Remise 3 Medienservice Agentur GmbH",
        "www.geeklan.co.uk" => "Geek LAN",
        "www.geeksforgeeks.org" => "Geeks For Geeks",
        "www.geekwire.com" => "GeekWire",
        "www.geeky-gadgets.com" => "Geeky Gadgets",
        "askmeaboutlinux.com" => "Geetu R Vaswani",
        "gellerreport.com" => "Geller Report",
        "geminiprotocol.net" => "Project Gemini",
        "geminiquickst.art" => "Gemini",
        "portal.mozz.us" => "Gemini",
        "builders.genagorlin.com" => "Dr Gena Gorlin",
        "genodians.org" => "Genode Operating System",
        "blogs.gentoo.org" => "Gentoo",
        "forums.gentoo.org" => "Gentoo",
        "www.gentoo.org" => "Gentoo",
        "www.getlamp.com" => "Get Lamp",
        "app.engage.gettyimages.com" => "Getty Images",
        "asylum.madhouse-project.org" => "Gergely Nagy",
        "chronicles.mad-scientist.club" => "Gergely Nagy",
        "www.geoffchappell.com" => "Geoff Chappell",
        "geoffgraham.me" => "Geoff Graham",
        "ghuntley.com" => "Geoff Huntley",
        "www.potaroo.net" => "Geoff Huston",
        "blog.sylver.dev" => "Geoffrey Copin",
        "www.fultoncountyga.gov" => "Fulton County, GA, USA",
        "www.epistem.ink" => "George",
        "blog.cerebralab.com" => "George Hosu",
        "cerebralab.com" => "George Hosu",
        "shapeshed.com" => "George Ornbo",
        "americandragnet.org" => "Georgetown Law",
        "www.geospatialworld.net" => "Geospatial Media and Communications",
        "www.germanvelasco.com" => "Germán Velasco",
        "www.berliner-zeitung.de" => "Germany",
        "www.iamexpat.de" => "Germany",
        "www.wien.info" => "Germany",
        "www.gtai.de" => "Germany Trade & Invest",
        "geshan.com.np" => "Geshan",
        "stealthoptional.com" => "GFinity",
        "www.greenfinanceplatform.org" => "GFP",
        "www.ghacks.net" => "Ghacks",
        "newsghana.com.gh" => "Ghana",
        "www.ghanaweb.com" => "Ghana",
        "www.ghananews.co.uk" => "Ghana",
        "ghanasoccernet.com" => "Ghana Soccer Net",
        "ghostbsd.org" => "Ghost BSD",
        "www.ghostbsd.org" => "Ghost BSD",
        "ghost.org" => "Ghost Foundation",
        "ghostinfluence.com" => "Ghost Influence",
        "giansegato.com" => "Gian Segato",
        "gigaom.com" => "GigaOm",
        "gigazine.net" => "GigaZine",
        "gigi.nullneuron.net" => "Gigi Labs",
        "gilest.org" => "Giles Turnbull",
        "castel.dev" => "Gilles Castel",
        "poolp.org" => "Gilles Chehade",
        "www.poolp.org" => "Gilles Chehade",
        "gillettnews.com" => "Gillett News",
        "gineersnow.com" => "GineersNow",
        "gcollazo.com" => "Giovanni Collazo",
        "engineering.giphy.com" => "GIPHY",
        "blog.gitguardian.com" => "Git Guardian",
        "legacy.gitbook.com" => "GitBook",
        "www.gitbook.com" => "GitBook",
        "blog.gitea.io" => "Gitea",
        "about.gitlab.com" => "GitLab",
        "docs.gitlab.com" => "GitLab",
        "framagit.org" => "GitLab",
        "gitlab.com" => "GitLab",
        "www.gizchina.com" => "Giz China",
        "www.gizmochina.com" => "Gizmo China",
        "earther.gizmodo.com" => "Gizmodo",
        "www.gizmodo.com.au" => "Gizmodo Australia",
        "gizmodo.com" => "Gizmodo",
        "io9.gizmodo.com" => "Gizmodo",
        "gizmoposts24.com" => "Gizmo Posts 24",
        "www.glasgowtimes.co.uk" => "Glasgow Times",
        "glaubercosta-11125.medium.com" => "Glauber Costa",
        "gleam.run" => "Gleam",
        "sportsnation.org.uk" => "Glencroft Ltd",
        "can-mex-usa-sec.org" => "Global Affairs Canada",
        "user-agent.globalcode.info" => "Global Code",
        "www.globalconstructionreview.com" => "Global Construction Review",
        "ged.globalencryption.org" => "Global Encryption Day",
        "www.footprintnetwork.org" => "Global Footprint Network",
        "globalnews.ca" => "Global News CA",
        "theglobalscholars.com" => "Global Scholars",
        "www.globalsign.com" => "GlobalSign",
        "www.globenewswire.com" => "Globe Newswire",
        "gluer.org" => "Victor Freire",
        "moodysbnn.blogspot.com" => "Glyn Moody",
        "opendotdotdot.blogspot.com" => "Glyn Moody",
        "blog.glyph.im" => "Glyph",
        "glyph.twistedmatrix.com" => "Glyph Lefkowitz",
        "www.gnome.org" => "Gnome",
        "guix.gnu.org" => "GNU",
        "lists.gnu.org" => "GNU",
        "lists.nongnu.org" => "GNU",
        "savannah.gnu.org" => "GNU",
        "www.gnu.org" => "GNU",
        "dev.gnupg.org" => "GnuPG",
        "lists.gnupg.org" => "GnuPG",
        "wiki.gnupg.org" => "GnuPG",
        "www.gocertify.com" => "Go Certify",
        "www.gofundme.com" => "GoFundMe",
        "goinglinux.com" => "Going Linux",
        "godotengine.org" => "Godot Engine",
        "www.goldderby.com" => "Gold Derby",
        "jalopnik.com" => "GO Media",
        "jezebel.com" => "GO Media",
        "kotaku.com" => "GO Media",
        "lifehacker.com" => "GO Media",
        "theslot.jezebel.com" => "GO Media",
        "thetakeout.com" => "GO Media",
        "www.avclub.com" => "GO Media",
        "www.theroot.com" => "GO Media",
        "goncalomb.com" => "Gonçalo MB",
        "blog.ovalerio.net" => "Gonçalo Valério",
        "x61.sh" => "GonzaloR",
        "www.good.is" => "Good",
        "goodereader.com" => "Good E Reader",
        "goodmenproject.com" => "Good Men Project",
        "www.goodolddays.net" => "Good Old Days",
        "goodresearch.dev" => "The Good Research Code Handbook",
        "goodness-exchange.com" => "Goodness Exchange",
        "www.goodwinlaw.com" => "Goodwin Law",
        "ai.google" => "Google",
        "blog.chromium.org" => "Google",
        "cloud.google.com" => "Google",
        "blog.google" => "Google",
        "chromereleases.googleblog.com" => "Google",
        "developers.googleblog.com" => "Google",
        "fuchsia.dev" => "Google",
        "googleprojectzero.blogspot.com" => "Google",
        "opensource.googleblog.com" => "Google",
        "security.googleblog.com" => "Google",
        "webmasters.googleblog.com" => "Google",
        "notes.kateva.org" => "Gordon's Notes",
        "blog.shotwell.ca" => "Gordon Shotwell",
        "gothamist.com" => "Gothamist",
        "www.governmentattic.org" => "Government Attic",
        "governmentciomedia.com" => "Government CIO Magazine",
        "www.governmentcomputing.com" => "Government Computing",
        "www.govexec.com" => "Government Executive",
        "www.cityandstateny.com" => "Government Media Executive Group LLC",
        "www.govtech.com" => "Government Technology",
        "www.govinfosecurity.com" => "Gov Info Sec News",
        "www.gq.com" => "GQ",
        "www.gq-magazine.co.uk" => "GQ",
        "thegradient.pub" => "The Gradient",
        "gqrx.dk" => "Gqrx",
        "grafana.com" => "Grafana",
        "grain.org" => "GRAIN",
        "graphika.com" => "Graphika",
        "grahamcluley.com" => "Graham Cluley",
        "www.grahamcluley.com" => "Graham Cluley",
        "www.grandforksherald.com" => "Grand Forks Herald",
        "grantslatton.com" => "Grant Slatton",
        "granta.com" => "Granta",
        "www.hawaiinewsnow.com" => "Gray Local Media",
        "www.kkco11news.com" => "Gray Local Media",
        "www.atlantanewsfirst.com" => "Gray Media Group",
        "www.dakotanewsnow.com" => "Gray Media Group",
        "www.kktv.com" => "Gray Media Group",
        "www.nbc12.com" => "Gray Media Group",
        "www.witn.com" => "Gray Media Group",
        "www.wect.com" => "Gray Media Group",
        "www.weau.com" => "Gray Media Group",
        "www.wsfa.com" => "Gray Media Group",
        "www.wtvy.com" => "Gray Media Group",
        "www.wvva.com" => "Gray Media Group",
        "www.hackread.com" => "Gray Dot Media Group",
        "greatlakesecho.org" => "Great Lakes Echo",
        "www.ekathimerini.com" => "Greece",
        "greekcitytimes.com" => "Greek City Times",
        "greekreporter.com" => "Greek Reporter",
        "www.greenbiz.com" => "Green Biz",
        "www.greenmatters.com" => "Green Matters",
        "greenparty.org.uk" => "Green Party UK",
        "www.greenparty.org.uk" => "Green Party UK",
        "greenteapress.com" => "Green Tea Press",
        "www.greenpeace.org" => "Greenpeace",
        "www.greenqueen.com.hk" => "GreenQueen",
        "www.greens-efa.eu" => "The Greens / EFA",
        "gpanders.com" => "Gregory Anders",
        "gregoryhammond.ca" => "Gregory Hammond",
        "micro.gregorypittman.net" => "Gregory Pittman",
        "www.igregious.com" => "Greg Fawcett",
        "gregmorris.co.uk" => "Greg Morris",
        "www.gr36.com" => "Greg Morris",
        "www.gkogan.co" => "Greg Kogan",
        "games.greggman.com" => "Gregg Tavares",
        "greycoder.com" => "GreyCoder",
        "www.gresearch.co.uk" => "G Research",
        "gdprhub.eu" => "GDPRhub",
        "gridlochgames.itch.io" => "Gridloch",
        "news.griffith.edu.au" => "Griffith University",
        "www.grimsbytelegraph.co.uk" => "Grimsby UK",
        "grist.org" => "Grist Magazine Inc",
        "www.groklaw.net" => "Groklaw",
        "curiouscoding.nl" => "Groot Koerkamp",
        "data.gsmaintelligence.com" => "GSMA Advisory Services Ltd",
        "www.gsmarena.com" => "GSM Arena",
        "www.goodthingsguy.com" => "GTG",
        "guardian.ng" => "Guardian",
        "www.errno.fr" => "Guillaume Quéré",
        "www.garron.blog" => "Guillermo Garron",
        "guillermolatorre.com" => "Guillermo Latorre",
        "www.guinnessworldrecords.com" => "Guiness World Records",
        "gulfnews.com" => "Gulf News",
        "www.gulftoday.ae" => "GulfToday",
        "blog.unhu.fr" => "Gunhu",
        "gunnar.se" => "Gunnar",
        "gwolf.org" => "Gunnar Wolf",
        "gerikson.com" => "Gustaf Erikson",
        "www.gutenberg.org" => "Project Gutenberg",
        "www.guylawrence.com.au" => "Guy Lawrence",
        "www.lockedinspace.com" => "Gvid",
        "www.how2shout.com" => "H2S Media",
        "www.h2-view.com" => "H2 View",
        "h3artbl33d.nl" => "H3artbl33d",
        "www.haaretz.com" => "Haaretz",
        "www.chamline.net" => "Habib Cham",
        "habr.com" => "Habr",
        "hack.org" => "Hack",
        "hackeducation.com" => "Hack Education",
        "hackaday.com" => "Hackaday",
        "hackaday.io" => "Hackaday",
        "hacked.com" => "Hacked",
        "www.hackerfactor.com" => "HackerFactor",
        "thehackernews.com" => "Hacker News",
        "hackernoon.com" => "Hacker Noon",
        "www.hackernoon.com" => "Hacker Noon",
        "www.hackster.io" => "Hackster",
        "isometricleaves.wordpress.com" => "HaikuOS",
        "www.haiku-os.org" => "HaikuOS",
        "hakaimagazine.com" => "Hakai Magazine",
        "hakibenita.com" => "Haki Benita",
        "www.wiumlie.no" => "Håkon Wium Lie",
        "blog.hboeck.de" => "Hanno Boeck",
        "hamel.dev" => "Hamel Husain",
        "probuildermag.co.uk" => "Hamerville Media Group",
        "www.hamiltonnolan.com" => "Hamilton Nolan",
        "hannuhartikainen.fi" => "Hannu Hartikainen",
        "humanrightsdefenders.blog" => "Hans Thoolen",
        "www.hanshq.net" => "Hans Wennborg",
        "www.drheap.nl" => "Hans-Dieter Hiep",
        "www.hansdieterhiep.nl" => "Hans-Dieter Hiep",
        "happymag.tv" => "Happy Mag",
        "apachelog.wordpress.com" => "Harald Sitter",
        "kde.haraldsitter.eu" => "Harald Sitter",
        "www.hardwarezone.com.sg" => "The Hardware Zone",
        "hardenedbsd.org" => "HardenedBSD",
        "harelang.org" => "The Hare Programming Language",
        "theevilskeleton.gitlab.io" => "Hari Rana",
        "harishpillay.com" => "Harish Pillay",
        "www.harpersbazaar.com" => "Harpers Baazar",
        "harpers.org" => "Harpers Magazine",
        "harrisonsand.com" => "Harrison Sand",
        "harrycresswell.com" => "Harry Cresswell",
        "hmarr.com" => "Harry Marr",
        "www.harsh17.in" => "Harshvardhan",
        "woodpecker.com" => "Harvey Reid",
        "learnyouahaskell.com" => "Learn You a Haskell for Great Good",
        "blog.haskell.org" => "Haskell",
        "discourse.haskell.org" => "Haskell",
        "www.haskellforall.com" => "Haskell For All",
        "havce.it" => "Havce CTF",
        "challahscript.com" => "Hazel Bachrach",
        "hrussman.neocities.org" => "Hazel Russman",
        "hazelweakly.me" => "Hazel Weakly",
        "headtopics.com" => "Head Topics",
        "www.env-health.org" => "HEAL",
        "www.healthaffairs.org" => "Health Affairs",
        "www.healthdatamanagement.com" => "Health Data Managment",
        "h-isac.org" => "Health-ISAC",
        "www.healthnewsreview.org" => "Health News Review",
        "www.healthcarefinancenews.com" => "Healthcare Finance",
        "www.healthcareitnews.com" => "Healthcare IT News",
        "www.healthline.com" => "Healthline Media",
        "www.medicalnewstoday.com" => "Healthline Media",
        "www.hearingreview.com" => "Hearing Review",
        "www.roadandtrack.com" => "Hearst Digital Media, Inc",
        "www.bicycling.com" => "Hearst Magazine Media, Inc",
        "www.elle.com" => "Hearst Magazine Media, Inc",
        "www.womenshealthmag.com" => "Hearst Magazine Media, Inc",
        "www.expressnews.com" => "Hearst Communications",
        "www.timesunion.com" => "Hearst Communications",
        "heathermeeker.com" => "Heather J Meeker",
        "heavy.com" => "Heavy",
        "heimdalsecurity.com" => "Heimdal Security",
        "blog.tmm.cx" => "Hein-Pieter van Braam",
        "www.heise.de" => "Heise",
        "www.h-online.com" => "Heise",
        "heliomass.com" => "Heliomass",
        "hellgatenyc.com" => "Hell Gate NYC",
        "hellas.postsen.com" => "Hellas Posts English",
        "www.hellenicshippingnews.com" => "Hellenic Shipping News",
        "www.helpnetsecurity.com" => "Help Net Security",
        "www.helpguide.org" => "HelpGuide.org Intl",
        "old.hiit.fi" => "Helsinki Institute for Information Technology",
        "helda.helsinki.fi" => "The University of Helsinki",
        "www.cs.helsinki.fi" => "The University of Helsinki",
        "www.helsinkitimes.fi" => "Helsinki Times",
        "hengaw.net" => "Hengaw Organization for Human Rights Hengaw Organization for Human Rights",
        "bergie.iki.fi" => "Henri Bergius",
        "hsivonen.fi" => "Henri Sivonen",
        "hacdias.com" => "Henrique Dias",
        "www.henrikkarlsson.xyz" => "Henrik Karlsson",
        "henrikwarne.com" => "Henrik Warne",
        "www.hercampus.com" => "Her Campus Media LLC",
        "www.heraldmalaysia.com" => "Herald Malaysia",
        "www.heraldsun.com.au" => "Herald Sun",
        "www.dailysignal.com" => "Heritage Foundation",
        "ounapuu.ee" => "Herman Õunapuu",
        "herrbischoff.com" => "Herr Bischoff",
        "hexus.net" => "Hexus",
        "briefs.video" => "Heydon Pickering",
        "heydonworks.com" => "Heydon Pickering",
        "thehftguy.com" => "HFT",
        "www.healthit.gov" => "HHS",
        "hicks.design" => "Hicks Design",
        "hidde.blog" => "Hidde de Vries",
        "www.hcn.org" => "High Country News",
        "www.highnorthnews.com" => "High North News",
        "hiiraan.com" => "Hiiraan Online",
        "hilaryburrage.com" => "Hilary Burrage",
        "www.hillelwayne.com" => "Hillel Wayne",
        "hillreporter.com" => "Hill Reporter",
        "hindupost.in" => "Hindu Post",
        "thehindustangazette.com" => "The Hindustan Gazette",
        "tech.hindustantimes.com" => "Hindustan Times",
        "www.hindustantimes.com" => "Hindustan Times",
        "www.hipaajournal.com" => "HIPAA",
        "www.h-i-r.net" => "HiR",
        "hisham.hm" => "Hisham",
        "www.historyonthenet.com" => "History",
        "www.history.com" => "History AE",
        "history-computer.com" => "History Computer",
        "unixhist.crys.site" => "History of UNIX",
        "thehistoryoftheweb.com" => "The History of the Web",
        "www.hivemq.com" => "HiveMQ Gmbh",
        "security.humanativaspa.it" => "HN",
        "www.hollywoodreporter.com" => "Hollywood Reporter",
        "www.home-assistant.io" => "Home Assistant",
        "home-assistant-guide.com" => "Home Assistant Guide",
        "homehack.nl" => "Home Hack",
        "www.hoover.org" => "The Hoover Instituion",
        "honeyryderchuck.gitlab.io" => "HoneyryderChuck",
        "honeytreelabs.com" => "HoneytreeLabs",
        "www.thestandard.com.hk" => "The Standard, Hong Kong",
        "hongkongfp.com" => "Hong Kong Free Press",
        "www.hongkongfp.com" => "Hong Kong Free Press",
        "scheduler.hope.net" => "HOPE",
        "hopeinsource.com" => "Hope in Source",
        "hopkintonindependent.com" => "Hopkinton Independent",
        "zerokspot.com" => "Horst Gutmann",
        "backreaction.blogspot.com" => "Sabine Hossenfelder",
        "admin.hostpoint.ch" => "Hostpoint",
        "www.hotcars.com" => "Valnet Inc",
        "hothardware.com" => "Hot Hardware",
        "www.hothardware.com" => "Hot Hardware",
        "www.hotrod.com" => "Hot Rod LLC",
        "thehouseofmoth.com" => "The House of Moth",
        "uh.edu" => "University of Houston",
        "www.houstonchronicle.com" => "Houston Chronicle",
        "www.houstonpublicmedia.org" => "Houston Public Media",
        "eclecticlight.co" => "Howard Oakley",
        "howlround.com" => "Howl Round",
        "www.howtoforge.com" => "HowTo Forge",
        "www.howtogeek.com" => "HowTo Geek",
        "www.hpl.hp.com" => "HP",
        "www.hpcwire.com" => "HPC Wire",
        "www.hrw.org" => "HRW",
        "www.hse.ie" => "HSE",
        "www.livemint.com" => "HT Digital Streams Ltd",
        "html-first.com" => "HTML First",
        "htmlforpeople.com" => "HTML For People",
        "www.html-tidy.org" => "HTML Tidy",
        "httptoolkit.com" => "HTTP Toolkit",
        "httptoolkit.tech" => "HTTP Toolkit",
        "blog.huadeity.com" => "HuaDeity",
        "www.tnhh.net" => "Huan Truong",
        "consumer.huawei.com" => "Huawei",
        "thehustle.co" => "The HubSpot Inc",
        "www.kob.com" => "Hubbard Broadcasting",
        "www.wdio.com" => "Hubbard Broadcasting",
        "www.whec.com" => "Hubbard Broadcasting",
        "www.hudson.org" => "Hudson Institute",
        "whynothugo.nl" => "Hugo Osvaldo Barrera",
        "www.hr.com" => "Human Resources Social Network",
        "humanists.international" => "Humanists International",
        "huggingface.co" => "Hugging Face, Inc",
        "www.hughrundle.net" => "Hugh Rundle",
        "blog.izissise.net" => "Hugues",
        "www.hungarianconservative.com" => "Hungarian Conservative",
        "insighthungary.444.hu" => "Insight Hungary",
        "telex.hu" => "Telex (Hungary)",
        "svg-tutorial.com" => "Hunor Márton Borbély",
        "www.huntonprivacyblog.com" => "Hunton Andrews Kurth",
        "www.huntress.com" => "Huntress",
        "html.com" => "HTML.com",
        "www.hurriyetdailynews.com" => "Hürriyet Daily News",
        "lazybear.io" => "Hyde Stevenson",
        "hyperallergic.com" => "HyperAllergic",
        "www.hyperbola.info" => "Hyperbola",
        "www.recall.ai" => "Hyperdoc Inc",
        "talk.hyvor.com" => "Hyvor Talk",
        "www.iafrikan.com" => "iAfrikan",
        "www.insideradvantagegeorgia.com" => "IAG",
        "technovia.co.uk" => "Ian Betteridge",
        "ianbetteridge.com" => "Ian Betteridge",
        "idallen.com" => "Ian D Allen",
        "ianthehenry.com" => "Ian Henry",
        "iapp.org" => "IAPP",
        "www.iatp.org" => "IATP",
        "www.ibiblio.org" => "Ibiblio",
        "securityintelligence.com" => "IBM",
        "developer.ibm.com" => "IBM Developer",
        "www.ibtimes.com.au" => "IBT Media",
        "www.icann.org" => "ICANN",
        "www.persecution.org" => "ICC",
        "www.icij.org" => "ICIJ",
        "grapevine.is" => "Iceland",
        "www.icirnigeria.org" => "ICIR",
        "www.indcatholicnews.com" => "ICN",
        "blog.iconfactory.com" => "Iconfactory",
        "ico.org.uk" => "ICOUK",
        "icrowdnewswire.com" => "iCrowdNewswire",
        "idroot.us" => "ID Root",
        "www.darksky.org" => "IDA",
        "www.idemia.com" => "IDEMIA France SAS",
        "idahocapitalsun.com" => "Idaho Capital Sun",
        "inl.gov" => "Idaho National Laboratory",
        "identicalsoftware.com" => "Identical Games",
        "www.channelasia.tech" => "IDG",
        "www.cio.com" => "IDG Communications Inc",
        "www.idginsiderpro.com" => "IDG",
        "www.pcworld.idg.com.au" => "IDG",
        "www.reseller.co.nz" => "IDG",
        "idiomdrottning.org" => "Idiomdrottning",
        "www.idiomdrottning.org" => "Idiomdrottning",
        "idlewords.com" => "Idle Words",
        "www.idownloadblog.com" => "iDownloadBlog",
        "idrw.org" => "IDRW",
        "www.iea.org" => "IEA",
        "spectrum.ieee.org" => "IEEE",
        "smartgrid.ieee.org" => "IEEE",
        "datatracker.ietf.org" => "IETF",
        "mailarchive.ietf.org" => "IETF",
        "tools.ietf.org" => "IETF",
        "ifex.org" => "IFEX",
        "www.ifj.org" => "IFJ",
        "iflas.blogspot.com" => "IFLAS",
        "www.iflscience.com" => "IFLS",
        "ifstudies.org" => "IFS",
        "www.ign.com" => "IGN",
        "blog.ignaciobrasca.com" => "Ignacio Brasca",
        "discourse.igniterealtime.org" => "Ignite Realtime",
        "ij.org" => "IJ",
        "sur.conectas.org" => "IJHR",
        "infojustice.org" => "IJIP",
        "www.ikea.com" => "Inter IKEA Systgems B V",
        "www.ilfattoquotidiano.it" => "Il Fatto Quotidiano",
        "iliana.fyi" => "Iliana Etaoin",
        "www.stamfordmercury.co.uk" => "Iliffe Media Publishing Ltd",
        "guides.library.illinois.edu" => "The University of Illinois",
        "news.illinois.edu" => "The University of Illinois",
        "www.ncsa.illinois.edu" => "The University of Illinois",
        "www.illinois.gov" => "Illinois",
        "illinoisnewstoday.com" => "Illinois",
        "www.countryherald.com" => "Illinois",
        "quic.xargs.org" => "Illustrated QUIC",
        "getimageview.net" => "Image View",
        "blogs.imf.org" => "IMF",
        "www.imf.org" => "IMF",
        "immich.app" => "Immich",
        "www.imore.com" => "iMore",
        "increment.com" => "Increment Magazine",
        "independentaustralia.net" => "Independent AU",
        "www.indexoncensorship.org" => "Index On Censorship",
        "deccanrepublic.com" => "India",
        "frontline.thehindu.com" => "India",
        "indiatribune.com" => "India Tribune",
        "indianews.in" => "India",
        "news24online.com" => "India",
        "odishatv.in" => "India",
        "trai.gov.in" => "India",
        "pib.gov.in" => "India",
        "silverscreenindia.com" => "India",
        "telanganatoday.com" => "India",
        "thegoaspotlight.com" => "India",
        "www.bloombergquint.com" => "India",
        "www.dailypioneer.com" => "India",
        "www.daily-sun.com" => "India",
        "www.indiandefencereview.com" => "India",
        "www.newagebd.net" => "India",
        "www.news18.com" => "India",
        "www.republicworld.com" => "India",
        "www.sundayguardianlive.com" => "India",
        "zeenews.india.com" => "India Dot Com Pvt Ltd",
        "indiaeducationdiary.in" => "India Education Diary",
        "www.indialegallive.com" => "India Legal Live",
        "www.india.com" => "India News",
        "indiancountrytoday.com" => "Indian Country Today",
        "indianexpress.com" => "Indian Express",
        "www.indiapost.com" => "India Post",
        "auto.economictimes.indiatimes.com" => "India Times",
        "cio.economictimes.indiatimes.com" => "India Times",
        "ciso.economictimes.indiatimes.com" => "India Times",
        "economictimes.indiatimes.com" => "India Times",
        "energy.economictimes.indiatimes.com" => "India Times",
        "government.economictimes.indiatimes.com" => "India Times",
        "health.economictimes.indiatimes.com" => "India Times",
        "telecom.economictimes.indiatimes.com" => "India Times",
        "timesofindia.indiatimes.com" => "India Times",
        "www.indiatimes.com" => "India Times",
        "www.indiatoday.in" => "India Today",
        "www.indiewire.com" => "Indie Wire",
        "www.cybersecuritydive.com" => "Industry Dive",
        "www.socialmediatoday.com" => "Industry Dive",
        "www.infoq.com" => "InfoQ",
        "www.lightreading.com" => "Informa PLC",
        "www.networkcomputing.com" => "Informa PLC",
        "energy-utilities.com" => "Informa PLC",
        "www.informationng.com" => "Information Nigeria",
        "www.bankinfosecurity.asia" => "Information Security Media Group Corporation",
        "infosec-handbook.eu" => "InfoSec Handbook",
        "www.infosecmatter.com" => "InfoSec Matter",
        "www.infosecurity-magazine.com" => "InfoSecurity Magazine",
        "infosurhoy.com" => "Infosurhoy",
        "www.infoworld.com" => "InfoWorld",
        "blog.windfluechter.net" => "Ingo Jürgensmann",
        "www.inkl.com" => "Inkl",
        "inkscape.org" => "Inkscape",
        "www.innovationaus.com" => "InnovationAus",
        "www.inputmag.com" => "Input Magazine",
        "www.inria.fr" => "La Fondation Inria",
        "insidebigdata.com" => "Inside Big Data",
        "www.insidehighered.com" => "Inside Higer Ed",
        "www.insidehook.com" => "Inside Hook",
        "inside.lighting" => "Inside.lighting",
        "www.insidetelecom.com" => "Inside Telecom",
        "insidesources.com" => "InsideSources LLC",
        "www.ifn.se" => "Research Institute of Industrial Economics",
        "discourse.imfreedom.org" => " Instant Messaging Freedom",
        "gnu.ist.utl.pt" => "Instituto Superior Técnico",
        "www.instituteforgovernment.org.uk" => "Institute for Government",
        "ips-dc.org" => "Institute for Policy Studies",
        "www.construction-physics.com" => "Institute for Progress",
        "www.instructables.com" => "Instructables",
        "www.businessinsurance.com" => "Insurance",
        "www.profrisk.com" => "Insurance",
        "www.insurancebusinessmag.com" => "Insurance Business UK",
        "www.iihs.org" => "Insurance Institute for Highway Safety, Highway Loss Data Institute",
        "www.insurancejournal.com" => "Insurance Journal",
        "community.intel.com" => "Intel",
        "www.intel471.com" => "Intel471",
        "ifcomp.org" => "The Interactive Fiction Competition",
        "ifdb.org" => "The Interactive Fiction Database",
        "intfiction.org" => "The Interactive Fiction Community",
        "interestingengineering.com" => "Interesting Engineering",
        "internationalaffairs.co" => "International Affairs",
        "www.ibtimes.co.in" => "International Business Times",
        "www.ibtimes.com" => "International Business Times",
        "www.ibtimes.co.uk" => "International Business Times",
        "www.ibtimes.sg" => "International Business Times",
        "laweconcenter.org" => "International Center for Law and Economics",
        "doi.org" => "International Digital Object Identifier (DOI) Foundation",
        "blogs.ifla.org" => "International Federation of Library Assocations and Institutions",
        "www.mathunion.org" => "International Mathematical Union",
        "imemc.org" => "International Middfle East Media Center",
        "www.pascalcongress.com" => "International Pascal Congress",
        "www.ips-planetarium.org" => "International Planetarium Society",
        "www.pressenza.com" => "International Press Agency",
        "www.inta.org" => "International Trademark Association",
        "iwp9.org" => "International Workshop on Plan 9",
        "archive.org" => "Internet Archive",
        "web.archive.org" => "Internet Archive",
        "blog.archive.org" => "Internet Archive",
        "internetphonebook.net" => "Internet Phone Book",
        "www.internetsociety.org" => "Internet Society",
        "internetingishard.netlify.app" => "InternetingIsHard",
        "www.interpol.int" => "INTERPOL",
        "www.intheblack.com" => "In The Black",
        "inventree.org" => "InvenTree",
        "www.investopedia.com" => "Investopedia",
        "ih.advfn.com" => "Investors Hub",
        "invisv.com" => "INVISV",
        "www.ioccc.org" => "IOCCC",
        "www.iol.co.za" => "IOL",
        "www.ionos.com" => "IONOS Inc",
        "iopscience.iop.org" => "IOP Publishing",
        "www.rcreader.com" => "Iowa",
        "iowacapitaldispatch.com" => "Iowa Capital Dispatch",
        "www.news.iastate.edu" => "Iowa State University",
        "www.iphonehacks.com" => "iPhone Hacks",
        "www.iphoneincanada.ca" => "iPhone In Canada",
        "www.ipcc.ch" => "IPCC",
        "ipi.media" => "IPI",
        "indigenouspeoples-sdg.org" => "IPMG-SDG",
        "www.investigativeproject.org" => "IPT",
        "www.i-programmer.info" => "I Programmer",
        "www.iqair.com" => "IQAir",
        "iranhr.net" => "Iran Human Rights",
        "iranpresswatch.org" => "Iran Press Watch",
        "iranwire.com" => "IranWire",
        "connachttribune.ie" => "Ireland",
        "www.irishcentral.com" => "Irish Central",
        "www.iccl.ie" => "Irish Council for Civil Liberties",
        "www.irishexaminer.com" => "Irish Examiner",
        "www.independent.ie" => "Irish Independent",
        "www.irishmirror.ie" => "Irish Mirror",
        "www.irishtimes.com" => "Irish Times",
        "irregulators.org" => "The Irregulators",
        "www.iru.org" => "IRU",
        "dshield.org" => "ISC",
        "lists.isc.org" => "ISC",
        "sysadmin-journal.com" => "Ish Sookun",
        "scilly.gov.uk" => "Isles of Scilly",
        "www.countypress.co.uk" => "Isle of Wight",
        "www.isocfoundation.org" => "ISOC",
        "blog.isosceles.com" => "Isosceles Blog",
        "www.ispreview.co.uk" => "ISPreview",
        "www.israelnationalnews.com" => "Israel National News",
        "securityandtechnology.org" => "IST",
        "istlsfastyet.com" => "Is TLS Fast Yet",
        "www.italianpost.news" => "Italian Post News",
        "www.unionesarda.it" => "Italy",
        "www.italy24news.com" => "Italy 24 News",
        "codewithoutrules.com" => "Itamar Turner Trauring",
        "itbrief.com.au" => "IT Brief Australia",
        "itbrief.co.nz" => "IT Brief NZ",
        "www.itjungle.com" => "IT Jungle",
        "www.itprotoday.com" => "IT Pro Today",
        "techblog.nz" => "IT Professionals NZ Inc",
        "ittavern.com" => "IT Tavern",
        "itch.io" => "Itch Corp",
        "sr.ithaka.org" => "Ithaka S+R",
        "itif.org" => "ITIF",
        "insidethemagic.net" => "ITM",
        "itmunch.com" => "ITM",
        "www.itnews.com.au" => "IT News AU",
        "www.itpro.com" => "IT Pro",
        "www.itpro.co.uk" => "IT Pro",
        "www.itproportal.com" => "IT Pro Portal",
        "itsfoss.com" => "It's FOSS",
        "news.itsfoss.com" => "It's FOSS",
        "itsgoingdown.org" => "ItsGoingDown",
        "it-online.co.za" => "IT-Online",
        "www.itv.com" => "ITV",
        "www.itweb.co.za" => "IT Web",
        "itwire.com" => "IT Wire",
        "www.itwire.com" => "IT Wire",
        "www.itworldcanada.com" => "IT World CA",
        "uplab.pro" => "Ivan Kuleshov",
        "softwaremaniacs.org" => "Ivan Sagalaev",
        "www.tomica.net" => "Ivan Tomica",
        "iximiuz.com" => "Ivan Velichko",
        "www.ivir.nl" => "IVIR",
        "www.iwf.org" => "IWF",
        "www.ixsystems.com" => "ix Systems",
        "jhalderm.com" => "J Alex Halderman",
        "www.jdsupra.com" => "J D Supra LLC",
        "jwgoerlich.com" => "J Wolfgang Goerlich",
        "gmi.skyjake.fi" => "Jaakko Keränen",
        "baty.blog" => "Jack Baty",
        "baty.net" => "Jack Baty",
        "scribbles.baty.net" => "Jack Baty",
        "daily.baty.net" => "Jack Baty",
        "www.jackfranklin.co.uk" => "Jack Franklin",
        "jackkelly.name" => "Jack Kelly",
        "wormsandviruses.com" => "Jack Wellborn",
        "www.hackingbutlegal.com" => "Jackie Singh",
        "jacky.wtf" => "Jacky Alciné",
        "www.jacky.wtf" => "Jacky Alciné",
        "tookmund.com" => "Jacob Adams Tookmund",
        "tech.davis-hansson.com" => "Jacob Davis Hansson",
        "jakubnowosad.com" => "Jacob Nowosad",
        "blog.jacobstoner.com" => "Jacob Stoner",
        "jacobin.com" => "Jacobin Magazine",
        "jacobinmag.com" => "Jacobin Magazine",
        "www.jacobinmag.com" => "Jacobin Magazine",
        "jacobian.org" => "Jacob Kaplan Moss",
        "adminblog.foucry.net" => "Jacques Foucry",
        "777.tf" => "Jae Lo Presti",
        "jaggedplanet.com" => "Jagged Planet",
        "jahed.dev" => "Jahed",
        "www.jakartadaily.id" => "Jakarta Daily",
        "jakearchibald.com" => "Jake Archibald",
        "www.paritybit.ca" => "Jake Bauer",
        "jakelazaroff.com" => "Jake Lazaroff",
        "www.jakerobins.com" => "Jake Robins",
        "jakob.space" => "Jakob L Kreuze",
        "blog.jakuba.net" => "Jakub Arnold",
        "blog.jimmac.eu" => "Jakub Steiner",
        "jamanetwork.com" => "JAMA",
        "jamesabley.com" => "James Abley",
        "www.b-list.org" => "James Bennett",
        "blog.hansenpartnership.com" => "James Bottomley",
        "www.roguelazer.com" => "James Brown",
        "jamesclear.com" => "James Clear",
        "jamesg.blog" => "James G",
        "prog21.dadgum.com" => "James Hague",
        "www.jameskerr.blog" => "James Kerr",
        "www.pathsensitive.com" => "James Koppel",
        "www.jameskupke.com" => "James Kupke",
        "incoherency.co.uk" => "James Stanley",
        "scattered-thoughts.net" => "Jamie Brandon",
        "www.scattered-thoughts.net" => "Jamie Brandon",
        "current.workingdirectory.net" => "Jamie McClelland",
        "jrsinclair.com" => "James Sinclair",
        "jami.net" => "Jami",
        "www.jvt.me" => "Jamie Tanna",
        "www.jwz.org" => "Jamie Zawinski",
        "stevens.netmeister.org" => "Jan Schaumann",
        "www.characterworks.co" => "Jane Ruffino",
        "www.janes.com" => "Janes",
        "jlelse.blog" => "Jan Lukas Else",
        "jnboehm.com" => "JanNiklas Böhm",
        "www.noa-s.org" => "Jan Nowa",
        "jpmens.net" => "Jan Piet Mens",
        "www.netmeister.org" => "Jan Schaumann",
        "www.japantimes.co.jp" => "Japan",
        "www.nippon.com" => "Japan",
        "www.jftc.go.jp" => "Japan Fair Trade Commission",
        "www.jareddiamond.org" => "Jared Diamond",
        "www.jarednelsen.dev" => "Jared Nelsen",
        "www.spicyweb.dev" => "Jared White",
        "heydingus.net" => "Jarrod Blundy",
        "blog.jabid.in" => "Jaseem Abid",
        "json.blog" => "Jason Becker",
        "grepjason.sh" => "Jason Burk",
        "bluerenga.blog" => "Jason Dyer",
        "jasonfry.co.uk" => "Jason Fry",
        "social.jasonheppler.org" => "Jason Heppler",
        "blog.jasonkratz.me" => "Jason Kratz",
        "echoville.blog" => "Jason Kratz",
        "jxnl.co" => "Jason Liu",
        "nochlin.com" => "Jason Nochlin",
        "jro.io" => "Jason Rose",
        "jasontucker.blog" => "Jason Tucker",
        "www.joshwcomeau.com" => "Jason W Comeau",
        "kottke.org" => "Jason Kottke",
        "jasonlefkowitz.net" => "Jason Lefkowitz",
        "ascii.textfiles.com" => "Jason Scott",
        "www.codewithjason.com" => "Jason Swett",
        "www.fromjason.xyz" => "Jason Velazquez",
        "esp32-open-mac.be" => "Jasper Devreker",
        "jasper.tandy.is" => "Jasper Tandy",
        "jasper.la" => "Jasper Lievisse Adriaanse",
        "thoughts.jatan.space" => "Jatan Mehta",
        "blog.dowhile0.org" => "Javier Martinez Canillas",
        "jaxenter.com" => "JAXenter",
        "jayconrod.com" => "Jay Conrad",
        "jaydaigle.net" => "Jay Daigle",
        "jaylittle.com" => "Jay Little",
        "heyjaywilson.com" => "Jay Wilson",
        "www.jbklutse.com" => "JB Klutse",
        "start.jcolemorrison.com" => "J Cole Morrison",
        "jcpa.org" => "JCPA",
        "jcs.org" => "JCS",
        "blog.jdpfu.com" => "JDPFu",
        "hypirion.com" => "Jean Niklas",
        "fortintam.com" => "Jean-François Fortin Tam",
        "jaywhy13.hashnode.dev" => "Jean-Mark Wright",
        "thephd.dev" => "JeanHeyd Meneide",
        "jeffbridgforth.com" => "Jeff Bridgforth",
        "www.jeffgeerling.com" => "Jeff Geerling",
        "jeffhuang.com" => "Jeff Huang",
        "sneak.berlin" => "Jeffrey Paul",
        "pdx.su" => "Jeff Sandberg",
        "sheetsj.com" => "Jeff Sheets",
        "micro.webology.dev" => "Jeff Triplett",
        "www.jelmer.uk" => "Jelmer Vernooij",
        "jemma.dev" => "Jemma Issroff",
        "jenniferplusplus.com" => "Jennifer Moore",
        "jepsen.io" => "Jepsen",
        "jeremy.bicha.net" => "Jeremy Bicha",
        "www.jeremyblum.com" => "Jeremy Blum",
        "jerf.org" => "Jeremy Bowers",
        "www.jerf.org" => "Jeremy Bowers",
        "jeremyburge.com" => "Jeremy Burge",
        "www.jeremycherfas.net" => "Jeremy Cherfas",
        "adactio.com" => "Jeremy Keith",
        "www.jeremykun.com" => "Jeremy Kun",
        "jeremymikkola.com" => "Jeremy Mikkola",
        "www.jeremymorgan.com" => "Jeremy Morgan",
        "www.historyofinformation.com" => "Jeremy Norman",
        "ardentperf.com" => "Jeremy Schneider",
        "nullptr.club" => "Jeroen DeHaas",
        "jfmengels.net" => "Jeroen Engels",
        "jeroensangers.com" => "Jeroen Sangers",
        "jerseyeveningpost.com" => "Jersey Evening Post",
        "www.jpost.com" => "Jerusalem Post",
        "j3s.sh" => "Jes Olson",
        "man.ifconfig.se" => "Jesper Wallin",
        "jezs00.medium.com" => "Jess Farber",
        "www.librarian.net" => "Jessamyn West",
        "jesseduffield.com" => "Jesse Duffield",
        "blog.jse.li" => "Jesse Li",
        "jessesingal.substack.com" => "Jesse Singal",
        "ospi.fi" => "Jesse Sandberg",
        "jessitron.com" => "Jessica Kerr",
        "discombobulated.co.nz" => "Jessica Nickelsen",
        "blog.jessfraz.com" => "Jessie Frazelle",
        "www.jetnet.com" => "JETNET",
        "jewishjournal.com" => "Jewish Journal",
        "www.jewishnews.co.uk" => "Jewish News",
        "www.jweekly.com" => "Jewish News",
        "www.jewishpress.com" => "Jewish Press",
        "www.jezebel.com" => "Paste Media Group",
        "jezenthomas.com" => "Jezen Thomas",
        "jfrog.com" => "JFrog",
        "www.jihadwatch.org" => "Jihad Watch",
        "jilliancyork.com" => "Jillian C York",
        "jillwohlner.com" => "Jill Wohlner",
        "internetperdition.wordpress.com" => "Jim Garrett",
        "dev.jimgrey.net" => "Jim Grey",
        "jimmitchell.org" => "Jim Mitchell",
        "blog.jim-nielsen.com" => "Jim Nielsen",
        "www.jipitec.eu" => "JIPITEC",
        "jpospisil.com" => "Jiri Pospisil",
        "jitsi.org" => "Jitsi",
        "www.jkrowling.com" => "JK Rowling",
        "blog.jmp.chat" => "JMP",
        "www.jns.org" => "JNS",
        "www.joabj.com" => "Joab Jackson",
        "joanwestenberg.com" => "Joan Westenberg",
        "jobgether.com" => "Jopgether SRL",
        "artlung.com" => "Joe Crawford",
        "jo.ie" => "Joe Davis",
        "bitworking.org" => "Joe Gregorio",
        "rhonabwy.com" => "Joe Heck",
        "joelchrono.xyz" => "Joel Chrono",
        "jgoguen.ca" => "Joel Goguen",
        "joelgustafson.com" => "Joel Gustafson",
        "www.idatum.net" => "Joel P",
        "www.joelonsoftware.com" => "Joel Spolsky",
        "joemorrison.substack.com" => "Joe Morrison",
        "blog.krakjoe.ninja" => "Joe Watkins",
        "joeyh.name" => "Joey Hess",
        "www.johanbleuzen.fr" => "Johan Bleuzen",
        "johan.hal.se" => "Johan Halse",
        "www.johanl.se" => "Johan Larsson",
        "blog.johannes-mittendorfer.com" => "Johannes Mittendorfer",
        "weberblog.net" => "Johannes Weber",
        "jwillbold.com" => "Johannes Willbold",
        "john.ankarstrom.se" => "John Ankarström",
        "www.johndcook.com" => "John D Cook",
        "changelog.complete.org" => "John Goerzen",
        "www.complete.org" => "John Goerzen",
        "blog.jgc.org" => "John Graham Cumming",
        "www.jrgsystems.com" => "John Grafton",
        "daringfireball.net" => "John Gruber",
        "www.dirtyfeed.org" => "John J Hoare",
        "john.measey.com" => "John Measey",
        "johnmenadue.com" => "John Menadue",
        "www.ke5fx.com" => "John Miles, KE5FX",
        "memex.naughtons.org" => "John Naughton",
        "notgull.net" => "John Nunley",
        "ghost.onolan.org" => "John O'Nolan",
        "john.onolan.org" => "John O'Nolan",
        "computeradsfromthepast.substack.com" => "John Paul Wohlscheid",
        "johnpilger.com" => "John Pilger",
        "www.quadibloc.com" => "John Savard",
        "nachtimwald.com" => "John Schember",
        "johnstawinski.com" => "John Stawinski IV",
        "johnnydecimal.com" => "Johnny Decimal",
        "joinup.ec.europa.eu" => "Joinup",
        "jnsgr.uk" => "Jon Seager",
        "jonwillia.ms" => "Jon Williams",
        "jbb.ghsq.ga" => "Jonah Brüchert",
        "jonas.brusman.se" => "Jonas Brusman",
        "www.jonashietala.se" => "Jonas Hietala",
        "jcarroll.com.au" => "Dr Jonathan Carroll",
        "professional-troublemaker.com" => "Jonathan Corbett",
        "jmtd.net" => "Jonathan Dowland",
        "jonathanhaidt.com" => "Jonathan Haidt",
        "yonkeltron.com" => "Jonathan E Magen",
        "thejpster.org.uk" => "Jonathan Pallant",
        "jriddell.org" => "Jonathan Riddell",
        "jonathanturley.org" => "Jonathan Turley",
        "xyinn.org" => "Jonathan Vasquez",
        "www.jonathanychan.com" => "Jonathan Y Chan",
        "rightofpublicity.com" => "Jonathan Faber",
        "blog.jonlu.ca" => "Jon Luca DeCaro",
        "blog.jonudell.net" => "Jon Udell",
        "gekkio.fi" => "Joonas Javanainen",
        "joonas.fi" => "Joonas Loppi",
        "joost.blog" => "Joost de Valk",
        "geoghegan.ca" => "Jordan Geoghegan",
        "jordankaye.dev" => "Jordan Kaye",
        "jordanreger.com" => "Jordan Reger",
        "www.worldofreel.com" => "Jordan Ruimy",
        "www.jordantimes.com" => "The Jordan Times",
        "jordan-wright.com" => "Jordan Write",
        "jorgemorais.gitlab.io" => "JorgeMorais",
        "jorin.me" => "Jorin",
        "josvisser.substack.com" => "Jos Visser",
        "www.josemunozmatos.com" => "Jose Munoz",
        "www.saverilawfirm.com" => "Joseph Saveri Law Firm",
        "githubcopilotinvestigation.com" => "Joseph Saveri Law Firm",
        "llmlitigation.com" => "Joseph Saveri Law Firm",
        "githubcopilotlitigation.com" => "Joseph Saveri Law Firm",
        "joshaustin.tech" => "Josh Austin",
        "josh.blog" => "Josh Betz",
        "josh.is-cool.dev" => "Josh Byrd",
        "joshldavis.com" => "Josh Davis",
        "cyberb.space" => "Josh Erb",
        "codingitwrong.com" => "Josh Justice",
        "www.joshmcguigan.com" => "Josh Mcguigan",
        "joshwithers.blog" => "Josh Withers",
        "kennedn.com" => "Joshua Kennedy",
        "joshua.hu" => "Joshua Rogers",
        "www.journee-mondiale.com" => "Journées Mondiales",
        "freedomnews.org.uk" => "Journal of Anarchist Socialism",
        "www.journaloffreespeechlaw.org" => "Journal of Free Speech Law",
        "jpegxl.io" => "JPEG XL Converter",
        "jpieper.com" => "J Pieper",
        "jrs-s.net" => "JRS Systems",
        "jrswab.com" => "JR Swab",
        "kernelpanic.life" => "Jsf0",
        "daily.jstor.org" => "JSTOR",
        "judecnelson.blogspot.com" => "Jude C Nelson",
        "www.jntrnr.com" => "JT",
        "jbrio.net" => "Juan B Rodriguez",
        "juerd.nl" => "Juerd Waalboer",
        "hamatti.org" => "Juha-Matti Santala",
        "www.syntaxerror.tech" => "Juha-Matti Santala",
        "lehtimaeki.medium.com" => "Juhani Lehtimäki",
        "jvns.ca" => "Julia Evans",
        "blog.jak-linux.org" => "Julian Andres Klode",
        "jupe.studio" => "Julian Peters",
        "juliareda.eu" => "Julia Reda",
        "blog.cr0.org" => "Julien Tinnes",
        "dustri.org" => "Julien Voisin",
        "jumpcloud.com" => "Jump Cloud",
        "www.jumpingrivers.com" => "Jumping Rivers",
        "blogs.juniper.net" => "Juniper Networks",
        "www.jupiterbroadcasting.com" => "Jupiter Broadcasting",
        "www.jurist.org" => "JURIST",
        "nibblestew.blogspot.com" => "Jussi Pakkanen",
        "justenergy.com" => "Just Energy Texas LP",
        "www.justsecurity.org" => "Just Security",
        "patents.justia.com" => "Justia",
        "justinblank.com" => "Justin Blank",
        "jmduke.com" => "Justin Duke",
        "justingarrison.com" => "Justin Garrison",
        "www.jmeiners.com" => "Justin Meiners",
        "justinmiller.io" => "Justin Miller",
        "justinvollmer.com" => "Justin Vollmer",
        "www.justinvollmer.com" => "Justin Vollmer",
        "justine.lol" => "Justine Tunney",
        "blog.bdw.li" => "JWB",
        "jyn.dev" => "JYN",
        "k3tan.com" => "K3tan",
        "nadh.in" => "Kailash Nadh",
        "kaiwenwang.com" => "Kaiwen Wang",
        "www.kali.org" => "Kali Linux",
        "www.discovermagazine.com" => "Kalmback Media Co",
        "www.bitsaboutmoney.com" => "Kalzumeus Software LLC",
        "palaiologos.rocks" => "Kamila Szewczyk",
        "www.kansascity.com" => "Kansas City",
        "www.kansaslegalservices.org" => "Kansas Legal Services",
        "kansasreflector.com" => "Kansas Reflector",
        "securelist.com" => "Kapersky",
        "mrkaran.dev" => "Karan Sharma",
        "kcoyle.blogspot.com" => "Karen Coyle",
        "kcoyle.net" => "Karen Coyle",
        "semaphore.substack.com" => "Karina Nguyen",
        "www.karl.berlin" => "Karl Bartel",
        "dbdemon.com" => "Karl Levik",
        "www.openmymind.net" => "Karl Seguin",
        "www.technicalsourcery.net" => "Karl Stenerud",
        "www.karlsutt.com" => "Karl Sutt",
        "karl-voit.at" => "Karl Voit",
        "www.kaspersky.com" => "Kaspersky",
        "technicalwriting.dev" => "Kayce Basques",
        "www.biodigitaljazz.net" => "Kayce Basques",
        "justanerds.site" => "KLD",
        "kathmandupost.com" => "Nepal",
        "www.nepalitimes.com" => "Nepal Times",
        "blog.kraken.com" => "KDAE",
        "eco.kde.org" => "KDE",
        "mail.kde.org" => "KDE",
        "gkeenan.co" => "Keenan",
        "keepassxc.org" => "KeePassXC",
        "useyourloaf.com" => "Keith Harrison",
        "keithlovesmovies.com" => "Keith Loves Movies",
        "keivan.io" => "Keivan Beigi",
        "lightroomkillertips.com" => "KelbyOne",
        "laughingmeme.org" => "Kellan Elliott-McCrea",
        "blog.kellybrazil.com" => "Kelly Brazil",
        "kellyshortridge.com" => "Kelly Shortridge",
        "swagitda.com" => "Kelly Shortridge",
        "www.stuff.tv" => "Kelsey Media",
        "kenkantzer.com" => "Ken Kantzer",
        "www.righto.com" => "Ken Shirriff",
        "kozume.neocities.org" => "Kenma",
        "blog.thelifeofkenneth.com" => "Kenneth Finnegan",
        "www.kentonline.co.uk" => "Kent UK",
        "kentwired.com" => "The Kent Stater",
        "www.k24tv.co.ke" => "Kenya",
        "www.the-star.co.ke" => "Kenya",
        "kenyan-post.com" => "Kenya",
        "datareportal.com" => "Kepios",
        "ketanjoshi.co" => "Ketan Joshi",
        "doublepulsar.com" => "Kevin Beaumont",
        "kevinboone.me" => "Kevin Boone",
        "kevin.burke.dev" => "Kevin Burke",
        "myconscious.stream" => "Kevin C Tofel",
        "kevincox.ca" => "Kevin Cox",
        "lawver.net" => "Kevin Lawver",
        "kliu.io" => "Kevin Liu",
        "kn100.me" => "Kevin Norman",
        "cliophate.wtf" => "Kevin Wammer",
        "interconnected.blog" => "Kevin Xu",
        "kevq.uk" => "Kev Quirk",
        "kevquirk.com" => "Kev Quirk",
        "www.canadianlawyermag.com" => "Key Media",
        "keygen.sh" => "Keygen LLC",
        "www.kff.org" => "KFF",
        "khn.org" => "KFF",
        "kfgo.com" => "KFGO Radio",
        "kgab.com" => "KGAB Radio",
        "www.kjzz.org" => "KJZZ Radio",
        "www.khaama.com" => "Khaama Press",
        "www.khaosodenglish.com" => "Khaosod",
        "www.kianryan.co.uk" => "Kian Ryan",
        "www.kickstarter.com" => "Kicksterter PBC",
        "www.uni-kiel.de" => "Kiel University",
        "kdhnews.com" => "Killeen Daily Herald, Texas",
        "www.komando.com" => "Kim Kommando",
        "www.insideedition.com" => "King World Productions Inc",
        "kirby.kevinson.org" => "Kirby Kevinson",
        "nocto.com" => "Kirsty Darbyshire",
        "www.kirupa.com" => "Kirupa",
        "kivikakk.ee" => "Kivikakk",
        "lottia.net" => "Kivikakk",
        "klarasystems.com" => "Klara",
        "www.kleefeldoncomics.com" => "Kleefeld on Comics",
        "copyrightblog.kluweriplaw.com" => "Kluwer Law",
        "debugging.works" => "Kmille",
        "blog.knoldus.com" => "Knoldus",
        "blog.knowbe4.com" => "KnowBe4",
        "kmaasrud.com" => "Knut Magnus Aasrud",
        "kodi.tv" => "Kodi Foundation",
        "kodsnack.se" => "Kodsnack",
        "blog.koehntopp.info" => "Koehntopp",
        "s8297.pcdn.co" => "Kojo Nnamdi",
        "koliasa.com" => "Koliasa",
        "www.1011now.com" => "KOLN TV",
        "www.komu.com" => "KOMU TV",
        "konstantintutsch.com" => "Konstantin Tutsch",
        "www.kooslooijesteijn.net" => "Koos Looijesteijn",
        "www.koreaherald.com" => "Korea Herald",
        "koreatimes.co.kr" => "The Korea Times",
        "www.koreatimes.co.kr" => "The Korea Times",
        "sw.kovidgoyal.net" => "Kovid Goyal",
        "kowabit.de" => "Kowabit",
        "www.kpbs.org" => "KPBS TV",
        "advisory.kpmg.us" => "KPMG",
        "kpmg.com" => "KPMG International",
        "www.kqed.org" => "KQED TV",
        "krdo.com" => "KRDO TC",
        "krfnd.org" => "KR Foundation",
        "krebsonsecurity.com" => "Krebs On Security",
        "krisshrishak.de" => "Dr Kris Shrishak",
        "kiko.io" => "Kristof Zerbe",
        "krita.org" => "Krita",
        "www.whmi.com" => "Krol Communications Inc",
        "www.kroll.com" => "Kroll",
        "www.ksat.com" => "KSAT TV",
        "www.kshb.com" => "KSHB TC",
        "www.ksl.com" => "Deseret Media",
        "kstp.com" => "KSTP TV",
        "ktar.com" => "KTAR Radio",
        "www.ktnv.com" => "KTNV TV",
        "kunnamon.io" => "Kunnamon",
        "kuow.org" => "KUOW Radio",
        "www.kuow.org" => "KUOW TV",
        "krabf.com" => "Kushaiah Felisilda",
        "kvoa.com" => "KVOA TV",
        "kurtmckee.org" => "Kurt McKee",
        "kyefox.com" => "Kye Fox",
        "downloads.kemitchell.com" => "Kyle E Mitchell",
        "writing.kemitchell.com" => "Kyle E Mitchell",
        "houseofkyle.com" => "Kyle Ford",
        "kcimc.medium.com" => "Kyle McDonald",
        "kylemcdonald.net" => "Kyle McDonald",
        "ldstephens.net" => "L D Stephens",
        "lab6.com" => "Lab6",
        "labzilla.io" => "LabZilla",
        "mydbanotebook.org" => "Lætitia Avrot",
        "ladybird.org" => "The Ladybird Browser Initiative",
        "www.lagerdata.com" => "Lager",
        "lambdaland.org" => "Lambda Land",
        "www.lambiek.net" => "Lambiek Comix-Strips",
        "www.lep.co.uk" => "Lancashire",
        "landreport.com" => "Land Report",
        "lapcatsoftware.com" => "Lap Cat Software",
        "www.laphamsquarterly.org" => "Laphams Quarterly",
        "www.laprogressive.com" => "LA Progressive",
        "www.laptopmag.com" => "Laptop Magazine",
        "www.laquadrature.net" => "La Quadature Du Net",
        "www.repubblica.it" => "la Repubblica",
        "laker.tech" => "Laker Turner",
        "www.huttu.net" => "Lari Huttunen",
        "lars.ingebrigtsen.no" => "Lars Ingrebrigtsen",
        "blog.liw.fi" => "Lars Wirzenius",
        "doc.liw.fi" => "Lars Wirzenius",
        "liw.fi" => "Lars Wirzenius",
        "las.rs" => "Las Safin",
        "blog.lastpass.com" => "LastPass",
        "lastrealindians.com" => "Last Real Indians",
        "lastrealindians.com" => "Last Real Indians",
        "www.lastweekinaws.com" => "Last Week In AWS",
        "www.reviewjournal.com" => "Las Vegas Review Journal",
        "lasvegassun.com" => "Las Vegas Sun",
        "latacora.micro.blog" => "Latacora",
        "latestherald.com" => "Latest Herald",
        "latenightsw.com" => "Late Night Software Ltd",
        "www.latinpost.com" => "Latin Post",
        "www.latintimes.com" => "Latin Times",
        "eng.lsm.lv" => "Latvia",
        "mitten.lol" => "Laura Fisher",
        "liberda.nl" => "Lauren N Liberda",
        "blog.dend.ro" => "Laurențiu Nicola",
        "lawandcrime.com" => "Law And Crime",
        "www.lawsociety.ie" => "Law Society of Ireland",
        "www.lawliberty.org" => "Law And Liberty",
        "www.lawfareblog.com" => "Lawfare",
        "www.lawfaremedia.org" => "The Lawfare Institute",
        "www.lawgazette.co.uk" => "Law Society Gazette",
        "tratt.net" => "Lawrence Tratt",
        "lazyfoo.net" => "Lazy Foo",
        "www.lbc.co.uk" => "LBC",
        "lcamtuf.substack.com" => "Lcamtuf",
        "contrachrome.com" => "Leah Elliott",
        "leahneukirchen.org" => "Leah Neukirchen",
        "leah.is" => "Leah Oswald",
        "learnxinyminutes.com" => "Learn X in Y minutes",
        "learnlinuxandlibreoffice.org" => "LearnLinuxAndLibreOffice",
        "www.ledgerinsights.com" => "Ledger Insights",
        "leebriggs.co.uk" => "Lee Briggs",
        "ljpuk.net" => "Lee Peterson",
        "yingtongli.me" => "Lee Yingtong Li",
        "www.legacy.com" => "Legacy",
        "lasclev.org" => "The Legal Aid Society of Cleveland",
        "knsiradio.com" => "Leighton Broadcasting",
        "len.falken.ink" => "Len Falken",
        "www.alevsk.com" => "Lenin Alevski",
        "leolabs.org" => "Leo Bernard",
        "lmika.org" => "Leon Mika",
        "www.thedigitalcatonline.com" => "Leonardo Giordani",
        "leontrolski.github.io" => "Leontrolski",
        "www.lesswrong.com" => "Less Wrong",
        "letsencrypt.org" => "Let's Encrypt",
        "levlaz.org" => "Lev Lazinskiy",
        "levelup.gitconnected.com" => "Level Up Coding",
        "lewiscampbell.tech" => "Lewis Campbell",
        "www.lewis8s.codes" => "Lewis Codes",
        "lewisdale.dev" => "Lewis Dale",
        "lexfridman.com" => "Lex Fridman",
        "www.lexology.com" => "Lexology",
        "liam-on-linux.dreamwidth.org" => "Liam Proven",
        "liam-on-linux.livejournal.com" => "Liam Proven",
        "libcom.org" => "Libcom",
        "cpucycles.cr.yp.to" => "Libcpucycles",
        "libereurope.eu" => "LIBER",
        "liblouis.org" => "Liblouis",
        "bibliotekettarsaka.com" => "Library Case",
        "blog.librarything.com" => "Library Thing",
        "libreboot.org" => "LibreBoot",
        "libreelec.tv" => "LibreELEC",
        "extensions.libreoffice.org" => "LibreOffice",
        "help.libreoffice.org" => "LibreOffice",
        "libreoffice-dev.blogspot.com" => "LibreOffice",
        "media.libreplanet.org" => "Libre Planet",
        "blog.libtorrent.org" => "Libtorrent",
        "www.libyanexpress.com" => "Libya",
        "licenseuse.org" => "Licensing",
        "lichen.sensorstation.co" => "Lichen CMS",
        "www.lieffcabraser.com" => "Lieff Cabraser Hiemann and Bernstein",
        "www.lifehack.org" => "Lifehack",
        "www.reviewgeek.com" => "LifeSavvy Media",
        "www.lifewire.com" => "Lifewire",
        "www.lightbluetouchpaper.org" => "Light Blue Touchpaper",
        "liliputing.com" => "Liliputing",
        "www.linaro.org" => "Linaro",
        "robotmoon.com" => "Linmiao Xu",
        "www.linode.com" => "Linode",
        "linusakesson.net" => "Linus Åkesson",
        "www.linusakesson.net" => "Linus Åkesson",
        "lkml.org" => "Linux",
        "www.lkml.org" => "Linux",
        "wiki.nftables.org" => "Linux",
        "lore.kernel.org" => "Linux mailing lists",
        "people.kernel.org" => "Linux",
        "mirror.linux.org.au" => "Linux Australia",
        "www.linuxbabe.com" => "Linux Babe",
        "linuxcapable.com" => "Linux Capable",
        "linuxgizmos.com" => "Linux Gizmos",
        "linuxhandbook.com" => "Linux Handbook",
        "linuxhint.com" => "Linux Hint",
        "linuxiac.com" => "Linuxiac",
        "linuxinsider.com" => "Linux Insider",
        "www.linux.it" => "Linux IT",
        "www.linuxjournal.com" => "Linux Journal",
        "www.linuxlinks.com" => "Linux Links",
        "www.linuxmadesimple.info" => "Linux Made Simple",
        "www.linux-magazine.com" => "Linux Magazine",
        "blog.linuxmint.com" => "Linux Mint",
        "forums.linuxmint.com" => "Linux Mint",
        "linmob.net" => "Linux On Mobile",
        "linuxphoneapps.org" => "Linux Phone Apps",
        "www.linuxpromagazine.com" => "Linux Pro Magazine",
        "www.linuxquestions.org" => "Linux Questions",
        "ploum.be" => "Lionel Dricot",
        "ploum.net" => "Lionel Dricot",
        "lithub.com" => "Literary Hub",
        "www.livelaw.in" => "Live Law",
        "blog.llvm.org" => "LLVM Project",
        "blogs.loc.gov" => "LOC",
        "www.loc.gov" => "LOC",
        "www.cornwalllive.com" => "Local World",
        "www.gloucestershirelive.co.uk" => "Local World",
        "locusmag.com" => "Locus Magazine",
        "logicmag.io" => "Logic Magazine",
        "www.logikalsolutions.com" => "Logikal Solutions",
        "blog.logrocket.com" => "LogRocket Inc",
        "islingtontribune.com" => "London",
        "londonnewstime.com" => "London",
        "www.lonelyplanet.com" => "Lonely Planet",
        "thelongcontext.com" => "The Long Context",
        "loomcom.com" => "Loom Communications, LLC",
        "surfingcomplexity.blog" => "Lorin Hochstein",
        "kristoff.it" => "Loris Cro",
        "www.lamag.com" => "Los Angeles Magazine",
        "highschool.latimes.com" => "Los Angeles Times",
        "www.latimes.com" => "Los Angeles Times",
        "louderthanwar.com" => "Louder Than War",
        "louplummer.lol" => "Lou Plummer",
        "amerpie.lol" => "Lou Plummer",
        "blog.dureuill.net" => "Louis Dureuil",
        "loup-vaillant.fr" => "Loup Vaillant",
        "heyloura.com" => "Loura",
        "louwrentius.com" => "Louwrentius",
        "solar.lowtechmagazine.com" => "Low Tech Mag",
        "www.lowtechmagazine.com" => "Low Tech Mag",
        "www.lowpass.cc" => "Lowpass Media LLC",
        "www.lowyinstitute.org" => "Lowy Institute",
        "blogs.luc.edu" => "Loyola University Chicago",
        "www.lrt.lt" => "LRT",
        "lowerraritanwatershed.org" => "LRWP",
        "blogs.lse.ac.uk" => "LSE",
        "ageinghacker.net" => "Luca Saiu",
        "lucas.art" => "Lucas da Silva",
        "lucasgroup.com.au" => "Lucas Group",
        "lucasfcosta.com" => "Lucas F Costa",
        "ludic.mataroa.blog" => "Lucidity",
        "blog.phundrak.com" => "Lucien Cartier-Tilet",
        "livefreeordichotomize.com" => "Lucy D'Agostino McGowan & Nick Strayer",
        "mzll.it" => "Luigi Mozzillo",
        "www.luisquintanilla.me" => "Luis Quintanilla",
        "blog.lukaszolejnik.com" => "Lukasz Olejnik",
        "www.unterminated.com" => "Luke",
        "luke8086.dev" => "Luke S",
        "www.lkhrs.com" => "Luke Harris",
        "lukeplant.me.uk" => "Luke Plant",
        "lukerissacher.com" => "Luke Rissacher",
        "blog.lumen.com" => "Lumen Technologies",
        "www.lumi-supercomputer.eu" => "LUMI",
        "www.lusakatimes.com" => "Lusaka ZM",
        "www.lustre.org" => "Lustre",
        "www.lut.fi" => "LUT University",
        "lwn.net" => "LWN",
        "lxer.com" => "LXer",
        "blog.lyokolux.space" => "Lykolux",
        "lyra.horse" => "Lyra",
        "spyglass.org" => "M G Siegler",
        "www.filmvanalledag.nl" => "Maarten",
        "cheerful.nl" => "Maarten Janssen",
        "www.mcls.io" => "Maarten Claes",
        "vanemden.wordpress.com" => "Maarten van Emden",
        "proycon.anaproy.nl" => "Maarten van Gompel",
        "www.macaubusiness.com" => "Macaue Business",
        "www.macchaffee.com" => "Mac Chaffee",
        "www.macobserver.com" => "Mac Observer",
        "ports.macports.org" => "Mac Ports",
        "macprotricks.com" => "Mac Pro Tricks",
        "macdailynews.com" => "MacDailyNews",
        "www.macrotrends.net" => "Macrotrends",
        "forums.macrumors.com" => "MacRumors",
        "www.macrumors.com" => "MacRumors",
        "www.macstories.net" => "MacStories Inc",
        "www.macworld.com" => "Macworld",
        "madisoncollege.edu" => "Madison Area Technical College",
        "adtechmadness.wordpress.com" => "Madtech",
        "maheshba.bitbucket.io" => "Mahesh Balakrishnan",
        "marc.info" => "Mailing list ARChives",
        "www.mail-archive.com" => "Mailing List Archives",
        "malisper.me" => "Mailisper",
        "www.mailpile.is" => "Mailpile",
        "maitriyana.com" => "Maitriyana",
        "mainichi.jp" => "The Mainchi Newspapers",
        "apps.web.maine.gov" => "Maine",
        "www.maine.gov" => "Maine",
        "mainemorningstar.com" => "Maine Morning Star",
        "makezine.com" => "Make",
        "makemyday.free.fr" => "Make My Day Records",
        "www.makery.info" => "Makery",
        "www.maketecheasier.com" => "Make Tech Easier",
        "www.makeuseof.com" => "Make Use Of",
        "makoism.com" => "Makoism",
        "www.malaymail.com" => "Malay Mail",
        "paultan.org" => "Malaysia",
        "malcolmcoles.com" => "Malcom Coles",
        "blog.malwarebytes.com" => "Malwarebytes Labs",
        "www.malwarebytes.com" => "Malwarebytes Labs",
        "www.industrialempathy.com" => "Malte Ubl",
        "aworkinglibrary.com" => "Mandy Brown",
        "everythingchanges.us" => "Mandy Brown",
        "managedtechservices.com" => "Managed Technology Services",
        "www.manchestereveningnews.co.uk" => "Manchester Evening News",
        "themanchestermirror.com" => "The Manchester Mirror",
        "mandarismoore.com" => "Mandaris Moore",
        "www.mandiant.com" => "Mandiant",
        "english.manoramaonline.com" => "Manorama Online",
        "www.inc.com" => "Mansueto Ventures",
        "www.manton.org" => "Manton Reece",
        "manualredeye.com" => "Manual High School",
        "manuelmoreale.com" => "Manuel Moreale",
        "www.htmhell.dev" => "Manuel Matuzović",
        "www.matuzo.at" => "Manuel Matuzović",
        "manypossibilities.net" => "Many Possibilities",
        "blog.mapotofu.org" => "Mapotofu",
        "marcamos.com" => "Marc Amos",
        "huphtur.nl" => "Marcel Appelman",
        "mmk2410.org" => "Marcel Kapfer",
        "brooker.co.za" => "Marc Brooker",
        "www.coding2learn.org" => "Marc Scott",
        "www.kolaja.eu" => "Marcel Kolaja",
        "blog.metaobject.com" => "Marcel Weiher",
        "marcin.juszkiewicz.com.pl" => "Marcin Juszkiewicz",
        "marcocetica.com" => "Marco Cetica",
        "mb.esamecar.net" => "Marco F",
        "blog.bofh.it" => "Marco d'Itri",
        "marcozehe.de" => "Marco Zehe",
        "www.marcozehe.de" => "Marco Zehe",
        "mbuffett.com" => "Marcus Buffett",
        "prefetch.eu" => "Marcus R A Newman",
        "blog.mro.name" => "Marcus Rohrmoser",
        "www.emptywheel.net" => "Marcy Wheeler",
        "www.boucek.me" => "Marian Bouček",
        "marijkeluttekes.dev" => "Marijke Luttekes",
        "rmpr.xyz" => "Mario Rufus",
        "marionrecord.com" => "Marion County Record",
        "ship.energy" => "Maritime",
        "www.rivieramm.com" => "Maritime",
        "maritime-executive.com" => "The Maritime Executive LLC",
        "gexp.no" => "Marius Bakke",
        "chorasimilarity.wordpress.com" => "Marius Buliga",
        "www.oshogbo.vexillium.org" => "Mariusz Zaborski",
        "aggressivelyparaphrasing.me" => "Mark",
        "www.theengineer.co.uk" => "Mark Allen Group",
        "markcurtis.info" => "Mark Curtis",
        "www.markround.com" => "Mark Dastmalchi-Round",
        "blog.plover.com" => "Mark-Jason Dominus",
        "marksrpicluster.blogspot.com" => "Mark G James",
        "www.marketplace.org" => "Marketplace",
        "marketresearchbase.com" => "Market Research Base",
        "www.marketwatch.com" => "Market Watch",
        "phoenixtrap.com" => "Mark Gardner",
        "www.markhansen.co.nz" => "Mark Hansen",
        "mark.hysted.com" => "Mark Hysted",
        "jamsek.dev" => "Mark Jamsek",
        "www.mnot.net" => "Mark Nottingham",
        "probably.co.uk" => "Mark Phillips",
        "markosaric.com" => "Marko Saric",
        "www.markozivanovic.com" => "Marko Živanović",
        "www.marktechpost.com" => "Mark Tech Post",
        "www.metalevel.at" => "Markus Triska",
        "unterwaditzer.net" => "Markus Unterwaditzer",
        "martechseries.com" => "Mar Tech Series",
        "blog.brixit.nl" => "Martijn Braam",
        "blog.startifact.com" => "Martijn Faassen",
        "martincmartin.com" => "Martin C. Martin ",
        "martinfowler.com" => "Martin Fowler",
        "www.martingunnarsson.com" => "Martin Gunnarsson",
        "blog.martin-haehnel.de" => "Martin Hähne",
        "martinheinz.dev" => "Martin Heinz",
        "martin.kleppmann.com" => "Martin Kleppmann",
        "www.matecdev.com" => "Martin D Maas",
        "www.martinrowan.co.uk" => "Martin Rowan",
        "mht.wtf" => "Martin Thoresen",
        "www.arp242.net" => "Martin Tournoij",
        "martin-ueding.de" => "Martin Ueding",
        "blast-o-rama.com" => "Marty Day",
        "www.blast-o-rama.com" => "Marty Day",
        "in.mashable.com" => "Mashable",
        "mashable.com" => "Mashable",
        "sea.mashable.com" => "Mashable",
        "mashpeewampanoagtribe-nsn.gov" => "Mashpee Wampanoag Tribe",
        "investor.masimo.com" => "Masimo",
        "www.massnews.com" => "Mass News",
        "www.masswerk.at" => "Mass:Werk",
        "www.mass.gov" => "Massachusetts",
        "www.masslive.com" => "Massachusetts News",
        "www.masslivemedia.com" => "Mass Live",
        "www.masteringemacs.org" => "Mastering Emacs",
        "blog.joinmastodon.org" => "Mastodon",
        "matduggan.com" => "Mat Duggan",
        "matanabudy.com" => "Matan Abudy",
        "mathieu.comandon.org" => "Mathieu Comandon",
        "papers.mathyvanhoef.com" => "Mathy Vanhoef",
        "matrix.org" => "Matrix",
        "bessey.dev" => "Matt Bessey",
        "birchtree.me" => "Matt Birchler",
        "www.mattblaze.org" => "Matt Blaze",
        "matt.blwt.io" => "Matt Blewitt",
        "mattcool.tech" => "Matt Cool",
        "mrehler.com" => "Matt Ehler",
        "axio.ms" => "Matt Evans",
        "fantinel.dev" => "Matt Fantinel",
        "www.over-yonder.net" => "Matt Fuller",
        "matt.life" => "Matt Holt",
        "www.mattkeeter.com" => "Matt Keeter",
        "www.mattmahoney.net" => "Matt Mahoney",
        "ma.tt" => "Matt Mullenweg",
        "www.hezmatt.org" => "Matt Palmer",
        "mattstein.com" => "Matt Stein",
        "blog.gingerbeardman.com" => "Matt Sephton",
        "interconnected.org" => "Matt Webb",
        "mdwdotla.medium.com" => "Matt Welsh",
        "xnacly.me" => "Matteo",
        "matthewbutterick.com" => "Matthew Butterick",
        "mjg59.dreamwidth.org" => "Matthew Garrett",
        "www.going-flying.com" => "Matthew J Ernisse",
        "thedesk.matthewkeys.net" => "Matthew Keys",
        "matthewrocklin.com" => "Matthew Rocklin",
        "www.slowboring.com" => "Matthew Yglesias",
        "endler.dev" => "Matthias Endler",
        "openwebcraft.com" => "Matthias Geisler",
        "xosc.org" => "Matthias Schmidt",
        "www.mrlacey.com" => "Matt Lacey",
        "mattlangford.com" => "Matt Langford",
        "matt.might.net" => "Matt Might",
        "www.mattmillman.com" => "Matt Millman",
        "matt-rickard.com" => "Matt Rickard",
        "www.zagaja.com" => "Matt Zagaja",
        "mavenroundtable.io" => "Maven",
        "bernsteinbear.com" => "Max Bernstein",
        "max.levch.in" => "Max Levchin",
        "dirtypipe.cm4all.com" => "Max Kellermann",
        "maxsommer.de" => "Max Sommer",
        "maxim.tips" => "Maxim Tips",
        "www.mripard.dev" => "Maxime Ripard",
        "maximevaillancourt.com" => "Maxime Vaillancourt",
        "maya.land" => "Maya Land",
        "www.mayoclinic.org" => "Mayo Clinic",
        "jarunmb.com" => "MB",
        "mcb.org.uk" => "MCB",
        "www.charlotteobserver.com" => "McClatchy Media Network",
        "bullandbearmcgill.com" => "McGill University",
        "bullenweg.com" => "Matt Mullenweg’s Bull",
        "www.mckinsey.com" => "McKinsey and Company",
        "gld.mcphail.uk" => "McPhail",
        "murrayblackburnmackenzie.org" => "MBM",
        "www.mdpi.com" => "MDPI",
        "www.mdsec.co.uk" => "MD Sec",
        "medcitynews.com" => "Med City News",
        "medevel.com" => "Medevel",
        "medforth.biz" => "Medforth",
        "medforth.blog" => "Medforth",
        "www.videogameschronicle.com" => "1981 Media Ltd",
        "www.screendaily.com" => "Media Business Insight Ltd",
        "www.rcmediafreedom.eu" => "Media Freedom Rapid Response",
        "www.grid.news" => "Media Investment Projects OpCo LLC",
        "www.mediapost.com" => "MediaPost Communications",
        "windowsreport.com" => "MediaReflector",
        "www.mediaite.com" => "Mediaite",
        "www.mediamatters.org" => "Media Matters",
        "www.medianama.com" => "Media Nama",
        "mediatemple.net" => "Media Temple",
        "dailytrust.com" => "Media Trust Limited",
        "www.mediawiki.org" => "Media Wiki",
        "www.medicaleconomics.com" => "Medical Economics",
        "www.news-medical.net" => "Medical News",
        "mediocregopher.com" => "Mediocregopher",
        "coronavirus.medium.com" => "Medium",
        "blog.medium.com" => "Medium",
        "medium.com" => "Medium",
        "onezero.medium.com" => "Medium",
        "www.medpagetoday.com" => "MedPage Today",
        "meduza.io" => "Meduza",
        "www.meforum.org" => "ME Forum",
        "www.meed.com" => "MEED Media FZ LLC",
        "megelison.com" => "Meg Elison",
        "www.memesita.com" => "Memesita",
        "www.memri.org" => "MEMRI",
        "www.mentalfloss.com" => "Mental Floss",
        "middle-east-online.com" => "MEO",
        "www.mercatornet.com" => "MercatorNet",
        "www.merchantsofdoubt.org" => "Merchants of Doubt",
        "www.mercurynews.com" => "Mercury News",
        "merecivilian.com" => "Mere Civilian",
        "www.meritalk.com" => "Meritalk",
        "meshedinsights.com" => "Meshed Insights",
        "www.metabase.com" => "Metabase",
        "blog.metabrainz.org" => "Meta Brainz",
        "www.metro.us" => "Metro",
        "www.metrotimes.com" => "Metro Times",
        "metro.co.uk" => "Metro UK",
        "mexiconewsdaily.com" => "Mexico News Daily",
        "militaryfamilieslearningnetwork.org" => "MFLN",
        "500ish.com" => "MG Siegler",
        "www.glasgowlive.co.uk" => "MGN Ltd",
        "www.mi5.gov.uk" => "MI5",
        "www.miamiherald.com" => "Miami Herald",
        "micahflee.com" => "Micah F Lee",
        "me.micahrl.com" => "Micah R Ledbetter",
        "michalpitr.substack.com" => "Michal Pitr",
        "michal.sapka.me" => "Michał Sapka",
        "www.michalzelazny.com" => "Michal Zelazny",
        "lorentzen.ch" => "Michael's and Christian's blog",
        "www.brutman.com" => "Michael B Brutman",
        "mihobu.lol" => "Michael Burkhardt",
        "michaeldehaan.substack.com" => "Michael DeHaan",
        "curves.ulfheim.net" => "Michael Driscoll",
        "mek.fyi" => "Michael E. Karpeles",
        "citizen428.net" => "Michael Kohl",
        "michael.kjorling.se" => "Michael Kjörling",
        "mekarpeles.medium.com" => "Michael E. Karpeles",
        "michaelfeathers.silvrback.com" => "Michael Feathers",
        "www.michaelgeist.ca" => "Michael Geist",
        "mh9.codes" => "Michael Hausenblas",
        "michenriksen.com" => "Michael Henriksen",
        "www.michaelhorowitz.com" => "Michael Horowitz",
        "blog.ikuamike.io" => "Michael Ikua",
        "mtlynch.io" => "Michael Lynch",
        "www.michaelperrin.fr" => "Michaël Perrin",
        "michael-prokop.at" => "Michael Prokop",
        "justmarkup.com" => "Michael Scharnagl",
        "michael.stapelberg.ch" => "Michael Stapelberg",
        "rip-van-webble.blogspot.com" => "Michael Thomas",
        "mjtsai.com" => "Michael Tsai",
        "www.uplawski.eu" => "Michael Uplawski",
        "www.urspringer.de" => "Michael Urspringer",
        "www.ecliptik.com" => "Michael Waltz",
        "psychocod3r.wordpress.com" => "Michael Warren",
        "michaelweinberg.org" => "Michael Weinberg",
        "michaelwest.com.au" => "Michael West Media",
        "www.michaelwest.com.au" => "Michael West Media",
        "rys.io" => "Michał Woźniak",
        "michel-slm.name" => "Michel Alexandre Salim",
        "maique.eu" => "Micro Maique",
        "michiganadvance.com" => "Michigan Advance",
        "www.mlive.com" => "Michigan News",
        "midrange.tedium.co" => "Midrange",
        "menafn.com" => "Middle East North Africa Financial Network, Inc.",
        "www.middleeasteye.net" => "Middle East Eye",
        "www.mei.edu" => "Middle East Institute",
        "www.middleeastmonitor.com" => "Middle East Monitor",
        "www.middleeastobserver.org" => "Middle East Observer",
        "wtvbam.com" => "Midwest Communications",
        "blog.miguelgrinberg.com" => "Miguel Grinberg",
        "mcyoung.xyz" => "Miguel Young de la Sota",
        "crys.site" => "Michał Sapka",
        "hapgood.us" => "Mike Caulfield",
        "mikemcquaid.com" => "Mike McQuaid",
        "reorchestrate.com" => "Mike Seddon",
        "www.piratewires.com" => "Mike Solana",
        "mikestone.me" => "Mike Stone",
        "www.militarytimes.com" => "Military Times",
        "www.military.com" => "Military.com",
        "millichronicle.com" => "Milli Chronicle",
        "www.milwaukeeindependent.com" => "Milwaukee Independent",
        "mindmatters.ai" => "Mind Matters",
        "www.mining-technology.com" => "Mining Technology",
        "www.health.govt.nz" => "Ministry Of Health NZ",
        "www.mintpressnews.com" => "Mint Press News",
        "minnechaugsmokesignal.com" => "Minnechaug Regional High School",
        "blog.mnus.de" => "Minus",
        "www.mirror.co.uk" => "Mirror UK",
        "www.jacksongov.org" => "Missouri",
        "missouriindependent.com" => "Missouri",
        "www.mistys-internet.website" => "Misty De Méo",
        "mitchellh.com" => "Mitchell Hashimoto",
        "wtfmitchel.medium.com" => "Mitchel Lewis",
        "climate.mit.edu" => "MIT",
        "groups.csail.mit.edu" => "MIT",
        "telecom.csail.mit.edu" => "MIT",
        "www.csail.mit.edu" => "MIT",
        "web.mit.edu" => "MIT",
        "www.technologyreview.com" => "MIT Technology Review",
        "mitpress.mit.edu" => "MIT Press",
        "cwe.mitre.org" => "MITRE Corporation",
        "www.mitre.org" => "MITRE Corporation",
        "mitxela.com" => "Mixterla",
        "box.matto.nl" => "MJ Fransen",
        "www.chiefhealthcareexecutive.com" => "MJH Life Sciences",
        "s.mkws.sh" => "MKWS",
        "www.mnnonline.org" => "MNN",
        "mobiledevmemo.com" => "Mobile Dev Memo",
        "www.mobileindustryreview.com" => "Mobile Industry Review",
        "www.mobileworldlive.com" => "Mobile World Live",
        "moderndiplomacy.eu" => "Modern Diplomacy",
        "www.modernghana.com" => "Modern Ghana",
        "www.tweag.io" => "Modus Create LLC",
        "moldstud.com" => "MoldStud",
        "blog.mollywhite.net" => "Molly White",
        "citationneeded.news" => "Molly White",
        "www.citationneeded.news" => "Molly White",
        "www.mondaq.com" => "Mondaq",
        "mondaynote.com" => "Monday Note",
        "www.lemonde.fr" => "Le Monde",
        "www.mondo2000.com" => "Mondo2000",
        "news.mongabay.com" => "Mongabay",
        "www.mongodb.com" => "MongoDB",
        "www.monitor.co.ug" => "Monitor UG",
        "www.monolithicpower.com" => "Monolithic Power Systems Inc",
        "billingsgazette.com" => "Montana",
        "www.montelnews.com" => "Montel",
        "montrealgazette.com" => "Montreal Gazette",
        "monzo.com" => "Monzo Bank Limited",
        "moodle.com" => "Moodle",
        "www.lmspulse.com" => "MoodleNews LLC",
        "morningconsult.com" => "Morning Consult",
        "morningstarnews.org" => "Morning Star News",
        "morningstaronline.co.uk" => "Morning Star UK",
        "www.morningstar.com" => "Morningstar US",
        "linderud.dev" => "Morten Linderud",
        "www.techcircle.in" => "Mosaic Media Ventures Pvt Ltd",
        "www.motorauthority.com" => "MH Sub I LLC",
        "www.motortrend.com" => "Motor Trend Group LLC",
        "www.motorious.com" => "Motorius",
        "www.movieguide.org" => "Movie Guide",
        "try.popho.be" => "Moviuro",
        "moxie.org" => "Moxie Marlinspike",
        "last-chance-for-eidas.org" => "Mozilla",
        "addons.mozilla.org" => "Mozilla",
        "blog.mozilla.org" => "Mozilla",
        "developer.mozilla.org" => "Mozilla",
        "developer.mozilla.org" => "Mozilla",
        "research.mozilla.org" => "Mozilla",
        "foundation.mozilla.org" => "Mozilla",
        "hacks.mozilla.org" => "Mozilla",
        "internethealthreport.org" => "Mozilla",
        "www.mprnews.org" => "MPR News",
        "mrpogson.com" => "Mr Pogson",
        "marketresearchtelecast.com" => "MRT",
        "msfaccess.org" => "MSF",
        "www.msn.com" => "MSN",
        "mspoweruser.com" => "MS Poweruser",
        "www.muckrock.com" => "Muckrock",
        "mulloverthing.com" => "MullOverThing",
        "www.mulle-kybernetik.com" => "Mulle kybernetiK",
        "multicians.org" => "Multics",
        "multimedia.cx" => "Multimedia",
        "mullvad.net" => "Mullvad VPN",
        "muninetworks.org" => "Municipal Broadband",
        "muratbuffalo.blogspot.com" => "Murat Demirbas",
        "syntackle.com" => "Murtuzaali Surti",
        "syntackle.live" => "Murtuzaali Surti",
        "www.musee-orsay.fr" => "musées d'Orsay et de l'Orangerie",
        "musically.com" => "Music Ally Ltd",
        "www.musicgateway.com" => "Music Gateway Ltd",
        "musictech.com" => "MusicTech",
        "www.musicbusinessworldwide.com" => "Music Business Worldwide",
        "muted.io" => "Muted.IO",
        "mux.com" => "Mux",
        "muxup.com" => "Muxup",
        "mwl.io" => "MWL",
        "mxb.dev" => "MXB",
        "mxlinux.org" => "MX Linux",
        "www.mmtimes.com" => "Myanmar Times",
        "mycroft.ai" => "Mycroft",
        "n3wjack.net" => "N3wjack",
        "cloudbsd.xyz" => "Naguam",
        "www.nakedcapitalism.com" => "Naked Capitalism",
        "nakedsecurity.sophos.com" => "Naked Security",
        "www.nango.dev" => "Nango",
        "thenarwhal.ca" => "The Narwhal",
        "apod.nasa.gov" => "NASA",
        "blogs.nasa.gov" => "NASA",
        "earthobservatory.nasa.gov" => "NASA",
        "mars.nasa.gov" => "NASA",
        "www.jpl.nasa.gov" => "NASA",
        "www.nasa.gov" => "NASA",
        "www.nasdaq.com" => "Nasdaq",
        "www.simplermachines.com" => "Nat Bennett",
        "natanyellin.com" => "Natan Yellin",
        "nathanbrixius.wordpress.com" => "Nathan Brixius",
        "knowler.dev" => "Nathan Knowler",
        "toastytech.com" => "Nathan Lineback",
        "www.nfsmith.ca" => "Nathan Smith",
        "nathanupchurch.com" => "Nathan Upchurch",
        "endtimes.dev" => "Nathaniel",
        "theviewfromguppylake.blogspot.com" => "Nathaniel Borenstein",
        "nathansnelgrove.com" => "Nathaniel Snelgrove",
        "www.citizensadvice.org.uk" => "National Association of Citizens Advice Bureaux",
        "www.ncregister.com" => "National Catholic Register",
        "nationalflagfoundation.org" => "National Flag Foundation",
        "www.nationalgeographic.com" => "National Geographic",
        "www.nationalheraldindia.com" => "National Herald IN",
        "nationalinterest.org" => "National Interest",
        "www.maanmittauslaitos.fi" => "National Land Survey of Finland",
        "www.natlawreview.com" => "National Law Review US",
        "www.nationalobserver.com" => "National Observer CA",
        "nationalpost.com" => "National Post",
        "www.rephrain.ac.uk" => "National Research Centre on Privacy, Harm Reduction and Adversarial Influence Online",
        "www.nationalreview.com" => "National Review US",
        "new.nsf.gov" => "National Science Foundation",
        "www.nsf.gov" => "National Science Foundation",
        "www.secularism.org.uk" => "National Secular Society",
        "nsarchive.gwu.edu" => "The National Security Archive",
        "native-land.ca" => "Native Land Digital",
        "www.edinburghnews.scotsman.com" => "National World Publishing Ltd",
        "www.nationalworld.com" => "National World Publishing Ltd",
        "nativenewsonline.net" => "NativeNews Online",
        "nhqc3s.hq.nato.int" => "NATO",
        "www.nato.int" => "NATO",
        "www.nature.com" => "Nature",
        "nayadaur.tv" => "Nayadaur",
        "markuta.com" => "Naz Markuta",
        "www.nba.com" => "NBA",
        "www.msnbc.com" => "NBC",
        "www.nbcbayarea.com" => "NBC",
        "www.nbclosangeles.com" => "NBC",
        "nbcpalmsprings.com" => "NBC",
        "www.nbcboston.com" => "NBC",
        "www.nbcchicago.com" => "NBC",
        "www.nbcdfw.com" => "NBC",
        "www.nbcnews.com" => "NBC",
        "www.nbcnewyork.com" => "NBC",
        "www.nbcphiladelphia.com" => "NBC",
        "www.nbcmiami.com" => "NBCUniversal Media LLC",
        "www.nbcwashington.com" => "NBC",
        "ncac.org" => "NCAC",
        "research.nccgroup.com" => "NCC Group Research",
        "www.nccgroup.com" => "NCC Group Security Services Inc",
        "www.ncr-iran.org" => "NCRI",
        "nationalcybersecuritynews.today" => "NCSNT",
        "food.ndtv.com" => "NDTV",
        "gadgets360.com" => "NDTV",
        "gadgets.ndtv.com" => "NDTV",
        "sports.ndtv.com" => "NDTV",
        "www.ndtv.com" => "NDTV",
        "nebraskaexaminer.com" => "Nebraska Examiner",
        "madned.substack.com" => "NedUtzig",
        "nee.lv" => "Nee",
        "www.neelc.org" => "Neel Chauhan",
        "neighbourhood.ie" => "The Neighbourhoodie Software GmbH",
        "neil-clarke.com" => "Neil Clarke",
        "neilkakkar.com" => "Neil Kakkar",
        "www.neilmacy.co.uk" => "Neil Macy",
        "neil.computer" => "Neil Panchal",
        "criticaledtech.com" => "Neil Selwyn",
        "www.nejm.org" => "NEJM",
        "blog.nelhage.com" => "Nelson Elhage",
        "neosmart.net" => "Neo Smart",
        "housefresh.com" => "NeoMam Studios LtNeoMam Studios Ltd",
        "neoslab.com" => "Neos Lab",
        "packbat.neocities.org" => "Neo­packbats",
        "www.neowin.net" => "Neowin",
        "digitalenvironment.org" => "NERC UK",
        "en.neritam.com" => "Neritam",
        "neritam.wordpress.com" => "Neritam",
        "nesslabs.com" => "Ness Labs",
        "net2.com" => "Net2",
        "netblocks.org" => "Netblocks",
        "mail-index.netbsd.org" => "NetBSD",
        "netbsd0.blogspot.com" => "NetBSD",
        "blog.netbsd.org" => "NetBSD",
        "www.netbsd.org" => "NetBSD",
        "netflixtechblog.com" => "Netflix",
        "www.netgate.com" => "Netgate",
        "www.acm.nl" => "Netherlands",
        "netherlands.postsen.com" => "Netherlands Posts English",
        "blog.netlab.360.com" => "Netlab",
        "www.silicon.co.uk" => "Net Media Europe",
        "www.netnod.se" => "Netnod",
        "linux-training.be" => "NetSec BVBA",
        "www.forbesindia.com" => "Network 18 Media and Investments Ltd",
        "networkupstools.org" => "Network UPS Tools",
        "www.networkworld.com" => "Network World",
        "networthpick.com" => "Networth Pick",
        "cdn.netzpolitik.org" => "Netzpolitik",
        "netzpolitik.org" => "Netzpolitik",
        "newatlas.com" => "New Atlas",
        "www.newcastleherald.com.au" => "Newcastle Herald AU",
        "www.newcastlestar.com.au" => "Newcastle Star AU",
        "www.newdelhitimes.com" => "New Delhi Times IN",
        "neweasterneurope.eu" => "New Eastern Europe",
        "www.newelectronics.co.uk" => "New Electronics",
        "www.newenglishreview.org" => "New English Review",
        "www.neweurope.eu" => "New Europe",
        "www.nhpr.org" => "New Hampshire Public Radio",
        "cms.newindianexpress.com" => "New Indian Express",
        "www.newindianexpress.com" => "New Indian Express",
        "www.co.burlington.nj.us" => "Burlington County, New Jersey",
        "newjerseymonitor.com" => "New Jersey Montitor",
        "www.nj.com" => "New Jersey News",
        "newmatilda.com" => "New Matilda",
        "newnaratif.com" => "New Naratif",
        "newnetworks.com" => "New Networks",
        "newrepublic.com" => "New Republic",
        "www.newweather.org" => "New Weather Institue",
        "www.anchor.com.au" => "Newfold Digital Inc",
        "www.news.com.au" => "News AU",
        "thenewshawks.com" => "The NewsHawks",
        "thenewsprint.co" => "The Newsprint",
        "www.newsguardtech.com" => "NewsGuard Technologies Inc",
        "www.newsroomrobots.com" => "Substack Inc",
        "www.eastlothiancourier.com" => "Newsquest Media Group Ltd",
        "www.enfieldindependent.co.uk" => "Newsquest Media Group Ltd",
        "www.hackneygazette.co.uk" => "Newsquest Media Group Ltd",
        "www.hampshirechronicle.co.uk" => "Newsquest Media Group Ltd",
        "www.greenocktelegraph.co.uk" => "Newsquest Media Group Ltd",
        "www.salisburyjournal.co.uk" => "Newsquest Media Group Ltd",
        "www.thenorthernecho.co.uk" => "Newsquest Media Group Ltd",
        "www.thenational.wales" => "Newsquest Media Group Ltd",
        "www.oxfordmail.co.uk" => "Newsquest Media Group Ltd",
        "www.newscientist.com" => "New Scientist",
        "www.newsmax.com" => "Newsmax",
        "www.newstatesman.com" => "New Statesman",
        "www.newsweek.com" => "Newsweek",
        "newvirginiapress.com" => "New Virginia Press",
        "www.nycbar.org" => "New York City Bar",
        "www.nydailynews.com" => "New York Daily News",
        "www.nysun.com" => "New York Sun",
        "dfs.ny.gov" => "New York State",
        "www.nysenate.gov" => "New York State Senate",
        "archive.nytimes.com" => "New York Times",
        "nytco-assets.nytimes.com" => "New York Times",
        "static01.nyt.com" => "New York Times",
        "www.nytco.com" => "New York Times",
        "www.nytimes.com" => "New York Times",
        "www.newyorker.com" => "New Yorker",
        "www.hastingsdc.govt.nz" => "Hastsings Distric Council, New Zealand",
        "legislation.govt.nz" => "New Zealand",
        "comcom.govt.nz" => "Commerce Commission of New Zealand",
        "nzhistory.govt.nz" => "New Zealand",
        "thespinoff.co.nz" => "New Zealand",
        "www.odt.co.nz" => "New Zealand",
        "fij.ng" => "Foundation for Investigative Journalism Nigeria",
        "www.newstimes.com.ng" => "News Times Nigeria",
        "www.nzherald.co.nz" => "New Zealand Herald",
        "www.wpri.com" => "Nexstar Media Group Inc",
        "www.krqe.com" => "Nexstar Media Inc",
        "wreg.com" => "Nexstar Media Inc",
        "www.valleycentral.com" => "Nexstar Media Inc",
        "wgntv.com" => "Nexstar Media Inc",
        "nextcloud.com" => "Next Cloud",
        "www.nextgames.com" => "Next Games",
        "www.nextinnonprofits.com" => "Next in Nonprofits",
        "tech.nextroll.com" => "Next Roll",
        "www.nexttv.com" => "Next TV",
        "www.nextgov.com" => "Nextgov",
        "nextitsecurity.com" => "Next IT Security",
        "nfu.org" => "NFU",
        "www.nhs.uk" => "National Health Service UK",
        "mailman.nginx.org" => "Nginx",
        "trac.nginx.org" => "Nginx",
        "nguyen.cincinnati.oh.us" => "Nguyễn",
        "www.rechargenews.com" => "NHST Media Group",
        "blog.relyabilit.ie" => "Niall Murphy",
        "thenib.com" => "The Nib",
        "blog.nicco.love" => "Niccolò Venerandi",
        "www.ncameron.org" => "Nicholas Cameron",
        "ludocode.com" => "Nicholas Fraser",
        "ntietz.com" => "Nicholas Tietz-Sokolsky",
        "pointlessramblings.com" => "Nick Barrett",
        "www.ncartron.org" => "Nico Cartron",
        "nicochilla.com" => "Nico Chilla",
        "koolinus.wordpress.com" => "Nicola Losito",
        "nicolalosito.i" => "Nicola Losito",
        "cropp.blog" => "Nicolas Cropp",
        "fratti.ch" => "Nicolas F",
        "blog.frankel.ch" => "Nicolas Fränkel",
        "thejollyteapot.com" => "Nicolas Magand",
        "niconiconi.neocities.org" => "Niconiconi",
        "nicole.express" => "Nicole Express",
        "neilzone.co.uk" => "Niel Brown",
        "nielscautaerts.xyz" => "Niels Cautaerts",
        "provos.org" => "Niels Provos",
        "www.provos.org" => "Niels Provos",
        "www.niemanlab.org" => "Nieman Lab",
        "thenigerialawyer.com" => "Nigeria",
        "www.thecable.ng" => "Nigeria",
        "www.thetimes.com.ng" => "Nigeria",
        "independent.ng" => "Nigeria",
        "thenationonlineng.net" => "Nigeria",
        "gazettengr.com" => "Nigeria",
        "nationaldailyng.com" => "Nigeria",
        "www.thenigerianvoice.com" => "Nigeria",
        "pmnewsnigeria.com" => "Nigeria",
        "www.premiumtimesng.com" => "Nigeria",
        "www.pulse.ng" => "Nigeria",
        "tribuneonlineng.com" => "Nigerian Tribune",
        "thenightgallery.wordpress.com" => "Night Gallery",
        "www.nightwish.com" => "Nightwish",
        "pubmed.ncbi.nlm.nih.gov" => "NIH",
        "www.ncbi.nlm.nih.gov" => "NIH",
        "nikhilism.com" => "Nikhil Marathe",
        "laplab.me" => "Nikita Lapkov",
        "tonsky.me" => "Nikita Prokopov",
        "sobolevn.me" => "Nikita Sobolev",
        "asia.nikkei.com" => "Nikkei",
        "nikokultalahti.com" => "Niko Kultalahti",
        "pragmaticpineapple.com" => "Nikola Đuza",
        "nikola.kotur.org" => "Nikola Kotur",
        "nilcoalescing.com" => "Nil Coalescing LtĐuzal",
        "ninazumel.com" => "Nina B Zumel",
        "unravelweb.dev" => "Nishu Goel",
        "nl.usembassy.gov" => "US Embassy and Consulate",
        "csrc.nist.gov" => "US NIST",
        "nvd.nist.gov" => "US NIST",
        "nvlpubs.nist.gov" => "US NIST",
        "pages.nist.gov" => "US NIST",
        "www.nist.gov" => "US NIST",
        "nxos.org" => "Nitrux",
        "www.cyberciti.biz" => "nixCraft",
        "nixos.wiki" => "NixOS",
        "nltimes.nl" => "NL Times",
        "ncatlab.org" => "nLab",
        "blog.nlnetlabs.nl" => "NLNet Foundation",
        "nlnet.nl" => "NLNet Foundation",
        "guitar.com" => "Guitar (NME Networks)",
        "www.nme.com" => "NME Networks",
        "blog.noredink.com" => "No Red Ink",
        "nosystemd.org" => "No Systemd",
        "blog.noip.com" => "No-IP",
        "arctic.noaa.gov" => "NOAA",
        "oceanservice.noaa.gov" => "NOAA",
        "www.noaa.gov" => "NOAA",
        "www.fisheries.noaa.gov" => "NOAA Fisheries",
        "codeofhonor.substack.com" => "Noah",
        "codefol.io" => "Noah Gibbs",
        "thetechenabler.substack.com" => "Noah Hall",
        "noahliebman.net" => "Noah Liebman",
        "noahpinion.substack.com" => "Noah Smith",
        "chomsky.info" => "Noam Chomsky",
        "noamzeise.com" => "Noam Zeise",
        "bitecode.substack.com" => "Nobody has time for Python",
        "nflatrea.bearblog.dev" => "Noë Flatreaud",
        "noelrappin.com" => "Noel Rappin",
        "www.noip.com" => "NoIP",
        "www.nokia.com" => "Nokia",
        "nokiamob.net" => "Nokia Mob",
        "www.nola.com" => "NOLA",
        "nolanlawson.com" => "Nolan Lawson",
        "eieio.games" => "Nolen Royalty",
        "mississippitoday.org" => "Nonprofit Mississippi News",
        "nonstrict.eu" => "Nonstrict B V",
        "noratrieb.dev" => "Noratrieb",
        "www.preining.info" => "Norbert Preining",
        "nordicmonitor.com" => "Nordic Research and Monitoring Network",
        "nordvpn.com" => "NordVPN",
        "presse.no" => "Norsk Presseforbund",
        "www.ncsbe.gov" => "North Carolina",
        "wilmingtonjournal.com" => "North Carolina",
        "www.nipolicingboard.org.uk" => "Northern Ireland Policing Board UK",
        "www.nsnews.com" => "North Shore News",
        "northerntimes.nl" => "The Northern Times",
        "digital.library.unt.edu" => "uni North Texas",
        "localnewsinitiative.northwestern.edu" => "uni Northwestern",
        "copyright.nova.edu" => "uni Nova Southeastern",
        "now.northropgrumman.com" => "Northrop Grumman",
        "us.norton.com" => "Gen Digital Inc",
        "digitalpreservation-blog.nb.no" => "Norway",
        "www.nrk.no" => "Norway",
        "www.aftenposten.no" => "Norway",
        "norwaytoday.info" => "Norway",
        "www.notebookcheck.net" => "Notebook Check",
        "blog.notryan.com" => "Not Ryan",
        "magazine.nd.edu" => "Notre Dame Magazine",
        "www.nottinghampost.com" => "Nottinghamshire Post",
        "nowtoronto.com" => "Now Toronto",
        "novaramedia.com" => "Novara Media",
        "ktvz.com" => "NPG of Oregon",
        "alaskapublic.org" => "NPR",
        "indianapublicmedia.org" => "NPR",
        "text.npr.org" => "NPR",
        "www.npr.org" => "NPR",
        "www.wosu.org" => "NPR",
        "wysu.org" => "NPR",
        "www.kut.org" => "NPR",
        "nrb.org" => "NRB",
        "www.nrdc.org" => "NRDC",
        "www.nsa.gov" => "NSA",
        "www.nmedia.net" => "NSH",
        "www.nsta.org" => "NSTA",
        "wrt.nth.io" => "NTH",
        "support.ntp.org" => "NTP",
        "www.ntpsec.org" => "NTPsec",
        "blog.nuclearsecrecy.com" => "Nuclear Secrecy",
        "www.nuj.org.uk" => "NUJ",
        "nulltx.com" => "Null TX",
        "blog.numericcitizen.me" => "Numeric Citizen",
        "nusenu.medium.com" => "Nusenu",
        "www.nutsvolts.com" => "Nuts And Volts",
        "www.nuug.no" => "NUUG",
        "blogs.nvidia.com" => "NVIDIA Corporation",
        "blog.nviso.eu" => "NVISO Labs",
        "nycbug1.nycbug.org" => "NYCBUG",
        "nymag.com" => "NYMag",
        "noyb.eu" => "NYOB",
        "decider.com" => "NYP Holdings Inc",
        "nypost.com" => "NYPost",
        "www.nzyme.org" => "Nzyme.org",
        "nyxspace.com" => "Nyx Space",
        "oaklandcountyblog.com" => "Oakland County MI",
        "www.netlib.org" => "Oak Ridge National Laboratory",
        "www.oasis-open.org" => "OASIS",
        "oberlinreview.org" => "Oberlin College",
        "obnam.org" => "Obnam",
        "observer.com" => "Observer Media",
        "blog.rlwinm.de" => "Occasionally Useful Notes",
        "reliefweb.int" => "OCHA",
        "www.omct.org" => "OCMT",
        "opencovidpledge.org" => "OCP",
        "www.oddbird.net" => "OddBird",
        "odysee.com" => "Odysee Inc",
        "otavio.cc" => "Otávio C",
        "adepts.of0x.cc" => "Of0x",
        "www.ofcom.org.uk" => "OFCOM",
        "off-guardian.org" => "Off Guardian",
        "www.legislature.ohio.gov" => "Ohio",
        "oicanadian.com" => "OI Canadian",
        "oilprice.com" => "Oil Price",
        "www.oilshell.org" => "Oil Shell",
        "oisinmoran.com" => "Oisín Moran",
        "tulsaworld.com" => "TulsaWorld",
        "okpolicy.org" => "Oklahoma Policy Institute",
        "www.olafalders.com" => "Olaf Alders",
        "oldvcr.blogspot.com" => "Old VCR",
        "olimex.wordpress.com" => "Olimex",
        "www.olimex.com" => "Olimex",
        "www.theolivepress.es" => "The Olive Press",
        "oliver.st" => "Oliver",
        "ols.wtf" => "Oliver Leaver Smith",
        "fullystacked.net" => "Ollie Williams",
        "madebyoll.in" => "Ollin Boer Bohan",
        "www.palmefonden.se" => "The Olof Palme Memorial Fund",
        "onemileatatime.com" => "OMAAT",
        "www.omarpolo.com" => "Omar Polo",
        "omar.website" => "Omar Rizwan",
        "www.omeronsecurity.com" => "Omer Singer",
        "www.omgubuntu.co.uk" => "OMG Ubuntu",
        "phys.org" => "Omicron Limited",
        "om.co" => "Om Malik",
        "ondrejcertik.com" => "Ondřej Čertík",
        "ondrejsevcik.com" => "Ondrej Sevcik",
        "www.sleepfoundation.org" => "OneCare Media LLC",
        "onelawforall.org.uk" => "One Law For All UK",
        "theonion.com" => "The Onion",
        "www.theonion.com" => "The Onion",
        "www.online-tech-tips.com" => "Online Tech Tips",
        "onlykey.io" => "OnlyKey",
        "www.windytan.com" => "Oona Räisänen",
        "ooni.org" => "OONI",
        "www.priv.gc.ca" => "OPCCA",
        "www.o3de.org" => "Open 3D Engine",
        "openai.com" => "Open AI",
        "letter.open-web-advocacy.org" => "Open Letter to Tim Cook",
        "ftp.openbsd.org" => "OpenBSD",
        "www.openbsd.org" => "OpenBSD",
        "xenocara.org" => "OpenBSD",
        "www.openbsdfoundation.org" => "The OpenBSD Foundation",
        "webzine.puffy.cafe" => "OpenBSD Webzine",
        "www.opendemocracy.net" => "Open Democracy",
        "opencollective.com" => "Open Collective",
        "www.openculture.com" => "Open Culture LLC",
        "en.odfoundation.eu" => "Open Dialog Foundation",
        "pubs.opengroup.org" => "The Open Group Library",
        "abopen.com" => "Open Hardware Consultancy",
        "www.openlogic.com" => "Open Logic",
        "www.openpr.com" => "open PR",
        "openradar.appspot.com" => "Open Radar",
        "www.openranpolicy.org" => "OpenRAN",
        "www.openreach.co.uk" => "OpenRreach Ltd",
        "www.openrightsgroup.org" => "OpenRightsGroup",
        "www.openssl.org" => "OpenSSL",
        "www.ouvrirlascience.fr" => "Open Science",
        "www.opensecrets.org" => "Open Secrets",
        "www.osfc.io" => "Open Source Firmware Conference",
        "www.opensourceforu.com" => "Open Source For U",
        "grsecurity.net" => "Open Source Security Inc",
        "opensourcesecurity.io" => "Open Source Security (Audio Show)",
        "anchor.fm" => "Open Source Startup Podcast",
        "opensource.org" => "Open Source Initiative",
        "openeveryone.substack.com" => "Open Source For Everyone",
        "lists.mindrot.org" => "OpenSSH",
        "www.openssh.com" => "OpenSSH",
        "openstandards.nz" => "Open Standards NZ",
        "openvpn.net" => "OpenVPN",
        "www.openwall.com" => "Openwall",
        "openzfs.org" => "OpenZFS",
        "opguides.info" => "Op Guides",
        "respectfulinsolence.com" => "Orac",
        "www.oecd.org" => "Organisation for Economic Co-operation and Development",
        "www.socialmediasafety.org" => "Organization for Social Media Safety",
        "www.o-ran.org" => "O-RAN",
        "www.oc-breeze.com" => "Orange County Breeze",
        "www.ocregister.com" => "Orange County Register",
        "lists.orbitalfox.eu" => "Orbital Fox",
        "www.oreilly.com" => "OReilly",
        "blog.orhun.dev" => "Orhun Parmaksız",
        "www.orlandoweekly.com" => "Orlando Weekly",
        "www.orfonline.org" => "Observer Research Foundation",
        "www.osnews.com" => "OS News",
        "ovr.today" => "Oskar van Rijswijk",
        "wickstrom.tech" => "Oskar Wickström",
        "osnote.com" => "OSNote",
        "osshistory.org" => "OSS History",
        "cippic.ca" => "uni Ottawa",
        "ottawacitizen.com" => "Ottawa",
        "ottertune.com" => "OtterTune",
        "www.drijf.net" => "Otto Moerbeek",
        "ourworldindata.org" => "Our World in Data",
        "softwarecrisis.dev" => "Out of the Software Crisis",
        "www.outlookindia.com" => "Outlook Publishing India Pvy Ltd",
        "www.outlookbusiness.com" => "Outlook Publishing India Pvy Ltd",
        "velo.outsideonline.com" => "Outside Interactive Inc",
        "www.outsideonline.com" => "Outside Interactive Inc",
        "outsidethebeltway.com" => "Outside The Beltway",
        "www.outsidethebeltway.com" => "Outside The Beltway",
        "overpopulation-project.com" => "Overpopulation",
        "www.overthinkingit.com" => "Overthinking It",
        "www.ovh.ie" => "OVH",
        "owengage.com" => "Owen Gage",
        "owlcation.com" => "Owlcation",
        "theowp.org" => "OWP",
        "policy-practice.oxfam.org" => "Oxfam",
        "www.oxfam.org" => "Oxfam",
        "academic.oup.com" => "Oxford University Press",
        "oxide.computer" => "Oxide",
        "www.ozy.com" => "OZY",
        "www.legis.state.pa.us" => "PA General Assembly",
        "morepablo.com" => "Pablo Meier",
        "blog.trends.tf" => "Pair of Pared Pears",
        "blog.packagecloud.io" => "Computology LLC",
        "pagedout.institute" => "Paged Out!!",
        "pagosadailypost.com" => "Pagosa Daily Post",
        "pakobserver.net" => "Pakistan",
        "www.thefridaytimes.com" => "Pakistan",
        "www.geo.tv" => "Pakistan",
        "propakistani.pk" => "Pakistan",
        "www.pakistantoday.com.pk" => "Pakistan",
        "forum.palemoon.org" => "Palemoon",
        "palladiummag.com" => "Palladium Magazine",
        "unit42.paloaltonetworks.com" => "Palo Alto Networks",
        "www.cityofpaloalto.org" => "Palo Alto, California",
        "www.pandasecurity.com" => "Panda Security SLU",
        "www.paulox.net" => "Paolo Melchiorre",
        "papersplease.org" => "Papers Please",
        "paperswithcode.com" => "Papers With Code",
        "www.papuansbehindbars.org" => "Papuans Behind Bars",
        "blog.paradedb.com" => "ParadeDB",
        "www.parallelmirror.com" => "Parallel Mirror",
        "www.parisbeacon.com" => "Paris Beacon News",
        "informatimago.free.fr" => "Pascal Bourguignon",
        "www.patagonia.com" => "Patagonia",
        "www.patentlyapple.com" => "Patently Apple",
        "patentpandas.org" => "Patent Pandas",
        "www.againstmonopoly.org" => "Patents",
        "www.patheos.com" => "Patheos",
        "blog.patreon.com" => "Patreon",
        "news.patreon.com" => "Patreon",
        "www.patreon.com" => "Patreon",
        "www.patrick-breyer.de" => "Patrick Breyer",
        "paedubucher.ch" => "Patrick Bucher",
        "pubby.games" => "Patrick Jordan Bene",
        "venam.nixers.net" => "Patrick Louis",
        "www.kalzumeus.com" => "Patrick McKenzie",
        "pnewman.org" => "Partick Newman",
        "esham.io" => "Benjamin Esham",
        "www.hardill.me.uk" => "Benjamin John Hardill",
        "astro-gr.org" => "Pau Amaro Seoane",
        "www.paubox.com" => "Paubox Inc",
        "paularmstrong.dev" => "Paul Armstrong",
        "www.strassmann.com" => "Paul A Strassmann",
        "pboyd.io" => "Paul Boyd",
        "peateasea.de" => "Paul Chochrane",
        "www.paulcraigroberts.org" => "Paul Craig Roberts",
        "pdfernhout.net" => "Paul D Fernhout",
        "libertysys.com.au" => "Paul Gear",
        "www.madboa.com" => "Paul Heinlein",
        "paulrobertlloyd.com" => "Paul Robert Lloyd",
        "www.pauladamsmith.com" => "Paul Smith",
        "paulstamatiou.com" => "Paul Stamatiou",
        "www.paulosyibelo.com" => "Paulos Yibelo",
        "thepavlovictoday.com" => "The Pavlovic Today",
        "pawelgrzybek.com" => "Paweł Grzybek",
        "katafrakt.me" => " Paweł Świątkowski",
        "www.greatlakesnow.org" => "PBS",
        "www.pbs.org" => "PBS",
        "www.pbsutah.org" => "PBS",
        "www.pcengines.ch" => "PC Engines",
        "www.pcgamer.com" => "PC Gamer",
        "www.pcgamesn.com" => "PCGamesN",
        "pclosmag.com" => "PCLinuxOS Magazine",
        "uk.pcmag.com" => "PC Mag",
        "www.pcmag.com" => "PC Mag",
        "pcper.com" => "PC Perspective",
        "pc-tablet.com" => "PC-Tablet",
        "www.pcworld.com" => "PC World",
        "www.pcbway.com" => "PCBWay",
        "www.lifehacker.com.au" => "Pedestrian Group",
        "blog.pcora.eu" => "Pedro",
        "blog.peerdb.io" => "PeerDB",
        "blog.peerverse.space" => "Peerverse",
        "penberg.org" => "Pekka Enberg",
        "www.pmail.com" => "Pengasus Mail",
        "pen.org" => "Pen America",
        "www.penguin.co.uk" => "Penguin Books",
        "www.artforum.com" => "Penske Media Corporation",
        "www.billboard.com" => "Penske Media Corporation",
        "people.com" => "People Magazine",
        "peoplesdispatch.org" => "Peoples Dispatch",
        "peppermintos.com" => "PeppermintOS",
        "wwm.percona.com" => "Percona",
        "periferiesurbanes.org" => "Perifèries Urbanes",
        "security.metacpan.org" => "Perl",
        "tprc.us" => "Perl",
        "act.yapc.eu" => "Perl",
        "yapcjapan.org" => "Perl",
        "perladvent.org" => "Perl",
        "perldoc.perl.org" => "Perl",
        "blogs.perl.org" => "Perl",
        "log.perl.org" => "Perl",
        "perlconference.us" => "Perl",
        "perlmaven.com" => "Perl",
        "perlmonks.org" => "PerlMonks",
        "www.perlmonks.org" => "PerlMonks",
        "perlweeklychallenge.org" => "Perl",
        "news.perlfoundation.org" => "Perl",
        "perlweekly.com" => "Perl",
        "squareperl.com" => "Perl",
        "www.perl.com" => "Perl",
        "pdl.perl.org" => "Perl Data Language",
        "perlhacks.com" => "Perl Hacks",
        "prma.dev" => "Perma",
        "www.permaculturenews.org" => "Permaculture Research Institute",
        "peroty.micro.blog" => "Peroty",
        "petapixel.com" => "Peta Pixel",
        "lotech.co.uk" => "Pete",
        "explodingcomma.com" => "Pete Brown",
        "petewarden.com" => "Pete Warden",
        "peterbabic.dev" => "Peter Babic",
        "peter.czanik.hu" => "Peter 'CzP' Czanik",
        "peter.eisentraut.org" => "Peter Eisentraut",
        "bad.network" => "Peter Hessler",
        "boredzo.org" => "Peter Hosey",
        "petermalmgren.com" => "Peter Malmgren",
        "nxdomain.no" => "Peter N M Hansteen",
        "norvig.com" => "Peter Norvig",
        "www.peteronion.org.uk" => "Peter Onion",
        "www.peterboroughtoday.co.uk" => "Peterborough Telegraph",
        "blog.peterruppel.de" => "PeterRuppel",
        "pitr.ca" => "Peter Vernigorov",
        "catonmat.net" => "Peteris Krumins",
        "petrovday.com" => "Petrov Day",
        "www.pewtrusts.org" => "Pew Charitable Trusts",
        "www.pewresearch.org" => "Pew Reseach Center",
        "philbooth.me" => "Phil Booth",
        "philbull.wordpress.com" => "Phil Bull",
        "notes.eatonphil.com" => "Phil Eaton",
        "stollerys.co.uk" => "Phil Stollerys",
        "philip.greenspun.com" => "Philip Greenspun",
        "ruzkuku.com" => "Philip Kaludercic",
        "www.philipotoole.com" => "Philip O'Toole",
        "news.abs-cbn.com" => "Phillippines",
        "www.cnnphilippines.com" => "Phillippines",
        "phildini.dev" => "Philip James",
        "philzimmermann.com" => "Phil Zimmermann",
        "phirephoenix.com" => "Phirephoenix",
        "www.phonearena.com" => "Phone Arena",
        "openbenchmarking.org" => "Phoronix Media",
        "www.phoronix.com" => "Phoronix",
        "blog.jetbrains.com" => "PHP",
        "externals.io" => "PHP",
        "phr.org" => "PHR",
        "phrack.org" => "Phrack",
        "pimylifeup.com" => "Pi My Life Up",
        "pipe.pico.sh" => "pico.sh LLC",
        "docs.pikvm.org" => "PiKVM Handbook",
        "www.privateinternetaccess.com" => "PIA",
        "plbrault.com" => "Pier‑Luc Brault",
        "delroth.net" => "Pierre 'delroth' Bourdon",
        "pierre.equoy.fr" => "Pierre Equoy",
        "ambrevar.xyz" => "Pierre Neidhardt",
        "pijul.org" => "Pijul",
        "www.pillarcatholic.com" => "The Pillar",
        "blog.pimoroni.com" => "Pimoroni",
        "pine64.org" => "Pine64",
        "www.pine64.org" => "Pine64",
        "www.thepinknews.com" => "PinkNews",
        "european-pirateparty.eu" => "Pirate Party",
        "calpirg.org" => "PIRG",
        "pirg.org" => "PIRG",
        "uspirg.org" => "PIRG",
        "uspirgedfund.org" => "PIRG",
        "blog.pitest.org" => "Pi Test",
        "pixel-gallery.co.uk" => "Pixel Gallery",
        "www.pixelstech.net" => "Pixels Tech",
        "pivot-to-ai.com" => "Pivot to AI",
        "pjmedia.com" => "PJ Media",
        "www.plagiarismtoday.com" => "Plagiarism Today",
        "planetscale.com" => "PlanetScale",
        "planetsmarts.com" => "Planet Smarts",
        "www.planetary.org" => "The Planetary Society",
        "www.planetizen.com" => "Planetizen",
        "en.epicenter.works" => "Plattform Grundrechtspolitik",
        "platform.sh" => "Platform.sh GmbH",
        "plausible.io" => "Plausible",
        "journals.plos.org" => "PLOS",
        "plumconsulting.co.uk" => "Plumb Consulting",
        "www.pmnewsnigeria.com" => "PM News NG",
        "www.pnas.org" => "PNAS",
        "www.pocket-lint.com" => "Pocket Lint",
        "pocketnow.com" => "Pocket Now",
        "scienceinpoland.pap.pl" => "Poland",
        "www.gov.pl" => "Poland",
        "notesfrompoland.com" => "Poland",
        "poland.postsen.com" => "Poland",
        "polandin.com" => "Poland In",
        "polarjournal.ch" => "Polar Journal",
        "polarhive.net" => "Polarhive",
        "news.met.police.uk" => "Police UK",
        "www.lapoliticaonline.com" => "La Política Online S A",
        "www.politico.eu" => "Politico",
        "www.politico.com" => "Politico LLC",
        "www.eenews.net" => "Politico LLC",
        "www.politicususa.com" => "PoliticusUSA LLC",
        "polypane.app" => "Polypane B V",
        "pomed.org" => "POMED",
        "poniesandlight.co.uk" => "Ponies and Light Ltd",
        "blog.popcorncomputer.com" => "Popcorn Computer",
        "www.popularmechanics.com" => "Popular Mechanics",
        "www.popsci.com" => "Popular Science",
        "portswigger.net" => "Port Swigger",
        "www.pressherald.com" => "Portland Press Herald",
        "law360.com" => "Portfolio Media Inc",
        "www.law360.com" => "Portfolio Media Inc",
        "portswigger.net" => "Port Swigger",
        "www.positech.co.uk" => "Positech Games",
        "positivemoney.org" => "Positive Money",
        "blog.ptsecurity.com" => "Positive Technologies",
        "www.ptsecurity.com" => "Positive Technologies",
        "thepostmillennial.com" => "Post Millennial",
        "postopen.org" => "Post-Open",
        "www.postgresql.org" => "PostgreSQL",
        "postmarketos.org" => "postmarketOS",
        "www.powazek.com" => "Derek Powazek",
        "blog.powerdns.com" => "PowerDNS",
        "www.powerpc-notebook.org" => "GNU Linux PowerPC Notebook",
        "www.politifact.com" => "Poynter Institute",
        "www.poynter.org" => "Poynter Institute",
        "www.pragmaticlinux.com" => "Pragmatic Linux",
        "microblog.pratikmhatre.com" => "Pratik",
        "praveshkoirala.com" => "Pravesh Koirala",
        "misfra.me" => "Preetam Jinka",
        "www.premierchristianity.com" => "Premier Christianty",
        "community.element14.com" => "Premier Farnell Ltd",
        "concordia.at" => "Presseclub Concordia",
        "pressgazette.co.uk" => "Press Gazette",
        "www.pressgazette.co.uk" => "Press Gazette",
        "pthorpe92.dev" => "Preston Thorpe",
        "www.pri.org" => "PRI",
        "priceofoil.org" => "Price Of Oil",
        "priceonomics.com" => "Priceonomics",
        "www.princewilliamtimes.com" => "Prince William Times",
        "www.prisonlegalnews.org" => "Prison Legal News",
        "petsymposium.org" => "Privacy Enhancing Technologies Symposium",
        "www.petsymposium.org" => "Privacy Enhancing Technologies Symposium",
        "privacyfirst.nl" => "Privacy First",
        "blog.privacyguides.org" => "Privacy Guides",
        "privacytests.org" => "PrivacyTests.org",
        "privacyinternational.org" => "Privacy International",
        "blog.privacytools.io" => "Privacy Tools",
        "gdpr.report" => "Priv Sec Global",
        "www.prnewswire.com" => "PR Newswire",
        "www.globalcement.com" => "Pro Global Media",
        "productiongap.org" => "Production Gap Report",
        "www.programmableweb.com" => "Programmable Web",
        "pldb.com" => "Programming Language DataBase",
        "www.dtnpf.com" => "Progressive Farmer DTN",
        "www.projectcensored.org" => "Project Censored",
        "runeberg.org" => "Project Runeberg",
        "www.project-syndicate.org" => "Project Syndicate",
        "project-trident.org" => "Project Trident",
        "features.propublica.org" => "Pro Publica",
        "www.propublica.org" => "Pro Publica",
        "www.proofpoint.com" => "Proofpoint",
        "www.prosus.com" => "Prosus",
        "www.protocol.com" => "Protocol",
        "proton.me" => "Proton A G",
        "protonmail.com" => "Proton A G",
        "protonvpn.com" => "ProtonVPN",
        "en.protothema.gr" => "Protothema",
        "blog.prototypr.io" => "Prototypr",
        "providencemag.com" => "Provedence Magagzine",
        "www.prri.org" => "PRRI",
        "www.prwatch.org" => "PR Watch",
        "www.prweb.com" => "PR Web",
        "www.psypost.org" => "PsyPost",
        "cdn.aaai.org" => "The Association for the Advancement of Artificial Intelligence (AAAI)",
        "www.psychologicalscience.org" => "Association for Psychological Science",
        "www.psychologytoday.com" => "Psychology Today",
        "www.publictechnology.net" => "PT",
        "www.citizen.org" => "Public Citizen",
        "publicdomainmovie.net" => "Public Domain Movies",
        "publicdomainreview.org" => "Public Domain Review",
        "publicintegrity.org" => "Public Integrity",
        "publicinterestnetwork.org" => "Public Interest Network",
        "publicknowledge.org" => "Public Knowledge",
        "www.publicmediaalliance.org" => "Public Media Alliance",
        "publicseminar.org" => "Public Seminar",
        "www.publish0x.com" => "Publish0x",
        "www.publishersweekly.com" => "Publishers Weekly",
        "publishingperspectives.com" => "Publishing Perspectives",
        "www.pulseitmagazine.com.au" => "Pulse IT AU",
        "pulsesecurity.co.nz" => "Pulse Security Ltd",
        "www.pulumi.com" => "Pulumi",
        "punchng.com" => "Punch NG",
        "punkx.org" => "Punkx",
        "politicalviolenceataglance.org" => "PVAG",
        "www.cerias.purdue.edu" => "Purdue University",
        "blog.purestorage.com" => "Pure Storage Inc",
        "puri.sm" => "Purism",
        "us.pycon.org" => "PyCon US",
        "llm.datasette.io" => "Python",
        "docs.python.org" => "Python",
        "peps.python.org" => "Python",
        "www.pythonmorsels.com" => "Python",
        "pip.pypa.io" => "Python",
        "blog.pypi.org" => "Python Package Index",
        "pyfound.blogspot.com" => "Python Software Foundation",
        "pythonspeed.com" => "Python Speed",
        "engineering.q42.nl" => "Q42 Engineering",
        "qemu-advent-calendar.org" => "Qemu",
        "www.quintessenz.org" => "Quintessenz",
        "rexarski.com" => "Qiū Ruì",
        "qorg11.net" => "Qorg",
        "qrp-popcorn.blogspot.com" => "QRP HomeBuilder",
        "www.qt.io" => "Qt",
        "quadrant.org.au" => "Quadrant",
        "www.qualcomm.com" => "Qualcomm",
        "blog.qualys.com" => "Qualys",
        "www.qualys.com" => "Qualys",
        "www.quantamagazine.org" => "Quanta Magazine",
        "blog.quarkslab.com" => "Quarkslab",
        "qz.com" => "Quartz",
        "eprints.qut.edu.au" => "Queensland University of Technology",
        "www.qhrc.qld.gov.au" => "Queensland Human Rights Commission AU",
        "qsantos.fr" => "Quentin Santos",
        "qsapp.com" => "Quicksilver",
        "quillette.com" => "Quillette",
        "quindarius.com" => "Quin Ali Lyles-Wood",
        "www.quirksmode.org" => "Quirks Mode",
        "r2c.dev" => "R2C",
        "rjfaas.com" => "R J Faas",
        "r-graph-gallery.com" => "The R Graph Gallery",
        "rscottjones.com" => "R Scott Jones",
        "www.rstreet.org" => "R Street Institute",
        "ryxcommar.com" => "R Y X R",
        "rmkit.dev" => "Rmkit",
        "www.railtarget.eu" => "RT Publishing s r o",
        "rachsmith.com" => "Rach Smith",
        "rachelbythebay.com" => "Rachel",
        "kwon.nyc" => "Rachel J Kwon",
        "rachbelaid.com" => "Rachid Belaid",
        "www.rkoucha.fr" => "Rachid Koucha",
        "docs.racket-lang.org" => "Racket",
        "programmingwithstyle.com" => "Radek Koziel",
        "radfordneal.wordpress.com" => "Radford Neal",
        "en.radiofarda.com" => "Radio Farda",
        "www.radiofree.org" => "Radio Free",
        "radioink.com" => "Radio Ink",
        "forum.radxa.com" => "Radxa Community",
        "rsadowski.de" => "Rafael Sadowski",
        "www.sizeofvoid.org" => "Rafael Sadowski",
        "www.railtech.com" => "RailTech",
        "poisel.info" => "Rainer Poisel",
        "rainforestfoundation.org" => "Rainforest Foundation US",
        "www.rainforest-alliance.org" => "Rainforest Alliance",
        "rairfoundation.com" => "RAIR Foundation",
        "rakhesh.com" => "Rakhesh Sasidharan",
        "course.raku.org" => "Rakulang",
        "docs.raku.org" => "Rakulang",
        "raku-advent.blog" => "Rakulang",
        "rakudoweekly.blog" => "Rakulang",
        "www.newsobserver.com" => "Raleigh News And Observer",
        "ramble.pw" => "Ramble",
        "rtpg.co" => "Raphael",
        "www.rappler.com" => "Rappler",
        "datasheets.raspberrypi.com" => "Raspberry Pi",
        "forums.raspberrypi.com" => "Raspberry Pi",
        "hackspace.raspberrypi.org" => "Raspberry Pi",
        "magpi.raspberrypi.com" => "Raspberry Pi",
        "magpi.raspberrypi.org" => "Raspberry Pi",
        "pip.raspberrypi.com" => "Raspberry Pi",
        "sheets.raspberrypi.com" => "Raspberry Pi",
        "picockpit.com" => "Raspberry Pi",
        "www.raspberrypi.com" => "Raspberry Pi",
        "www.raspberrypi.org" => "Raspberry Pi",
        "helloworld.raspberrypi.org" => "Raspberry Pi Foundation",
        "www.raspberrypi-spy.co.uk" => "Raspberry Pi Spy",
        "raspberrytips.com" => "Raspberry Pi Tips",
        "rationalwiki.org" => "RationalWiki",
        "www.rawstory.com" => "Raw Story",
        "www.raygard.net" => "Ray Gardner",
        "www.raymondibrahim.com" => "Raymond Ibrahim",
        "ansari.sh" => "Rayyan Ansari",
        "www.rcfp.org" => "RCFP",
        "reactos.org" => "ReactOS",
        "about.readthedocs.com" => "Read the Docs Inc",
        "therealnews.com" => "The Real News Network",
        "realitycircuit.com" => "Reality Circuit",
        "www.devonlive.com" => "Reach PLC",
        "www.edinburghlive.co.uk" => "Reach PLC",
        "www.leicestermercury.co.uk" => "Reach PLC",
        "reason.com" => "Reason",
        "blog.rebased.pl" => "Rebased",
        "beccais.online" => "Rebecca Owen",
        "smayze.com" => "Rebooting Electronics",
        "joinreboot.org" => "Reboot",
        "smayze.com" => "Rebooting Electronics",
        "reclaimthenet.org" => "Reclaim The Net",
        "blog.reds.ch" => "Reconfigurable and embedded Digital Systems",
        "www.rei.com" => "Recreational Equipment Inc",
        "simblob.blogspot.com" => "Red Blob Games",
        "redhat.com" => "Red Hat Official",
        "www.redhat.com" => "Red Hat Official",
        "www.bestcolleges.com" => "Red Ventures",
        "felixreda.eu" => "Reda",
        "reduxx.info" => "Reduxx",
        "redmondmag.com" => "Redmond Magazine",
        "www.fighttorepair.org" => "Reflow",
        "fighttorepair.substack.com" => "Reflow",
        "mexicotoday.com" => "REFORMA",
        "www.rrnews.co.uk" => "Refurb Renovation News",
        "www.regenstrief.org" => "Regenstrief Institute",
        "tuckersiemens.com" => "Reilly Tucker Siemens",
        "www.reillywood.com" => "Reilly Wood",
        "reinout.vanrees.org" => "Reinout VanRees",
        "rietta.com" => "Reitta",
        "kokorobot.ca" => "Rek Bell",
        "relational-pipes.globalcode.info" => "Relational Pipes",
        "www.edrants.com" => "Reluctant Habits",
        "remarkable.com" => "reMarkable",
        "brusselssignal.eu" => "Remedia Europe",
        "remkusdevries.com" => "Remkus de Vries",
        "raymii.org" => "Remy Van Elst",
        "rhardih.io" => "René Hansen",
        "www.renewableenergyworld.com" => "Renewable Energy World",
        "reproof.app" => "Reproof",
        "www.researchgate.net" => "Research Gate",
        "www.resilience.org" => "Resilience",
        "restofworld.org" => "Rest of World",
        "retailwire.com" => "RetailWire",
        "www.context.news" => "Thompson Reuters Foundation",
        "in.reuters.com" => "Reuters",
        "mobile.reuters.com" => "Reuters",
        "uk.reuters.com" => "Reuters",
        "www.reuters.com" => "Reuters",
        "www.reuseabox.co.uk" => "ReuseABox",
        "lerner.co.il" => "Reuven Lerner",
        "www.reviewed.com" => "Reviewed",
        "www.revk.uk" => "RevK",
        "rewilding.org" => "Rewilding",
        "www.rfa.org" => "RFA",
        "www.rfc-editor.org" => "RFC",
        "gandhara.rferl.org" => "RFERL",
        "www.rferl.org" => "RFERL",
        "governor.ri.gov" => "Rhode Island",
        "en.rfi.fr" => "RFI",
        "www.rfi.fr" => "RFI",
        "rg3.name" => "Ricardo García",
        "blog.rgsilva.com" => "Ricardo Gomes da Silva",
        "morrick.me" => "Riccardo Mori",
        "www.rdwolff.com" => "Richard D Wolff",
        "www.richarddawkins.net" => "Richard Dawkins",
        "stallman.org" => "Richard M Stallman",
        "www.incompleteideas.net" => "Richard S Sutton",
        "rickcarlino.com" => "Rick Carlino",
        "falkvinge.net" => "Rick Falkvinge",
        "linuxmafia.com" => "Rick Moen",
        "www.repair.org" => "Right to Repair",
        "righttowarn.ai" => "Right to Warn About Advanced Artificial Intelligence",
        "www.rightchannelradios.com" => "Right Channel Radios",
        "www.riksbank.se" => "Riksbanken",
        "rileytestut.com" => "Riley Testut",
        "www.ringsidenews.com" => "Ringside News",
        "rinici.de" => "Rini",
        "labs.ripe.net" => "RIPE",
        "ripe80.ripe.net" => "RIPE",
        "www.ripe.net" => "RIPE",
        "riscv.org" => "RISCV",
        "risky.biz" => "RiskyBiz",
        "news.risky.biz" => "RiskyBiz",
        "riskybiznews.substack.com" => "RiskyBiz",
        "srslyriskybiz.substack.com" => "RiskyBiz",
        "www.riverfronttimes.com" => "River Front Times",
        "developer.r-project.org" => "Rlang",
        "www.r-bloggers.com" => "Rlang",
        "www.rnz.co.nz" => "RNZ",
        "rknight.me" => "Rob Knight",
        "www.landley.net" => "Rob Landley",
        "robm.me.uk" => "Rob Miller",
        "despairlabs.com" => "Rob Norris",
        "commandcenter.blogspot.com" => "Rob Pike",
        "www.computerglitch.net" => "Robbie Reese",
        "alexsci.com" => "Robert Alexander",
        "birming.com" => "Robert Birming",
        "frittiert.es" => "Robert Pfotenhauer",
        "blog.cleancoder.com" => "Robert C Martin",
        "blog.robertelder.org" => "Robert Elder",
        "rhaas.blogspot.com" => "Robert Haas",
        "robertheaton.com" => "Robert Heaton",
        "sfwriter.com" => "Robert J Sawyer",
        "robert.ocallahan.org" => "Robert OCallahan",
        "robertrehak.com" => "Robert Rehak",
        "www.datafantic.com" => "Robert Ritz",
        "robertspencer.org" => "Robert Spencer",
        "rob-turner.net" => "Robert Turner",
        "rbf.dev" => "Roberto Frenna",
        "robertovaccari.com" => "Roberto Vaccari",
        "robertovitillo.com" => "Roberto Vitillo",
        "robertreich.org" => "Robert Reich",
        "robertwinkler.com" => "Robert Winkler",
        "robert.winter.ink" => "Robert Winter",
        "berjon.com" => "Robin Berjon",
        "gazoche.xyz" => "Robin Lange",
        "robinrendle.com" => "Robin Rendle",
        "blog.sulami.xyz" => "Robin Schroer",
        "www.robinsloan.com" => "Robin Sloan",
        "sherwood.news" => "Robinhood Europe UAB",
        "robinhood.com" => "Robinhood Europe UAB",
        "ftp.rodents-montreal.org" => "Rodents-Montreal",
        "www.rodsbooks.com" => "Roderick W Smith",
        "notes.ghed.in" => "Rodrigo Ghedin",
        "trofire.com" => "ROF",
        "sgadrat.itch.io" => "Roger Bidon",
        "blog.paranoidpenguin.net" => "Roger Comply",
        "softhandover.wordpress.com" => "Roger Piqueras Jover",
        "weblog.rogueamoeba.com" => "Rogue Amoeba",
        "rohanrd.xyz" => "Rohan D",
        "grohan.co" => "Rohan Gupta",
        "seirdy.one" => "Rohan Kumar",
        "rolisz.ro" => "Rolisz",
        "www.rollcall.com" => "Rollcall",
        "www.rollingstone.com" => "Rolling Stone",
        "mmapped.blog" => "Roman Kashitsyn",
        "romchip.org" => "ROMchip",
        "blog.rareschool.com" => "Romilly Cocking",
        "flgov.com" => "Ron DeSantis",
        "thelinerproject.com" => "Ronnie Lutes",
        "undeleted.ronsor.com" => "Ronsor Labs",
        "rosindustrial.org" => "ROS Industrial",
        "www.rossp.org" => "Ross Poulton",
        "www.rottentomatoes.com" => "Rotten Tomatoes",
        "roytang.net" => "Roy Tang",
        "thoughtleadership.rbc.com" => "Royal Bank of Canada",
        "www.postofficetrial.com" => "Royal Mail UK",
        "royalsociety.org" => "The Royal Society UK",
        "www.chemistryworld.com" => "Royal Society Of Chemistry",
        "royalsocietypublishing.org" => "Royal Society UK",
        "www.royalsblue.com" => "Royals Blue",
        "www.rsaconference.com" => "RSA",
        "rsf.org" => "RSF",
        "www.rt.com" => "RT",
        "about.rte.ie" => "RTE",
        "www.rte.ie" => "RTE",
        "news.rthk.hk" => "RTHK",
        "today.rtl.lu" => "RTL",
        "brokenco.de" => "R Tyler Croy",
        "rubenerd.com" => "Ruben Schade",
        "rubycentral.org" => "Ruby Central",
        "rudism.com" => "Rudis Muiznieks",
        "web-in-security.blogspot.com" => "Ruhr University Bochum",
        "untidy.substack.com" => "Runa Sandvik",
        "runbsd.info" => "RunBSD",
        "ruslanspivak.com" => "Ruslan Spivak",
        "ruudvanasseldonk.com" => "Ruud van Asseldonk",
        "www.ruv.is" => "RÚV",
        "www.rwjf.org" => "RWJF",
        "ryanmulligan.dev" => "Ryan Mulligan",
        "ryantrimble.com" => "Ryan Trimble",
        "zinascii.com" => "Ryan Zezeski",
        "www.spglobal.com" => "S & P Global",
        "www.scienceboard.net" => "SAB",
        "www.sacredheartsc.com" => "Sacred Heart SC",
        "safcei.org" => "SAFCEI",
        "saferchemicals.org" => "Safer Chemicals",
        "journals.sagepub.com" => "Sage Journal",
        "saharareporters.com" => "Sahara Reporters",
        "blog.sahilister.in" => "Sahilister",
        "www.stltoday.com" => "Saint Louis Post-Dispatch",
        "www.christianheadlines.com" => "Salem Web Network",
        "www.salon.com" => "Salon",
        "code.foo.no" => "Salve J Nilsen",
        "sambleckley.com" => "Sam Bleckley",
        "samcurry.net" => "Sam Curry",
        "samwho.dev" => "Sam Rose",
        "news.samsung.com" => "Samsung",
        "httpster.io" => "Sami",
        "0x44.cc" => "Sami Alaoui Kendil",
        "www.sami-lehtinen.net" => "Sami Lehtinen",
        "www.saminiir.com" => "Sami Niiranen",
        "samueloph.dev" => "Samuel Henrique",
        "blog.samuelmaddock.com" => "Samuel Maddock",
        "samy.pl" => "Samy Kamkar",
        "www.sacurrent.com" => "San Antonio",
        "www.sandiegouniontribune.com" => "San Diego",
        "www.sfchronicle.com" => "San Fancisco",
        "sfstandard.com" => "The San Fancisco Standard",
        "www.sfexaminer.com" => "San Fancisco",
        "sjvsun.com" => "The San Joaquin Valley Sun",
        "ischool.sjsu.edu" => "San José State University",
        "www.uscopyrightattorneys.com" => "Sanders Law Group",
        "www.sandordargo.com" => "Sandor Dargo",
        "www.dshield.org" => "SANS",
        "isc.sans.edu" => "SANS",
        "www.sans.org" => "SANS",
        "www.santacruzsentinel.com" => "Santa Cruz",
        "without.boats" => "Saoirse",
        "sarajaksa.eu" => "Sara Jakša",
        "sarajoy.dev" => "Sarah Joy",
        "therealsarahmiller.substack.com" => "Sarah Miller",
        "sarajevotimes.com" => "Sarajevo Times",
        "www.saturdayeveningpost.com" => "Saturday Evening Post Society",
        "english.alarabiya.net" => "Saudi Arabia",
        "saudigazette.com.sa" => "Saudi Gazette",
        "hanukkah.bluebird.sh" => "BlueBird Shell",
        "savageminds.org" => "Savage Minds",
        "savetibet.org" => "Save Tibet",
        "www.savethechildren.org" => "Save the Children",
        "www.sbs.com.au" => "SBS",
        "smartbitchestrashybooks.com" => "SBTB",
        "www.scalevp.com" => "Scale Venture Partners",
        "scheerpost.com" => "Scheerpost",
        "schengen.news" => "Schengen.News",
        "schillerinstitute.com" => "Schiller Institute",
        "schwarztech.net" => "SchwarzTech",
        "www.schneems.com" => "Richard Schneeman",
        "www.spagmag.org" => "Society for the Promotion of Adventure Games",
        "scholarlykitchen.sspnet.org" => "Society for Scholarly Publishing",
        "scifiinterfaces.com" => "Sci-fi Interfaces",
        "www.scienceabc.com" => "Science ABC",
        "sciencealert.com" => "Science Alert",
        "www.sciencealert.com" => "Science Alert",
        "sciencebusiness.net" => "Science Business",
        "www.sciencedaily.com" => "Science Daily",
        "www.sciencefocus.com" => "Science Focus",
        "www.sciencenews.org" => "Science News",
        "sciencenigeria.com" => "Science Nigeria",
        "medicalxpress.com" => "Science X Network",
        "blogs.scientificamerican.com" => "Scientific American",
        "www.scientificamerican.com" => "Scientific American",
        "scitechdaily.com" => "Sci Tech Daily",
        "ihodl.com" => "SCMC",
        "www.scmagazineuk.com" => "SC Media UK",
        "www.scmp.com" => "SCMP",
        "www.scmp.com" => "SCMP",
        "www.scoop.co.nz" => "Scoop Media",
        "statescoop.com" => "Scoop News Group",
        "cyberscoop.com" => "Scoop News Group",
        "defensescoop.com" => "Scoop News Group",
        "fedscoop.com" => "Scoop News Group",
        "www.cyberscoop.com" => "Scoop News Group",
        "www.fedscoop.com" => "Scoop News Group",
        "www.scopeofwork.net" => "Scope of Work",
        "scorpil.com" => "Scorpil",
        "scottrichmond.me" => "Scott C Richmond",
        "www.scottcalonico.com" => "Scott Calonico",
        "sdubinsky.com" => "Scott Dubinsky",
        "scott.mn" => "Scott Feeney",
        "scot.tg" => "Scott Graham",
        "blog.simplejustice.us" => "Scott H Greenfield",
        "www.hanselman.com" => "Scott Hanselman",
        "scotthelme.co.uk" => "Scott Helme",
        "scottjehl.com" => "Scott Jehl",
        "www.scottohara.me" => "Scott O'Hara",
        "moral.net.au" => "Scott Percival",
        "www.scottredig.com" => "Scott Redig",
        "www.scott-a-s.com" => "Scott Schneider",
        "www.scottsmitelli.com" => "Scott Smitelli",
        "scottwillsey.com" => "Scott Willsey",
        "www.scl.org" => "Scottish Society for Computers and Law",
        "www.scottishdailyexpress.co.uk" => "Scottish Daily Express",
        "www.supremecourt.gov" => "SCOTUS",
        "www.scotusblog.com" => "SCOTUSblog",
        "obsd.solutions" => "Scqr Inc",
        "www.scrapingbee.com" => "ScrapingBee API",
        "screenrant.com" => "Screen Rant",
        "graphite.dev" => "Screenplay Studios Inc dba Graphite",
        "scribe.rip" => "Scribe",
        "www.10news.com" => "Scripps Media Inc",
        "www.newschannel5.com" => "Scripps Media Inc",
        "www.koaa.com" => "Scripps Media Inc",
        "www.kristv.com" => "Scripps Media Inc",
        "www.kxlf.com" => "Scripps Media Inc",
        "www.wrtv.com" => "Scripps Media Inc",
        "www.wxyz.com" => "Scripps Media Inc",
        "scripting.com" => "Scripting News",
        "blog.scrt.ch" => "SCRT",
        "www.scylladb.com" => "ScyllaDB Inc",
        "sdomi.pl" => "Sdomi",
        "sdtimes.com" => "SDTimes",
        "www.sdxcentral.com" => "SDx Central",
        "www.seancassidy.me" => "Sean Cassidy",
        "seancoates.com" => "Sean Coates",
        "boston.conman.org" => "Sean Conner",
        "xobs.io" => "Sean Cross",
        "www.seangoedecke.com" => "Sean Goedecke",
        "sean.heelan.io" => "Sean Heelan",
        "deadsuperhero.com" => "Sean Tilley",
        "sean.voisen.org" => "Sean Voisen",
        "www.seattletimes.com" => "Seattle Times",
        "seblog.nl" => "Sebastiaan Andeweg",
        "www.sebastianbuza.com" => "Sebastian Buza",
        "kapouay.eu.org" => "Sebastian Marie",
        "www.sebastiansylvan.com" => "Sebastian Sylvan",
        "sebastiano.tronto.net" => "Sebastian Tronto",
        "www.sebastopoltimes.com" => "Sebastopol Times",
        "www.sec.gov" => "SEC",
        "sec-consult.com" => "SEC Consule`",
        "seclists.org" => "Sec Lists",
        "secpy.medium.com" => "SecPy",
        "www.secret-bases.co.uk" => "Secret Bases",
        "secretnyc.co" => "Secret Media Network",
        "securepairs.org" => "Securepairs",
        "www.secureworks.com" => "Secureworks",
        "securepractice.co" => "Secure Practice",
        "securedrop.org" => "SecureDrop",
        "securityaffairs.com" => "Security Affairs",
        "securityaffairs.co" => "Security Affairs",
        "securityboulevard.com" => "Security Boulevard",
        "www.securitysales.com" => "Security Sales",
        "www.securityweek.com" => "Security Week",
        "www.sedaa.org" => "Sedaa",
        "www.seeedstudio.com" => "Seeed Studio",
        "seekingalpha.com" => "Seeking Alpha",
        "segmentnext.com" => "Segment Next",
        "www.searchenginejournal.com" => "SEJ",
        "southeastlinuxfest.org" => "SELF",
        "www.semafor.com" => "Semafor Inc",
        "semiengineering.com" => "Semi Engineering",
        "semiaccurate.com" => "SemiAccurate",
        "labs.sentinelone.com" => "Sentinel Labs",
        "www.sentinelone.com" => "Sentinel One",
        "blog.sentry.io" => "Sentry",
        "www.sepa.org.uk" => "SEPA UK",
        "josephg.com" => "Seph",
        "septentrio.uit.no" => "Septentrio Academic Publishing",
        "sequoia-pgp.org" => "SequoiaPGP",
        "lists.sequoia-pgp.org" => "SequoiaPGP",
        "sfgate.com" => "SFGate",
        "blog.serghei.pl" => "Serghei Iakovlev",
        "rasbora.dev" => "Sergiy Usatyuk",
        "serhack.me" => "SerHack",
        "getsession.org" => "Session",
        "www.seti.org" => "SETI Intsitute",
        "seths.blog" => "Seth Godin",
        "sethmlarson.dev" => "Seth Michael Larson",
        "www.sfgate.com" => "SFGate",
        "sfist.com" => "SFist",
        "www.softwarefreedom.org" => "SFLC",
        "insights.uksg.org" => "SGJournal UK",
        "www.shacknews.com" => "Shacknews",
        "shadowproof.com" => "Shadowproof",
        "www.scannedinavian.com" => "Shae Ericsson",
        "debugagent.com" => "Shai Almog",
        "blog.webjeda.com" => "Sharath",
        "www.thestar.co.uk" => "Sheffield",
        "sheridancomputers.co.uk" => "Sheridan Computers",
        "cosmicqbit.dev" => "Shariq Raza Qadri",
        "www.shetnews.co.uk" => "Shetland News",
        "actualbudget.com" => "Shift Reset LLC",
        "www.shippingandfreightresource.com" => "Shipping and Freight Resource",
        "code.openark.org" => "Shlomi Noach",
        "www.shmoocon.org" => "ShmooCon",
        "sharats.me" => "Shrikant Sharat Kandula",
        "www.shropshirestar.com" => "Shropshire Star",
        "siberiantimes.com" => "Siberian Times",
        "sick.codes" => "Sick Codes",
        "www.sicpers.info" => "SICP",
        "www.sierraclub.org" => "Sierra Club",
        "sigfrid-lundberg.se" => "Sigfrid Lundberg",
        "signmyrocket.com" => "Sign My Rocket",
        "www.signal.org" => "Signal",
        "signal.org" => "Signal",
        "blog.sigstore.dev" => "Sigstore",
        "www.armytimes.com" => "Sightline Media Group",
        "sjmulder.nl" => "Sijmen Mulder",
        "www.siliconrepublic.com" => "Silcon Republic",
        "siliconangle.com" => "Silicon Angle",
        "theglobalherald.com" => "Silicon Dales Ltd",
        "www.silvestar.codes" => "Silvestar Bistrović",
        "xn--ime-zza.eu" => "Šime",
        "šime.eu" => "Šime",
        "simonandrews.ca" => "Simon Andrews",
        "colly.com" => "Simon Collison",
        "sirupsen.com" => "Simon Hørup Eskildsen",
        "blog.josefsson.org" => "Simon Josefsson",
        "soc.me" => "Simon Ochsenreither",
        "emersion.fr" => "Simon Ser",
        "simonwillison.net" => "Simon Willison",
        "til.simonwillison.net" => "Simon Willison",
        "minutestomidnight.co.uk" => "Simone Silvestroni",
        "simonevellei.com" => "Simone Vellei",
        "www.simpleanalytics.com" => "Simple Analytics BV",
        "simplelogin.io" => "Simple Login",
        "www.simplypsychology.org" => "Simply Scholar Ltd",
        "simson.net" => "Simson Garfinkel",
        "singjupost.com" => "Singju Post",
        "singularityhub.com" => "Singularity Education Group",
        "www.sisvel.com" => "Sisvel",
        "www.sita.aero" => "SITA",
        "digit.site36.net" => "Site36",
        "www.sitra.fi" => "Sitra",
        "sixcolors.com" => "Six Colors",
        "opensourcewatch.beehiiv.com" => "SJVN",
        "skarnet.org" => "Skarnet",
        "skyandtelescope.org" => "Sky and Telescope",
        "news.sky.com" => "Sky News",
        "slashpages.net" => "Slash Pages",
        "www.slant.co" => "Slant",
        "slate.com" => "Slate",
        "www.thesleepjudge.com" => "The Sleep Judge",
        "slimbook.com" => "Slimbook",
        "devlog.hexops.com" => "Slimsag",
        "www.schoollibraryjournal.com" => "SLJ",
        "slovenia.postsen.com" => "Slovenia",
        "www.slowfood.com" => "Slow Food Foundation",
        "www.smartcitiesworld.net" => "Smart Cities World",
        "smartlogic.io" => "SmartLogic",
        "www.smashingmagazine.com" => "Smashing Magazine",
        "www.smithsonianmag.com" => "Smithsonian Magazine",
        "www.si.edu" => "Smithsonian Institute",
        "world-playground-deceit.net" => ">Smug Lisp Weenie",
        "www.snopes.com" => "Snopes",
        "www.socallinuxexpo.org" => "SoCal Linux Expo",
        "socialdhara.com" => "Social Dhara",
        "socialeconomicslab.org" => "Social Economics Lab",
        "www.social-engineer.com" => "Social Engineer",
        "sggsc.blog" => "Societe Generale India",
        "documents.saa.org" => "Society for American Archaeology",
        "www.saa.org" => "Society for American Archaeology",
        "gluecko.se" => "Soeren",
        "en.softonic.com" => "Softonic",
        "www.softpanorama.org" => "Softpanorama",
        "news.softpedia.com" => "Softpedia",
        "2023.fossy.us" => "Software Freedom Conservancy",
        "sfconservancy.org" => "Software Freedom Conservancy",
        "www.softandhardware.com" => "Software And Hardware",
        "www.softwareatscale.dev" => "Software At Scale",
        "davmac.org" => "Software Is Crap",
        "davmac.wordpress.com" => "Software Is Crap",
        "www.thesoftwareguild.com" => "Software Guild",
        "docs.softwareheritage.org" => "Software Heritage",
        "www.softwareheritage.org" => "Software Heritage",
        "blog.cofree.coffee" => "Solomon Bothwell",
        "somedudesays.com" => "Some Dude Says",
        "archives.somnolescent.net" => "The Somnolescent Archives",
        "www.songfacts.com" => "Songfacts",
        "blog.playstation.com" => "Sony",
        "www.playstation.com" => "Sony",
        "assets.sophos.com" => "Sophos",
        "news.sophos.com" => "Sophos",
        "soranews24.com" => "Sora News 24",
        "www.yoursoundmatters.com" => "Sound Matters",
        "git.sr.ht" => "Sourcehut",
        "man.sr.ht" => "Sourcehut",
        "mybroadband.co.za" => "South Africa",
        "www.capeindependent.com" => "South Africa",
        "www.citizen.co.za" => "South Africa",
        "southeastohiomagazine.com" => "Southeast Ohio",
        "laist.com" => "Southern California Public Radio",
        "www.southeastasianews.net" => "Big News Network FZ LLC",
        "southsidepride.com" => "Southside Pride",
        "soylentnews.org" => "Soylent News",
        "www.space.com" => "Space",
        "spaceraccoon.dev" => "Spaceraccoon",
        "spaceweather.com" => "Spaceweather.com",
        "www.thespacereview.com" => "The Space Review",
        "learn.sparkfun.com" => "SparkFun Electronics",
        "www.sparkfun.com" => "SparkFun Electronics",
        "sparktoro.com" => "Spark Toro",
        "sparrowmedia.net" => "Sparrow Media",
        "spectator.org" => "Spectator",
        "spectator.us" => "Spectator US",
        "www.spectator.com.au" => "Spectator AU",
        "www.speedcurve.com" => "SpeedCurve Ltd",
        "catern.com" => "Spencer Baugh",
        "www.spencerharston.com" => "Spencer Harston",
        "catern.com" => "Spencer Baugh",
        "spheres-journal.org" => "Spheres",
        "www.spiegel.de" => "Spiegel",
        "www.splicetoday.com" => "Splice Today",
        "www.spin.com" => "Next Management Partners",
        "spookbench.net" => "Spook",
        "www.si.com" => "Sports Illustrated",
        "www.sportsnhobbies.org" => "Sports n' Hobbies",
        "www.sportskeeda.com" => "Sportskeeda",
        "engineering.atspotify.com" => "Spotify Inc",
        "www.spottinghistory.com" => "SpottingHistory",
        "springmag.ca" => "Spring Magazine",
        "link.springer.com" => "Springer Nature",
        "researchintegrityjournal.biomedcentral.com" => "Springer-Verlag GmbH",
        "sputniknews.com" => "Sputnik News",
        "sqlite.org" => "SQLite",
        "www.sqlite.org" => "SQLite",
        "sverigesradio.se" => "SR",
        "www.sr2.uk" => "SR2 Commmunications Limited",
        "sourcehut.org" => "Srht",
        "srid.ca" => "Sridhar Ratnakumar",
        "srlabs.de" => "SR Labs",
        "www.sscce.org" => "The SSCCE",
        "www.ssh.com" => "SSH Communications Security Corporation",
        "lists.rutschle.net" => "SSLH",
        "ssplisbad.com" => "SSPL is Bad",
        "papers.ssrn.com" => "SSRN",
        "thestack.technology" => "The Stack",
        "www.thestack.technology" => "The Stack",
        "stackdiary.com" => "Stack Diary",
        "stackoverflow.blog" => "Stack Overflow",
        "stack-auth.com" => "Stackframe Inc",
        "staceyoniot.com" => "Stacey on IoT",
        "www.thebookseller.com" => "Stage Media Company Limited",
        "www.stamfordadvocate.com" => "Stamford Advocate",
        "stanbright.com" => "Stan Bright",
        "www.standict.eu" => "StandICT",
        "standpointmag.co.uk" => "Standpoint UK",
        "blog.thea.codes" => "Stargirl Flowers",
        "www.stargrave.org" => "Stargrave",
        "www.stripes.com" => "Stars And Stripes",
        "www.startribune.com" => "Star Tribune",
        "www.statnews.com" => "Stat",
        "statenews.com" => "State News",
        "2024.stateofcss.com" => "State of CSS 2024",
        "2023.stateofhtml.com" => "State of HTML 2023",
        "www.vsd.lt" => "State Security Department Of Lithuania",
        "www.statewatch.org" => "State Watch",
        "www.slashfilm.com" => "Static Media",
        "www.statista.com" => "Statista",
        "www.status.news" => "Status News LLC",
        "eay.cc" => "Stefan Grund",
        "www.stefanjudis.com" => "Stefan Judis",
        "skanthak.homepage.t-online.de" => "Stefan Kanthak",
        "www.stefantheard.com" => " Stefan Theard",
        "stefanzweifel.dev" => "Stefan Zweifel",
        "steflan-security.com" => "Stefano Lanaro",
        "it-notes.dragas.net" => "Stefano Marinelli",
        "blog.sesse.net" => "Steinar H Gunderson",
        "www.ancient-origins.net" => "Stella Novus",
        "stephango.com" => "Steph Ango",
        "stephenfry.substack.com" => "Stephen Fry",
        "512pixels.net" => "Stephen Hackett",
        "www.humprog.org" => "Stephen Kell",
        "svrooij.io" => "Stephan van Rooij",
        "www.bortzmeyer.org" => "Stéphane Bortzmeyer",
        "doc.huc.fr.eu.org" => "Stéphane Huc",
        "blog.stephaniestimac.com" => "Stephanie Stimac",
        "www.stephendiehl.com" => "Stephen Diehl",
        "buildingjerusalem.blog" => "Stephen Kneale",
        "blog.stephenmarz.com" => "Stephen Marz",
        "smist08.wordpress.com" => "Stephen Smith",
        "writings.stephenwolfram.com" => "Stephen Wolfram",
        "www.steves-internet-guide.com" => "Steve Cope",
        "unixwiz.net" => "Steve Friedl",
        "blog.steve.fi" => "Steve Kemp",
        "tangiblelife.net" => "Steve Ledlow",
        "www.troubleshooters.com" => "Steve Litt",
        "troubleshooters.com" => "Steve Litt",
        "blog.einval.com" => "Steve McIntyre",
        "visitmy.website" => "Steve Messer",
        "abnml.com" => "Steven Anderson",
        "srcincite.io" => "Steven Seeley",
        "www.servethehome.com" => "STH",
        "stiankri.substack.com" => "Stian Kristoffersen",
        "www.brautaset.org" => "Stig Brautaset",
        "www.stimson.org" => "Stimson",
        "stockholmcf.org" => "Stockholm Center For Freedom",
        "www.stonehenge.com" => "Stonehenge Consulting Services",
        "iamstoxe.com" => "Stoxe",
        "strandconsult.dk" => "Strand Consult",
        "stratechery.com" => "Stratechery",
        "www.streamingmedia.com" => "Streaming Media",
        "usa.streetsblog.org" => "Streetsblog USA",
        "streetinsider.com" => "StreetInsider",
        "www.streetinsider.com" => "StreetInsider",
        "stripe.com" => "Stripe",
        "tomassetti.me" => "Strumenta",
        "www.sttinfo.fi" => "STT Viestintäpalvelut Oy",
        "www.stuartellis.name" => "Stuart Ellis",
        "stuartl.longlandclan.id.au" => "Stuart Longland",
        "stuartschechter.org" => "Stuart Schechter",
        "www.thecollegefix.com" => "Student Free Press Association",
        "i.stuff.co.nz" => "Stuff",
        "stundin.is" => "Stundin",
        "stylestage.dev" => "Style Stage",
        "subethasoftware.com" => "Sub-Etha Software",
        "subplot.tech" => "Subplot",
        "www.brennancenter.org" => "Brennan Center for Justice at NYU Law",
        "snarky.ca" => "Brett Cannon",
        "www.asomo.co" => "Brett Scott",
        "suckless.org" => "Suckless",
        "sudantribune.com" => "Sudan",
        "www.sudanspost.com" => "Sudan",
        "www.sudo.ws" => "Sudo",
        "www.stuff.co.nz" => "Suff NZ",
        "suchir.net" => "Suchir Balaji",
        "harihareswara.net" => "Sumana Harihareswara",
        "www.harihareswara.net" => "Sumana Harihareswara",
        "battlepenguin.com" => "Sumit Khanna",
        "thesuntimesnews.com" => "The Sun Times",
        "sunainapai.in" => "Sunaina Pai",
        "www.sundayobserver.lk" => "Sunday Observer",
        "www.timeslive.co.za" => "Sunday Times",
        "learnbyexample.github.io" => "Sundeep Agarwal",
        "www.sundialservices.com" => "Sundial Services International LLC",
        "supabase.com" => "Supabase Inc",
        "superserverhero.com" => "Super Server Hero",
        "www.superhighway98.com" => "Superhighway 98",
        "superkuh.com" => "Superkuh",
        "stallmansupport.org" => "Support Stallman",
        "www.surfertoday.com" => "Surfer Today",
        "susam.net" => "SusamPal",
        "www.susps.org" => "SUSPS",
        "www.sussexlive.co.uk" => "Sussex Live UK",
        "nondoc.com" => "Sustainable Journalism Foundation",
        "svenluijten.com" => "Sven Luijten",
        "blog.siphos.be" => "Sven Vermeulen",
        "m.signalvnoise.com" => "SVN",
        "fsf.org.in" => "Swatantra",
        "fsf.org.in" => "Swatantra",
        "sweden.postsen.com" => "Postsen, Sweden",
        "www.government.se" => "Sweden",
        "www.sakerhetspolisen.se" => "Swedish Security Service",
        "www.jamstalldhetsmyndigheten.se" => "Sweden",
        "www.imy.se" => "Sedishj Authority for Privacy Protection",
        "www.swissinfo.ch" => "SWI",
        "forums.swift.org" => "Swift Forum",
        "www.swlondoner.co.uk" => "SW Londoner UK",
        "www.smh.com.au" => "Sydney Morning Herald",
        "www.syfy.com" => "SYFY",
        "blog.sygnia.co" => "Sygnia",
        "kerkour.com" => "Sylvain Kerkour",
        "sylvestre.ledru.info" => "Sylvestre Ledru",
        "www.synacktiv.com" => "Syncactiv",
        "blog.syncpup.com" => "Syncpup",
        "www.synthtopia.com" => "Synthtopia",
        "hacklog.in" => "Sys Admin Journal",
        "sysdig.com" => "Sysdig Inc",
        "blog.system76.com" => "System76",
        "support.system76.com" => "Systemd 76",
        "sysdfree.wordpress.com" => "Systemd Free",
        "systemtek.co.uk" => "SystemTeK",
        "www.thenewstribune.com" => "Tacoma News Tribune",
        "www.tahirih.org" => "Tahirih Justice Center",
        "tails.boum.org" => "Tails",
        "tails.net" => "Tails",
        "tailscale.com" => "Tailscale",
        "www.taipeitimes.com" => "Taipei Times",
        "www.taiwannews.com.tw" => "Taiwan News",
        "www.takahe.org.nz" => "Takahē Magazine",
        "takebackourtech.org" => "TakeBack Our Tech",
        "taler.net" => "Taler",
        "thedorkweb.substack.com" => "Tales From The DorkWeb",
        "tallahasseereports.com" => "Tallahassee Reports",
        "www.talospace.com" => "Talospace",
        "www.tampabay.com" => "Tampa Bay",
        "projects.tampabay.com" => "Tampa Bay Times",
        "www.taniarascia.com" => "Tania Rascia",
        "www.tanyagoodin.com" => "Tanya Goodin",
        "www.thecitizen.co.tz" => "Tanzania",
        "taosecurity.blogspot.com" => "Tao Security Blog",
        "tariosultan.com" => "Tario Sultan",
        "www.tarlogic.com" => "Tarlogic",
        "www.baeldung.com" => "Tarnum Java SRL",
        "mail.tarsnap.com" => "Tarsnap",
        "taskandpurpose.com" => "Task And Purpose",
        "tass.com" => "TASS",
        "pgsqlpgpool.blogspot.com" => "Tatsuo Ishii",
        "tavianator.com" => "Tavian Barnes",
        "lock.cmpxchg8b.com" => "Tavis Ormandy",
        "www.tandfonline.com" => "Taylor Francis Group",
        "tearsheet.co" => "Tearsheet",
        "text.tchncs.de" => "Tchncs",
        "www.techadvisor.com" => "Tech Advisor",
        "www.techcentral.ie" => "Tech Central (Ireland)",
        "techcentral.co.za" => "Tech Central (South Africa)",
        "technewsinc.com" => "Tech News Inc",
        "techreflect.net" => "Tech Reflect",
        "techcrunch.com" => "TechCrunch",
        "techdator.net" => "TechDator",
        "channellife.co.nz" => "Techday",
        "www.techdirt.com" => "Techdirt",
        "tech.eu" => "Tech EU",
        "techeconomy.ng" => "TechEconomy.ng",
        "techexec.com.au" => "Tech Exec",
        "techgage.com" => "Techgage",
        "www.techhive.com" => "Tech Hive",
        "techiemag.com" => "Techie Magazine",
        "thetechiesenior.com" => "Techie Senior",
        "www.technadu.com" => "TechNadu",
        "technode.com" => "TechNode",
        "www.techradar.com" => "TechRadar",
        "www.techrepublic.com" => "TechRepublic",
        "www.techslang.com" => "Techslang",
        "www.techspot.com" => "TechSpot",
        "techstory.in" => "TechStory Media",
        "devops.com" => "Techstrong Group",
        "searchcloudcomputing.techtarget.com" => "TechTarget",
        "searchdatamanagement.techtarget.com" => "TechTarget",
        "searchhealthit.techtarget.com" => "TechTarget",
        "www.techtarget.com" => "TechTarget",
        "www.techtimes.com" => "Tech Times",
        "www.techtricksworld.com" => "Tech Tricks World",
        "techunwrapped.com" => "Tech Unwrapped",
        "www.techworm.net" => "Techworm",
        "techxplore.com" => "TechXplore",
        "www.ted.com" => "TED",
        "tedium.co" => "Tedium",
        "edwardbenson.com" => "Ted Benson",
        "www.tedinski.com" => "Ted Kaminski",
        "flak.tedunangst.com" => "Ted Unangst",
        "teemu.online" => "Teemu Vidgren",
        "www.teenvogue.com" => "Teen Vogue",
        "www.blog.techraj156.com" => "Teja Swaroop",
        "tekin.co.uk" => "Tekin Süleyman",
        "telegra.ph" => "Telegraph PH",
        "goteleport.com" => "Teleport",
        "gravitational.com" => "Teleport",
        "www.telesurenglish.net" => "teleSUR",
        "tenfourfox.blogspot.com" => "Ten Four Fox",
        "www.tenable.com" => "Tenable Inc",
        "terathon.com" => "Terathon",
        "shkspr.mobi" => "Terence Eden",
        "edent.codeberg.page" => "Terence Eden",
        "terminusdb.com" => "TerminusDB",
        "terrastruct.com" => "Terrastruct Inc",
        "www.tesi.fi" => "Tesi",
        "www.texasattorneygeneral.gov" => "Texas",
        "texasnewstoday.com" => "Texas",
        "www.chron.com" => "Texas",
        "www.mysanantonio.com" => "Texas",
        "www.tpr.org" => "Texas Public Radio",
        "textual.textualize.io" => "Textualize Inc",
        "techfinancials.co.za" => "TFS",
        "www.theadvocate.com" => "The Advocate",
        "www.hepburnadvocate.com.au" => "The Advocate AU",
        "www.theafricareport.com" => "The Africa Report",
        "www.theage.com.au" => "The Age AU",
        "www.theamericanconservative.com" => "The American Conservative",
        "prospect.org" => "The American Prospect",
        "anarc.at" => "The Anarcat",
        "theappeal.org" => "The Appeal",
        "archpaper.com" => "The Architects Newspaper",
        "asianage.com" => "The Asian Age",
        "www.asianage.com" => "The Asian Age",
        "www.theatlantic.com" => "The Atlantic",
        "thebarentsobserver.com" => "The Barents Observer",
        "www.thebarentsobserver.com" => "The Barents Observer",
        "www.theblockcrypto.com" => "The Block",
        "www.thebroadsblog.co.uk" => "Broads Authority",
        "brusselsmorning.com" => "Brussels Morning Newspaper",
        "www.brusselstimes.com" => "The Brussels Times",
        "www.theburnin.com" => "The Burn In",
        "www.bizjournals.com" => "The Business Journals",
        "www.businesstimes.com.sg" => "TheBusiness Times",
        "www.thecanary.co" => "The Canary",
        "www.thechronicle.com.au" => "The Chronicle AU",
        "www.thecitizen.co.tz" => "The Citizen",
        "thecinemaholic.com" => "The Cinemaholic",
        "thecodist.com" => "The Codist",
        "theconversation.com" => "The Conversation",
        "thecorrespondent.com" => "The Correpsondent",
        "thecritic.co.uk" => "The Critic",
        "www.thedailybeast.com" => "The Daily Beast",
        "www.thedailystar.net" => "The Daily Star",
        "the-decoder.com" => "Deep Content GbR",
        "pavilion.dinfos.edu" => "Defense Information School",
        "www.thedefensepost.com" => "The Defense Post",
        "www.filfre.net" => "The Digital Antiquarian",
        "www.the-digital-life.com" => "The Digital Life",
        "thediplomat.com" => "The Diplomat",
        "thedispatch.com" => "The Dispatch",
        "dissenter.substack.com" => "The Dissenter",
        "thedissenter.org" => "The Dissenter",
        "www.thedrive.com" => "The Drive",
        "www.drive.com.au" => "The Drive Network",
        "www.theeastafrican.co.ke" => "The East African KE",
        "theecologist.org" => "The Ecologist",
        "impact.economist.com" => "The Economist",
        "www.economist.com" => "The Economist",
        "www.theepochtimes.com" => "The Epoch Times",
        "blogs.tribune.com.pk" => "The Express Tribune",
        "tribune.com.pk" => "The Express Tribune",
        "www.thefastmode.com" => "The Fast Mode",
        "thefederalist.com" => "The Federalist",
        "www.thefire.org" => "The Fire",
        "www.theglobeandmail.com" => "The Globe And Mail CA",
        "theglobepost.com" => "The Globe Post",
        "thegrayzone.com" => "The Gray Zone",
        "gru.gq" => "TheGrugq",
        "www.postguam.com" => "The Guam Daily Post",
        "www.theguardian.com" => "The Guardian UK",
        "thehayride.com" => "The Hayride",
        "www.heraldscotland.com" => "The Herald",
        "thehill.com" => "The Hill",
        "thehimalayantimes.com" => "The Himalayan Times",
        "www.thehindu.com" => "The Hindu",
        "www.thehindubusinessline.com" => "TheHinduBusinessLine",
        "www.thehour.com" => "The Hour",
        "thehumanist.com" => "The Humanist",
        "m.independent.ie" => "The Independent IE",
        "www.independent.co.ug" => "The Independent UG",
        "www.independent.co.uk" => "The Independent UK",
        "indieweb.org" => "IndieWeb",
        "www.theindianalawyer.com" => "The Indiana Lawyer",
        "theinformant.co.nz" => "The Informant",
        "www.theinfostride.com" => "The InfoStride",
        "www.theinquirer.net" => "The Inquirer UK",
        "www.irishnews.com" => "The Irish News",
        "www.thejakartapost.com" => "The Jakarta Post ID",
        "www.thejc.com" => "The Jewish Chronicle",
        "thejewishvoice.com" => "The Jewish Voice",
        "thejewishweekly.com" => "The Jewish Weekly",
        "www.thejournal.ie" => "The Journal",
        "www.thekashmirmonitor.net" => "The Kashmir Monitor",
        "thekingdominsider.com" => "The Kingdom Insider",
        "www.thelancet.com" => "The Lancet",
        "www.thelegaldescription.com" => "The Legal Description",
        "www.thelocal.dk" => "The Local DK",
        "www.thelocal.es" => "The Local ES",
        "www.thelocal.se" => "The Local SE",
        "www.thelondoneconomic.com" => "The London Economic",
        "themaritimepost.com" => "The Maritime Post",
        "themarkup.org" => "The Markup",
        "www.themoscowtimes.com" => "The Moscow Times",
        "www.fool.com" => "The Motley Fool",
        "www.thenation.com" => "The Nation",
        "www.thenational.ae" => "The National AE",
        "www.thenationalnews.com" => "The National AE",
        "www.thenational.scot" => "The National UK",
        "www.newarab.com" => "The New Arab",
        "english.alaraby.co.uk" => "TheNewArab",
        "www.theneweuropean.co.uk" => "The New European UK",
        "www.thenewhumanitarian.org" => "The New Humanitarian",
        "then24.com" => "The News 24",
        "www.thenews.com.pk" => "The News PK",
        "thenewleafjournal.com" => "The New Leaf Journal",
        "thenewstack.io" => "The New Stack",
        "engineering.nyu.edu" => "New York University",
        "www.nyu.edu" => "New York University",
        "www.nybooks.com" => "The New York Review",
        "www.nextplatform.com" => "The Next Platform",
        "thenextweb.com" => "The Next Web",
        "northafricapost.com" => "The North Africa Post",
        "thenorthlines.com" => "The North Lines IN",
        "www.thenorthlines.com" => "The North Lines IN",
        "www.theolympian.com" => "The Olympian",
        "klamathalerts.com" => "Oregon",
        "today.oregonstate.edu" => "Oregon State University",
        "www.oregonzoo.org" => "The Oregon Zoo",
        "www.oregonlive.com" => "The Oregonian",
        "www.inquirer.com" => "The Philadelphia Inquirer",
        "theprint.in" => "The Print",
        "programminghistorian.org" => "The Programming Historian",
        "www.thequint.com" => "The Quint",
        "theraven.substack.com" => "The Raven",
        "thereboot.com" => "The Reboot",
        "therecord.media" => "The Record",
        "www.recordedfuture.com" => "The Recorded Future Inc",
        "regmedia.co.uk" => "The Register UK",
        "www.theregister.com" => "The Register UK",
        "www.theregister.co.uk" => "The Register UK",
        "therevelator.org" => "The Revelator",
        "www.sltrib.com" => "The Salt Lake Tribune",
        "www.sciencetimes.com" => "The Science Times",
        "www.the-scientist.com" => "LabX Media Group",
        "www.scotsman.com" => "The Scotsman",
        "www.thescottishfarmer.co.uk" => "The Scottish Farmer UK",
        "www.gov.scot" => "The Scottish Government",
        "www.sparrowmedia.net" => "The Sparrow Project",
        "www.spectator.co.uk" => "The Spectator UK",
        "www.spokesman.com" => "The Spokesman Review",
        "sporks.space" => "The Sporks Space",
        "www.standardmedia.co.ke" => "The Standard KE",
        "www.thestar.com.my" => "The Star MY",
        "www.thestatesman.com" => "The Statesman",
        "www.straitstimes.com" => "The Straits Times",
        "www.aspistrategist.org.au" => "The Strategist",
        "www.thestreet.com" => "The Street",
        "www.the-sun.com" => "The Sun",
        "www.thesun.co.uk" => "The Sun",
        "www.thesundaily.my" => "The SunDaily MY",
        "www.thetimes.co.uk" => "The Sunday Times UK",
        "www.thetablet.co.uk" => "The Tablet",
        "www.thetechnobee.com" => "The Techno Bee",
        "www.thetelegraphandargus.co.uk" => "The Telegraph And Argus UK",
        "www.telegraphindia.com" => "The Telegraph IN",
        "www.telegraph.co.uk" => "The Telegraph UK",
        "www.texastribune.org" => "The Texas Tribune",
        "www.timesgazette.com" => "The Times Gazette",
        "www.timesofisrael.com" => "The Times Of Israel",
        "www.nwitimes.com" => "The Times Of Northwest Indiana",
        "www.thetimestribune.com" => "The Times Tribune",
        "www.thestar.com" => "The Toronto Star",
        "www.thetrace.org" => "The Trace",
        "www.tribuneindia.com" => "The Tribune IN",
        "www.contractsfinder.service.gov.uk" => "The United Kingdom",
        "committees.parliament.uk" => "The United Kingdom Parliament",
        "ccrc.gov.uk" => "The United Kingdom Criminal Cases Review Commission",
        "news.npcc.police.uk" => "The United Kingdom",
        "www.gov.uk" => "The United Kingdom",
        "thevaluable.dev" => "The Valuable Dev",
        "www.theverge.com" => "The Verge",
        "www.thevintagenews.com" => "The Vintage News",
        "www.wsj.com" => "The Wall Street Journal",
        "www.washingtonpost.com" => "The Washington Post",
        "www.washingtontimes.com" => "The Washington Times",
        "theweek.com" => "The Week",
        "www.theweek.in" => "The Week",
        "thewire.in" => "The Wire",
        "thewirecutter.com" => "The Wirecutter",
        "www.thewrap.com" => "The Wrap",
        "thezerohack.com" => "The Zero Hack",
        "theor.xyz" => "Theor",
        "thinkrealstate.com" => "Think Real State",
        "blog.thinkst.com" => "Thinkst",
        "thinksustainabilityblog.com" => "Think Sustainability",
        "searchengineland.com" => "Third Door Media LLC",
        "www.xythobuz.de" => "Thomas Buck",
        "www.softwaremaxims.com" => "Thomas Depierre",
        "medienbaecker.com" => "Thomas Günther",
        "blog.habets.se" => "Thomas Habets",
        "thomask.sdf.org" => "Thomas Karpiniec",
        "domm.plix.at" => "Thomas Klausner",
        "thomasrigby.com" => "Thomas Rigby",
        "th0mas.nl" => "Thomas Rinsma",
        "thomasward.com" => "Thomas Ward",
        "thoughtbot.com" => "Thoughtbot Inc",
        "bored.horse" => "Thord D Hedengren",
        "blog.alteholz.eu" => "Thorsten Alteholz",
        "thorstenball.com" => "Thorsten Ball",
        "registerspill.thorstenball.com" => "Thorsten Ball",
        "threatpost.com" => "Threat Post",
        "threema.ch" => "Threema GmbH",
        "blog.talosintelligence.com" => "Threat Source",
        "www.threatspike.com" => "Threat SpikeLabs",
        "djmag.com" => "Thrust Publishing Ltd",
        "theholytachanka.com" => "THT",
        "thumbwind.com" => "Thumbwind Publications LLC",
        "blog.thunderbird.net" => "Thunderbird",
        "www.thurrott.com" => "Paul Thurrott",
        "freetibet.org" => "Tibet",
        "www.contactmagazine.net" => "Tibet",
        "www.phayul.com" => "Tibet",
        "www.thetibetpost.com" => "Tibet",
        "www.tibetanjournal.com" => "Tibet",
        "www.tibetanreview.net" => "Tibet",
        "tidbits.com" => "TidBITS",
        "tigerbeetle.com" => "TigerBeetle Inc",
        "tilde.club" => "Tilde",
        "www.tillitis.se" => "Tilitis AB",
        "www.timbornholdt.com" => "Tim Bornholdt",
        "www.tfeb.org" => "Tim Bradshaw",
        "www.tbray.org" => "Tim Bray",
        "timcoatesinsights.wordpress.com" => "Tim Coates",
        "timcolwill.com" => "Tim Colwill",
        "blog.cotten.io" => "Tim Cotten",
        "oylenshpeegul.gitlab.io" => "Tim Heaney",
        "timkadlec.com" => "Tim Kadlec",
        "timkellogg.me" => "Tim Kellogg",
        "www.timdbg.com" => "Tim Misiak",
        "time.com" => "Time",
        "content.time.com" => "Time",
        "www.timeout.com" => "Time Out England Limited",
        "www.thetimes.com" => "Times Media Limited",
        "www.timeshighereducation.com" => "Times Higher Education",
        "blogs.timesofisrael.com" => "Times Of Israel",
        "jewishnews.timesofisrael.com" => "Times Of Israel",
        "timesofsandiego.com" => "Times Of San Diego",
        "timmyomahony.com" => "Timmy OMahony",
        "timotijhof.net" => "Timo Tijhof",
        "www.understandingai.org" => "Timothy B Lee",
        "snyder.substack.com" => "Timothy Snyder",
        "timvisee.com" => "Tim Visee",
        "telecominfraproject.com" => "TIP",
        "www.tirereview.com" => "Tire Review",
        "www.titledrops.net" => "Title Drops",
        "tittlepress.com" => "TittlePress",
        "www.barik.net" => "Titus Barik",
        "tla.systems" => "TLA Systems",
        "www.tmz.com" => "TMZ",
        "tnc.news" => "TNC",
        "tnsr.org" => "TNSR",
        "tbspace.de" => "Tobias Mädel",
        "tobykurien.com" => "Toby Kurien",
        "www.today.com" => "Today",
        "www.todayifoundout.com" => "Today I Found Out",
        "www.todayintabs.com" => "Today in Tabs",
        "www.together.xyz" => "Together",
        "tokenpost.com" => "Token Post",
        "tolkiengateway.net" => "Tolkien Gateway",
        "mloduchowski.com" => "Tomasz Mloduchowski",
        "tomdispatch.com" => "TomDispatch",
        "tomgamon.com" => "Tom Gamon",
        "tomgreenwood.substack.com" => "Tom Greenwood",
        "tomlehrersongs.com" => "Tom Lehrer Songs",
        "macwright.com" => "Tom MacWright",
        "macwright.org" => "Tom MacWright",
        "wheybags.com" => "Tom Mason",
        "cholla.mmto.org" => "Tom Trebisky",
        "eagain.net" => "Tommi Virtanen",
        "www.tommyp.org" => "Tommy Palmer",
        "sanctum.geek.nz" => "Tom Ryder",
        "blog.sanctum.geek.nz" => "Tom Ryder",
        "www.tomsguide.com" => "Tom's Guide",
        "www.tomshardware.com" => "Tom's Hardware",
        "communities-dominate.blogs.com" => "Tomi Ahonen",
        "www.zylstra.org" => "Ton Zijlstra",
        "dotat.at" => "Tony Finch",
        "eighty-twenty.org" => "Tony Garnock-Jones",
        "tontinton.com" => "Tony Solomonik",
        "it.toolbox.com" => "Toolbox Tech",
        "toolspond.com" => "Tools Pond",
        "top500.org" => "Top 500",
        "www.top500.org" => "Top 500",
        "toptechwire.com" => "Top TechWire",
        "toptechwire.com" => "Top TechWire",
        "topslakr.com" => "Topslakr",
        "kettunen.io" => "Topi Kettunen",
        "blog.torproject.org" => "Tor",
        "forum.torproject.net" => "Tor",
        "gitlab.torproject.org" => "Tor",
        "lists.torproject.org" => "Tor",
        "status.torproject.org" => "Tor",
        "torontosun.com" => "Toronto Sun",
        "torrentfreak.com" => "Torrent Freak",
        "towardsdatascience.com" => "Towards Data Science",
        "tracydurnell.com" => "Tracy Durnell",
        "www.thecurrent.com" => "The Trade Desk",
        "blog.trailofbits.com" => "Trail of Bits",
        "www.railwaypro.com" => "Trains",
        "www.translinkcf.fi" => "Trans Link",
        "transactional.blog" => "Transactional Blog",
        "site.transitapp.com" => "TransitApp",
        "www.transalt.org" => "Transportation",
        "treefoundation.org" => "TREE",
        "blog.trendmicro.com" => "Trend Micro",
        "www.trendmicro.com" => "Trend Micro",
        "www.trentonian.com" => "Trentonian",
        "www.trovster.com" => "Trevor Morris",
        "triblive.com" => "Trib",
        "tribunetimes.co.uk" => "Tribune Times",
        "www.musclecarsandtrucks.com" => "Tri-Power Media LLC",
        "www.trickster.dev" => "Trickster Dev",
        "www.tripplite.com" => "Tripp Lite",
        "www.tripwire.com" => "Tripwire",
        "www.troyhunt.com" => "Troy Hunt",
        "troypatterson.me" => "Troy Patterson",
        "www.trtworld.com" => "TRT World",
        "www.truenas.com" => "TrueNAS",
        "true-tech.net" => "TrueTech",
        "news.trust.org" => "Trust",
        "www.truthandtransparency.org" => "Truth and Transparency",
        "www.truthdig.com" => "Truthdig",
        "truthout.org" => "TruthOut",
        "www.tubsta.com" => "Tubsta",
        "tudorr.ro" => "Tudor Roman",
        "now.tufts.edu" => "Tufts University",
        "tukaani.org" => "The Tukaani Project",
        "www.tuko.co.ke" => "TUKOKE",
        "tumfatig.net" => "TuMFatig",
        "www.tumfatig.net" => "TuMFatig",
        "www.tumblr.com" => "Tumblr",
        "turingpi.com" => "Turing Pi",
        "www.aa.com.tr" => "Turkey",
        "www.turkishminute.com" => "Turkish Minute",
        "blog.turso.tech" => "Turso",
        "www.tusacentral.com" => "Tusa Central",
        "tuta.com" => "Tutao GmbH",
        "tutanota.com" => "Tutao GmbH",
        "tvier.net" => "Tvier",
        "tweedegolf.nl" => "Tweed Golf",
        "www.twilio.com" => "Twilio Inc",
        "www.twincities.com" => "TwinCities Pioneer Press",
        "twitgoo.com" => "Twitgoo",
        "blog.twitter.com" => "Twitter",
        "www.twitterandteargas.org" => "Twitter And Tear Gas",
        "musings.tychi.me" => "Ty Chi",
        "codefaster.substack.com" => "Tyler Adams",
        "tylercipriani.com" => "Tyler Cipriani",
        "tkte.ch" => "Tyler Kennedy",
        "tylerrussell.dev" => "Tyler Russell",
        "tylersticka.com" => "Tyler Sticka",
        "typeable.io" => "Typeable",
        "typst.app" => "Typst",
        "www.tyreextinguishers.com" => "Tyr Extinguishers",
        "ubuntu.com" => "Ubuntu",
        "ubuntuhandbook.org" => "Ubuntu Handbook",
        "www.ubuntupit.com" => "Ubuntu Pit",
        "www.ubuntubuzz.com" => "Ubuntubuzz",
        "businessfocus.co.ug" => "Uganda",
        "www.ugchristiannews.com" => "Uganda Christian News",
        "www.rugu.dev" => "Uğur Erdem Seyfi",
        "www.northwalespioneer.co.uk" => "North Wales Pioneer",
        "www.england.nhs.uk" => "National Health Service UK",
        "assets.publishing.service.gov.uk" => "UK",
        "www.judiciary.uk" => "UK",
        "www.ons.gov.uk" => "UK",
        "www.ukri.org" => "UK Research and Innovation",
        "ouci.dntb.gov.ua" => "Ukraine",
        "www.chathamhouse.org" => "UKRIIA",
        "orangejuiceliberationfront.com" => "Uli Kusterer",
        "desapublications.un.org" => "UN",
        "inweh.unu.edu" => "UN",
        "news.un.org" => "UN",
        "ohchr.org" => "UN",
        "treaties.un.org" => "UN",
        "unfccc.int" => "UN",
        "unric.org" => "UN",
        "until.un.org" => "UN",
        "www.un.org" => "UN",
        "www.unccd.int" => "UNCCD",
        "www.unep.org" => "UN",
        "www.unesco.org" => "UNESCO",
        "www3.astronomicalheritage.net" => "UNESCO",
        "www.genevaenvironmentnetwork.org" => "UN Environment Programme",
        "www.unchainedatlast.org" => "Unchained At Last",
        "undark.org" => "Undark",
        "undeadly.org" => "Undeadly",
        "www.undeadly.org" => "Undeadly",
        "www.unfpa.org" => "UNFPA",
        "www.unfriendlygrinch.info" => "Unfriendly Grinch",
        "unherd.com" => "UnHerd",
        "www.ohchr.org" => "UN Human Rights",
        "www.tuhs.org" => "The Unix Heritage Society",
        "unmitigatedrisk.com" => "Unmitigated Risk",
        "www.aalto.fi" => "Aalto University",
        "lib.tkk.fi" => "Aalto University",
        "acris.aalto.fi" => "Aalto University",
        "journals.library.ualberta.ca" => "uni Alberta",
        "www.universalhub.com" => "Universal Hub",
        "news.arizona.edu" => "University of Arizona",
        "www2.cs.arizona.edu" => "University of Arizona",
        "asunow.asu.edu" => "uni Arizona State",
        "azpbs.org" => "uni Arizona State",
        "news.asu.edu" => "uni Arizona State",
        "usenate.asu.edu" => "uni Arizona State",
        "news.uark.edu" => "uni Arkansas",
        "besacenter.org" => "uni Bar-Ilan",
        "www.bath.ac.uk" => "uni Bath",
        "scet.berkeley.edu" => "University of California, Berkeley",
        "btlj.org" => "University of California, Berkeley",
        "www.ocf.berkeley.edu" => "University of California, Berkeley",
        "health.ucdavis.edu" => "University of California, Davis",
        "scholarship.law.bu.edu" => "uni Boston",
        "oceans.ubc.ca" => "University of British Columbia",
        "blog.cs.brown.edu" => "uni Brown",
        "dornsife.usc.edu" => "University of Southern California",
        "bair.berkeley.edu" => "uni California",
        "cseweb.ucsd.edu" => "uni California",
        "today.ucsd.edu" => "uni California",
        "dailybruin.com" => "uni California",
        "library.ucsd.edu" => "uni California",
        "www.caida.org" => "uni California",
        "ucnet.universityofcalifornia.edu" => "uni California",
        "ucsdguardian.org" => "uni California",
        "www.dailycal.org" => "uni California",
        "www.highlandernews.org" => "uni California",
        "www.ucdavis.edu" => "uni California",
        "www.cst.cam.ac.uk" => "The University of Cambridge",
        "www.jbs.cam.ac.uk" => "The University of Cambridge",
        "ccaf.io" => "The University of Cambridge",
        "plus.maths.org" => "uni Cambridge",
        "www.cambridge.org" => "uni Cambridge",
        "www.varsity.co.uk" => "uni Cambridge",
        "www.cl.cam.ac.uk" => "uni Cambridge",
        "kb.cert.org" => "Carnegie Mellon University",
        "www.cs.cmu.edu" => "Carnegie Mellon University",
        "www.scs.cmu.edu" => "Carnegie Mellon University",
        "observer.case.edu" => "uni Case Western Reserve",
        "www.unicef.org" => "UNICEF",
        "www.cmich.edu" => "uni Central Michigan",
        "www.journals.uchicago.edu" => "The University of Chicago Press",
        "bfi.uchicago.edu" => "The University of Chicago",
        "harris.uchicago.edu" => "The University of Chicago",
        "news.uchicago.edu" => "The University of Chicago",
        "www2.lib.uchicago.edu" => "The University of Chicago",
        "www.ucl.ac.uk" => "uni College London",
        "curc.readthedocs.io" => "University of Colorado Boulder",
        "www.colorado.edu" => "University of Colorado Boulder",
        "csuglobal.edu" => "uni Colorado State",
        "news.climate.columbia.edu" => "uni Columbia",
        "columbianewsservice.com" => "uni Columbia",
        "www.publichealth.columbia.edu" => "uni Columbia",
        "dc.alumni.columbia.edu" => "uni Columbia",
        "knightcolumbia.org" => "uni Columbia",
        "www.cs.columbia.edu" => "uni Columbia",
        "cornellfreespeech.com" => "Cornell Free Speech Alliance",
        "news.cornell.edu" => "uni Cornell",
        "www.law.cornell.edu" => "uni Cornell",
        "blog.unicode.org" => "Unicode",
        "fossforce.com" => "Unicorn Media",
        "blogs.library.duke.edu" => "Duke University",
        "techpolicy.sanford.duke.edu" => "Duke University",
        "sites.duke.edu" => "Duke University",
        "sites.law.duke.edu" => "Duke University",
        "today.duke.edu" => "Duke University",
        "web.law.duke.edu" => "Duke University",
        "www.uef.fi" => "uni Eastern Finland",
        "pure.tue.nl" => "Eindhoven University of Technology",
        "research.tue.nl" => "Eindhoven University of Technology",
        "emorywheel.com" => "Emory University",
        "www.emorywheel.com" => "Emory University",
        "www.fau.edu" => "uni Florida Atlantic University",
        "zeus.ugent.be" => "uni Ghent",
        "www.harvardpress.com" => "Harvard Press LLC",
        "misinforeview.hks.harvard.edu" => "Harvard University",
        "hls.harvard.edu" => "Harvard University",
        "news.harvard.edu" => "Harvard University",
        "niemanreports.org" => "Harvard University",
        "clinic.cyber.harvard.edu" => "Harvard University",
        "gking.harvard.edu" => "Harvard University",
        "hbr.org" => "Harvard University",
        "www.belfercenter.org" => "Harvard University",
        "www.harvardmagazine.com" => "Harvard University",
        "www.hsph.harvard.edu" => "Harvard University",
        "www.thecrimson.com" => "Harvard University",
        "www.health.harvard.edu" => "Harvard University",
        "manoa.hawaii.edu" => "University of Hawaii",
        "scholarspace.manoa.hawaii.edu" => "University of Hawaii",
        "www.hawaii.edu" => "University of Hawaii",
        "carey.jhu.edu" => "John Hopkins University",
        "hub.jhu.edu" => "John Hopkins University",
        "www.cs.jhu.edu" => "John Hopkins University",
        "www.jhuapl.edu" => "John Hopkins University",
        "lkml.iu.edu" => "uni Indiana",
        "kb.iu.edu" => "uni Indiana",
        "ebeowulf.uky.edu" => "University of Kentucky",
        "www.kcl.ac.uk" => "uni King's College London",
        "www.unileverusa.com" => "unilever",
        "www.nsc.liu.se" => "uni Linköping",
        "www.lunduniversity.lu.se" => "uni Lund",
        "blogs.umass.edu" => "uni Massachusetts",
        "peri.umass.edu" => "uni Massachusetts",
        "www.umass.edu" => "uni Massachusetts",
        "press.umich.edu" => "University of Michigan",
        "www.citi.umich.edu" => "University of Michigan",
        "umdearborn.edu" => "University of Michigan",
        "heritage.umich.edu" => "University of Michigan",
        "impact.govrel.umich.edu" => "University of Michigan",
        "it.umich.edu" => "University of Michigan",
        "lib.umich.edu" => "University of Michigan",
        "michigan.it.umich.edu" => "University of Michigan",
        "quod.lib.umich.edu" => "University of Michigan",
        "www.lib.umich.edu" => "University of Michigan",
        "news.engin.umich.edu" => "University of Michigan",
        "web.eecs.umich.edu" => "University of Michigan",
        "news.umich.edu" => "University of Michigan",
        "president.umich.edu" => "University of Michigan",
        "record.umich.edu" => "University of Michigan",
        "repository.law.umich.edu" => "University of Michigan",
        "publicaffairs.vpcomm.umich.edu" => "University of Michigan",
        "www.michigandaily.com" => "University of Michigan",
        "wallacehouse.umich.edu" => "University of Michigan",
        "news.mit.edu" => "uni MIT",
        "thereader.mitpress.mit.edu" => "uni MIT",
        "onlinedegrees.unr.edu" => "uni Nevada",
        "www.cs.unm.edu" => "uni New Mexico",
        "news.unm.edu" => "uni New Mexico",
        "blog.jipel.law.nyu.edu" => "uni New York",
        "wagner.nyu.edu" => "uni New York",
        "citap.unc.edu" => "uni North Carolina",
        "newspaperownership.com" => "uni North Carolina",
        "www.cs.unc.edu" => "uni North Carolina",
        "scholarship.law.unc.edu" => "uni North Carolina",
        "huntnewsnu.com" => "uni Northeastern",
        "agcrops.osu.edu" => "Ohio State University",
        "library.osu.edu" => "Ohio State University",
        "news.osu.edu" => "Ohio State University",
        "www.ucanews.com" => "Union Of Catholic Asian News",
        "www.critic.co.nz" => "uni Otago",
        "reutersinstitute.politics.ox.ac.uk" => "uni Oxford",
        "people.maths.ox.ac.uk" => "uni Oxford",
        "www.blopig.com" => "uni Oxford",
        "ento.psu.edu" => "uni Pennsylvania State",
        "www.thetimes-tribune.com" => "The Times-Tribue, Scranton, PA",
        "events.seas.upenn.edu" => "uni Pennsylvania",
        "mackinstitute.wharton.upenn.edu" => "uni Pennsylvania",
        "fossilfueldissociation.princeton.edu" => "uni Princeton",
        "tv-watches-you.princeton.edu" => "uni Princeton",
        "you.have.fail" => "UniQMG",
        "homepage.cs.uri.edu" => "uni Rhode Island",
        "kjzz.org" => "uni Rio Salado College",
        "www.uni-rostock.de" => "uni Rostock",
        "rutgershonorsblog.wordpress.com" => "uni Rutgers",
        "www.rutgers.edu" => "uni Rutgers",
        "www.stmarytx.edu" => "uni Saint Mary",
        "www.sheffield.ac.uk" => "uni Sheffield",
        "the-peak.ca" => "uni Simon Frase",
        "people.math.sc.edu" => "uni South Carolina",
        "www.ijpr.org" => "uni Southern Oregon",
        "cs.stanford.edu" => "Stanford University",
        "www-cs-faculty.stanford.edu" => "Stanford University",
        "crfm.stanford.edu" => "Stanford University",
        "cyber.fsi.stanford.edu" => "Stanford University",
        "news.stanford.edu" => "Stanford University",
        "pacscenter.stanford.edu" => "Stanford University",
        "seclab.stanford.edu" => "Stanford University",
        "stacks.stanford.edu" => "Stanford University",
        "stanforddaily.com" => "Stanford University",
        "cyberlaw.stanford.edu" => "Stanford University",
        "mahb.stanford.edu" => "Stanford University",
        "web.stanford.edu" => "Stanford University",
        "pcl.stanford.edu" => "Stanford University",
        "www.stanforddaily.com" => "Stanford University",
        "bitsavers.informatik.uni-stuttgart.de" => "uni Stuttgart",
        "www.sydney.edu.au" => "uni Sydney",
        "news.syr.edu" => "uni Syracuse",
        "thecollege.syr.edu" => "uni Syracuse",
        "www.unitedforpeace.org" => "United For Peace",
        "trepo.tuni.fi" => "uni Tampere",
        "www.zeileis.org" => "Achim Zeileis",
        "osg.tuhh.de" => "Technische Universität Hamburg",
        "www.tum.de" => "Technische Universität München",
        "www.tn.gov" => "Tennessee",
        "www.mtsu.edu" => "Middle Tennessee State University",
        "news.utk.edu" => "University of Tennessee",
        "web.eecs.utk.edu" => "University of Tennessee",
        "www.jsg.utexas.edu" => "University of Texas",
        "radionavlab.ae.utexas.edu" => "University of Texas",
        "www.universityworldnews.com" => "University World News",
        "utcc.utoronto.ca" => "University of Toronto",
        "www.scss.tcd.ie" => "uni Trinity College Dublin",
        "www.utu.fi" => "uni Turku",
        "www.universetoday.com" => "Universe Today",
        "www.dre.vanderbilt.edu" => "uni Vanderbilt",
        "engineering.virginia.edu" => "University of Virginia",
        "www.cs.virginia.edu" => "University of Virginia",
        "vtx.vt.edu" => "uni Virginia Polytechnic Institute and State",
        "blog.communitydata.science" => "uni Washington",
        "com.uw.edu" => "uni Washington",
        "www.whitman.edu" => "uni Whitman",
        "whitmanwire.com" => "uni Whitman",
        "www.unixmen.com" => "Unix Men",
        "unixsheikh.com" => "Unix Sheikh",
        "www.unixsheikh.com" => "Unix Sheikh",
        "news.wisc.edu" => "The University of Wisconsin",
        "wiscprivacy.com" => "The University of Wisconsin",
        "yaak.app" => "Yaak",
        "avalon.law.yale.edu" => "Yale University",
        "e360.yale.edu" => "Yale University",
        "law.yale.edu" => "Yale University",
        "yaleclimateconnections.org" => "Yale University",
        "www.yardbarker.com" => "YB Media LLC",
        "investors.unity.com" => "Unity Technologies",
        "www.univision.com" => "Univision Communications Inc",
        "unnamed.website" => "Unnamed Website",
        "www.upguard.com" => "UpGuard",
        "www.upi.com" => "UPI",
        "www.upworthy.com" => "Upworthy",
        "popovicu.com" => "Uros Popovic",
        "www.dni.gov" => "US Director of National Intelligence",
        "www.whitehouse.gov" => "USA",
        "public-inspection.federalregister.gov" => "USA",
        "www.amc.af.mil" => "USAF",
        "www.usagm.gov" => "USAGM",
        "aspr.hhs.gov" => "US Administration for Strategic Preparedness and Response",
        "www.army.mil" => "USARMY",
        "www.atf.gov" => "USATF",
        "www.gao.gov" => "USGAO",
        "www.usbr.gov" => "USBR",
        "us-cert.cisa.gov" => "USCERT",
        "www.us-cert.gov" => "USCERT",
        "www.uscirf.gov" => "USCIRF",
        "crsreports.congress.gov" => "US Congress",
        "www.congress.gov" => "US Congress",
        "www.cbp.gov" => "USCBP",
        "www.solarium.gov" => "USCSC",
        "www.aphis.usda.gov" => "USDA",
        "www.fas.usda.gov" => "USDA",
        "www.state.gov" => "US Dept Of State",
        "www.transportation.gov" => "US Dept Of State",
        "www.hhs.gov" => "US Dept Of Health and Human Services",
        "www.dvidshub.net" => "US DOD",
        "dodcio.defense.gov" => "US DOD",
        "media.defense.gov" => "US DOD",
        "www.defense.gov" => "US DOD",
        "www.doi.gov" => "USDOI",
        "www.justice.gov" => "USDOJ",
        "www.eia.gov" => "US EIA",
        "docs.fcc.gov" => "US FCC",
        "www.fcc.gov" => "US FCC",
        "www.fda.gov" => "US FDA",
        "www.federalreservehistory.org" => "US Federal Reserve",
        "www.usgs.gov" => "US Geological Survey",
        "home.treasury.gov" => "US Treasury",
        "www.tigta.gov" => "US Treasury Inspector General",
        "www.marinecorpstimes.com" => "USMC",
        "www.marcorsyscom.marines.mil" => "USMC",
        "useplaintext.email" => "Use plaintext email",
        "www.usenix.org" => "USENIX",
        "www.federalregister.gov" => "US Federal Register",
        "docs.house.gov" => "US House Of Representatives",
        "energycommerce.house.gov" => "US House Of Representatives",
        "gottheimer.house.gov" => "US House Of Representatives",
        "judiciary.house.gov" => "US House Of Representatives",
        "lofgren.house.gov" => "US House Of Representatives",
        "mcgovern.house.gov" => "US House Of Representatives",
        "morelle.house.gov" => "US House Of Representatives",
        "www.merkley.senate.gov" => "US House Of Representatives",
        "oversightdemocrats.house.gov" => "US House Of Representatives",
        "schiff.house.gov" => "US House Of Representatives",
        "www.weather.gov" => "US National Weather Service",
        "www.navytimes.com" => "US Navy Times",
        "creditcards.usnews.com" => "US News",
        "money.usnews.com" => "US News And World Report",
        "www.usnews.com" => "US News And World Report",
        "news.usni.org" => "USNI",
        "www.nps.gov" => "USNPS",
        "www.stateoig.gov" => "USOIG",
        "www.budget.senate.gov" => "US Senate",
        "www.foreign.senate.gov" => "US Senate",
        "www.hsgac.senate.gov" => "US Senate",
        "www.klobuchar.senate.gov" => "US Senate",
        "www.markey.senate.gov" => "US Senate",
        "www.sanders.senate.gov" => "US Senate",
        "www.schmitt.senate.gov" => "US Senate",
        "www.warner.senate.gov" => "US Senate",
        "www.warren.senate.gov" => "US Senate",
        "www.wyden.senate.gov" => "US Senate",
        "www.sigar.mil" => "US SIGAR",
        "ustr.gov" => "USTR",
        "www.uswitch.com" => "USwitch",
        "www.userlandia.com" => "Userlandia",
        "www.utilitydive.com" => "Utility Dive",
        "utkuufuk.com" => "Utku",
        "www.ufried.com" => "Uwe Friedrichsen",
        "uxdesign.cc" => "UXCollective",
        "www.uxtigers.com" => "UX Tigers",
        "vadimkravcenko.com" => "Vadim Kravcenko",
        "valentin.willscher.de" => "Valentin Willscher",
        "www.valerionappi.it" => "Valerio Nappi",
        "www.thevalleypost.com" => "Valley Post",
        "movieweb.com" => "Valnet",
        "shufflingbytes.com" => "Valtteri Lehtinen",
        "www.valuewalk.com" => "Value Walk",
        "vancouversun.com" => "Vancouver Sun",
        "www.vanguardngr.com" => "Vanguard NG",
        "www.vanityfair.com" => "Vanity Fair",
        "variety.com" => "Variety",
        "varnish-cache.org" => "Varnish	HTTP Cache",
        "www.varonis.com" => "Varonis",
        "www.vaticannews.va" => "Vatican News",
        "www.vatupdate.com" => "VATupdate",
        "www.ribbonfarm.com" => "Venkatesh Rao",
        "venturebeat.com" => "Venture Beat",
        "www.railway-technology.com" => "GlobalData plc",
        "vereis.com" => "Vereis",
        "verfassungsblog.de" => "Verfassungsblog",
        "verietyinfo.com" => "Verietyinfo",
        "vermaden.wordpress.com" => "Vermaden",
        "www.reformer.com" => "Brattleboro Reformer, Vermont",
        "vtdigger.org" => "Vermont Journalism Trust Ltd",
        "verschwoerhaus.de" => "Verschwörhaus",
        "www.vertiv.com" => "Vertiv Group Corporation",
        "vesa.org" => "VESA",
        "scrollprize.org" => "Vesuvius Challenge",
        "news.va.gov" => "US Department of Veterans Affairs",
        "vldb.org" => "VLDB Endowment Inc",
        "vez.mrsk.me" => "Vez.mrsk.me",
        "www.vibilagare.se" => "Vi Bilägare",
        "www.refinery29.com" => "Vice Media Group",
        "www.vice.com" => "Vice Media Group",
        "vicki.substack.com" => "Vicki Boykis",
        "vicksburgnews.com" => "Vickburg Daily News",
        "victor.kropp.name" => "Victor Kropp",
        "zverok.space" => "Victor Shepelev",
        "www.vidarholen.net" => "Vidarholen",
        "yewtu.be" => "Video",
        "videocardz.com" => "Video Cardz",
        "www.videolan.org" => "VideoLAN",
        "blog.viditb.com" => "Vidit Bhargava",
        "www.vikash.nl" => "Vikash",
        "vimtricks.com" => "Vim Newsletter",
        "vincent.bernat.ch" => "Vincent Bernat",
        "www.vincentlammens.be" => "Vincent Lammens",
        "www.vinchin.com" => "Vinchin.com",
        "www.vincentdelft.be" => "Vincent Delft",
        "latex.now.sh" => "Vincent Dörig",
        "vintageapple.org" => "Vintage Apple",
        "www.vintagecomputing.com" => "Vintage Computing And Gaming",
        "www.vintag.es" => "Vintage Everyday",
        "www.vintageisthenewold.com" => "Vintage Is The New Old",
        "blog.viraptor.info" => "Viraptor",
        "www.virginiamercury.com" => "Virginia Mercury",
        "www.virginiaroberts.com" => "Virginia Roberts",
        "lis.virginia.gov" => "Virginia USA",
        "www.governor.virginia.gov" => "Virginia USA",
        "virtualizationreview.com" => "Virtualization",
        "virtuallyfun.com" => "Virtualization",
        "www.virusbulletin.com" => "Virus Bulletin",
        "www.hardhats.org" => "VistA",
        "www.visualcapitalist.com" => "Visual Capitalist",
        "vitonsky.net" => "Robert Vitonsky",
        "vitux.com" => "Vitux",
        "vivaldi.com" => "Vivaldi",
        "vmssoftware.com" => "VMS Software",
        "www.polygraph.info" => "VOA News",
        "projects.voanews.com" => "VOA News",
        "www.voanews.com" => "VOA News",
        "www.insidevoa.com" => "VOA News",
        "www.voicendata.com" => "Voice And Data",
        "voicebot.ai" => "Voicebot AI",
        "www.voiceofsandiego.org" => "Voice Of San Diego",
        "voidlinux.org" => "Void Linux",
        "www.vox.com" => "Vox",
        "www.mmafighting.com" => "Vox Media LLC",
        "www.thecut.com" => "Vox Media Network",
        "www.polygon.com" => "Vox Media",
        "vpnpro.com" => "VPN Pro",
        "blog.vpntracker.com" => "VPN Tracker",
        "vu.nl" => "Vrije Universiteit",
        "www.vusec.net" => "Vrije Universiteit",
        "docs.vultr.com" => "Vultr",
        "www.vulture.com" => "Vulture",
        "w3techs.com" => "W3 Techs",
        "wacotrib.com" => "Waco Tribune-Herald",
        "www.iwader.co.uk" => "Wade Urry",
        "blog.waleedkhan.name" => "Waleed Khan",
        "www.walesonline.co.uk" => "Wales UK",
        "wallabag.nixnet.services" => "Wallanag",
        "walledculture.org" => "Walled Culture",
        "thewalrus.ca" => "The Walrus",
        "thewaroncars.org" => "The War on Cars",
        "www.warhammer-community.com" => "Warhammer",
        "bsdimp.blogspot.com" => "Warner Losh",
        "www.warp.dev" => "Warp",
        "www.warwickshire.gov.uk" => "Warwickshie County Council, UK",
        "washbear.neocities.org" => "Washbear",
        "wbng.org" => "Washingon-Baltimore News Guild",
        "www.washingtonexaminer.com" => "Washington Examiner",
        "washingtonspectator.org" => "The Washington Spectator",
        "washingtontimes.com" => "Washingon Times",
        "www.washingtonian.com" => "Washingtonian",
        "washingtonmonthly.com" => "Washington Monthly",
        "washingtonpress.com" => "Washington Press",
        "uwaterloo.ca" => "University of Waterloo",
        "www.watereducation.org" => "Water Education Foundation",
        "www.watoday.com.au" => "WA Today",
        "www.wabe.org" => "WABE Radio",
        "www.wbaltv.com" => "WBAL TV",
        "www.wbez.org" => "WBEZ Radio",
        "www.wbur.org" => "WBUR Radio",
        "www.wgacontract2023.org" => "WGA Contract 2023",
        "www.wcax.com" => "WCAX TV",
        "wccftech.com" => "WCCF Tech",
        "wccoradio.radio.com" => "WCCO Radio",
        "equitablegrowth.org" => "WCEG",
        "www.wcvb.com" => "WCVB",
        "news.wgcu.org" => "WGCU",
        "www.wmuk.org" => "WMUK Radio",
        "www.weareteachers.com" => "WeAreTeachers",
        "webdevelopmenthistory.com" => "Web Development History",
        "calendar.perfplanet.com" => "Web Performance Calendar",
        "www.vpnmentor.com" => "Webselenese Ltd",
        "websockets.readthedocs.io" => "Websockets",
        "build.typogram.co" => "Wentin",
        "www.weny.com" => "WENY",
        "www.wevolver.com" => "Wevolver",
        "www.wunc.org" => "WUNC North Carolina Public Radio",
        "webkit.org" => "WebKit",
        "www.webmd.com" => "WebMD",
        "www.webpronews.com" => "Web Pro News",
        "www.websiteoptimization.com" => "Web Site Optimization",
        "weis2021.econinfosec.org" => "WEIS 2021",
        "wellcome.ac.uk" => "Wellcome",
        "wellcome.org" => "Wellcome",
        "wernerantweiler.ca" => "Prof. Werner Antweiler",
        "blog.wesleyac.com" => "Wesley Aptekar Cassels",
        "www.allthingsdistributed.com" => "Dr Werner Vogels",
        "notebook.wesleyac.com" => "Wesley Aptekar Cassels",
        "www.wezm.net" => "Wesley Moore",
        "www.wctrib.com" => "West Central Tribune",
        "www.joanwestenberg.com" => "Westenberg",
        "wfin.com" => "WFIN Radio",
        "www.wfmz.com" => "WFMZ TV",
        "www.wftv.com" => "WFTV TV",
        "www.wfyi.org" => "WFYI Radio",
        "whbl.com" => "WHBL Radio",
        "whdh.com" => "WHDH TV",
        "www.wheelchairdriver.com" => "Wheel Chair Driver",
        "www.which.co.uk" => "WhichUK",
        "www.wietzebeukema.nl" => "Wietze Beukema",
        "qogrisys.medium.com" => "WIFI 7 Module manufacturer",
        "en.wikibooks.org" => "WikiBooks",
        "www.wikihow.com" => "WikiHow",
        "diff.wikimedia.org" => "WikiMedia",
        "meta.wikimedia.org" => "WikiMedia",
        "techblog.wikimedia.org" => "WikiMedia",
        "onlinelibrary.wiley.com" => "Wiley",
        "www.whizzy.org" => "Will Cooke",
        "www.highonscience.com" => "Will High",
        "lethain.com" => "Will Larson",
        "fy.blackhats.net.au" => "William",
        "retrohacker.substack.com" => "William Blankenship",
        "www.willsroot.io" => "William Liu",
        "yossarian.net" => "William Woodruff",
        "www.wweek.com" => "Williamette Week",
        "www.conveniencestore.co.uk" => "William Reed Business Media",
        "www.wilsoncenter.org" => "The Wilson Center",
        "blog.wilsonl.in" => "Wilson Lin",
        "www.wiltshiremuseum.org.uk" => "Wiltshire Archaeological and Natural History Society",
        "limited.systems" => "Wim Vanderbauwhede",
        "wimvanderbauwhede.codeberg.page" => "Wim Vanderbauwhede",
        "www.windowscentral.com" => "Windows Central",
        "www.windowscentral.com" => "Windows Central",
        "www.winespectator.com" => "Wine Spectator",
        "wired.me" => "Wired",
        "www.wired.com" => "Wired",
        "www.wired.co.uk" => "Wired",
        "blog.wireshark.org" => "Wireshark",
        "www.wireshark.org" => "Wireshark",
        "thecountyline.net" => "Wisconsin",
        "www.wpr.org" => "Wisconsin Public Radio",
        "www.wise-geek.com" => "WiseGEEK",
        "www.whiskeytangohotel.com" => "WhiskeyTangoHotel",
        "www.withguitars.com" => "WithGuitars",
        "without-systemd.org" => "Without Systemd",
        "zuckgotmefor.wixsite.com" => "Wix",
        "www.wiz.io" => "Wiz Inc",
        "maker.wiznet.io" => "WIZNet",
        "www.wksu.org" => "WKSU Radio",
        "palant.info" => "Wladimir Palant",
        "blog.frost.kiwi" => "Wladislav Artsimovich",
        "wleusch.wordpress.com" => "W Leusch",
        "public.wmo.int" => "WMO",
        "www.wnd.com" => "WND",
        "wng.org" => "WNG",
        "www.world-nuclear-news.org" => "WNN",
        "wolfstreet.com" => "Wolfstreet",
        "www.womenarehuman.com" => "Women Are Human",
        "www.wonkette.com" => "Wonkette",
        "mywiki.wooledge.org" => "Greg Wooledge",
        "wbk.one" => "Woongbin Kang",
        "wordfinderx.com" => "WordFinderX",
        "xwp8users.com" => "WordPerfect on Linux",
        "automattic.com" => "WordPress",
        "wpbuilderhelper.com" => "WordPress",
        "wptavern.com" => "WordPress",
        "www.workers.org" => "Workers World",
        "blogs.worldbank.org" => "World Bank",
        "data.worldbank.org" => "World Bank",
        "www.worldbank.org" => "World Bank",
        "www.weforum.org" => "World Economic Forum",
        "www.who.int" => "World Health Organization",
        "www.w3.org" => "World Wide Web Consortium",
        "webfoundation.org" => "World Wide Web Foundation",
        "worldcrunch.com" => "Worldcrunch",
        "rpms.worldvista.org" => "WorldVistA",
        "brainbaking.com" => "Wouter Groeneveld",
        "www.advancedcustomfields.com" => "WPEngine Inc",
        "wraltechwire.com" => "WRAL Techwire",
        "www.wraltechwire.com" => "WRAL Techwire",
        "www.wral.com" => "Capitol Broadcasting Company Inc",
        "write.as" => "Write.as",
        "wrla.ch" => "Wrlach",
        "worldrepublicnews.com" => "WRN",
        "wryl.tech" => "Wyrl",
        "wsau.com" => "WSAU Radio",
        "www.wsls.com" => "WSLS TV",
        "www.wsws.org" => "WSWS",
        "wtop.com" => "WTOP Radio",
        "news.wttw.com" => "WTTW TV",
        "wwfint.awsassets.panda.org" => "WWF",
        "www.worldwildlife.org" => "WWF",
        "www.wwf.org.uk" => "WWF",
        "wwf.fi" => "WWF",
        "x25519.ulfheim.net" => "X25519 Key Exchange",
        "x41-dsec.de" => "X41 D-Sec GmbH",
        "x61.ar" => "X61",
        "xavi.privatedns.org" => "Xavi92",
        "www.xbiz.com" => "XBiz",
        "www.xda-developers.com" => "XDA",
        "xeiaso.net" => "Xe's Blog",
        "christine.website" => "Xe",
        "www.fuzzygrim.com" => "Xila",
        "www.xinhuanet.com" => "Xinhua",
        "healthitsecurity.com" => "Xtelligent Healthcare Media",
        "www.xyte.ch" => "XueYao",
        "xayax.net" => "XAYAX",
        "finance.yahoo.com" => "Yahoo News",
        "in.news.yahoo.com" => "Yahoo News",
        "news.yahoo.com" => "Yahoo News",
        "sg.news.yahoo.com" => "Yahoo News",
        "www.yahoo.com" => "Yahoo News",
        "www.yakimaherald.com" => "Yakima Herald",
        "reyammer.io" => "Yanick Fratantonio",
        "www.yanisvaroufakis.eu" => "Yanis Varoufakis",
        "yarmo.eu" => "Yarmo Machenbach",
        "ykarroum.com" => "Yassir Karroum",
        "mangoumbrella.com" => "Yilei Yang",
        "yinan.me" => "Yinan",
        "bytes.yingw787.com" => "Ying787",
        "yle.fi" => "YLE",
        "yonkerstimes.com" => "Yonkers Times",
        "yordi.me" => "Yordi Verkroost",
        "yorickpeterse.com" => "Yorick Peterse",
        "yorkshirebylines.co.uk" => "Yorkshire Bylines",
        "www.yorkshireeveningpost.co.uk" => "Yorkshire Evening Post",
        "www.examinerlive.co.uk" => "Yorkshire Live",
        "yosefk.com" => "Yossi Kreinin",
        "docs.yottadb.com" => "YottaDB",
        "docs.yottadb.net" => "YottaDB",
        "yottadb.com" => "YottaDB",
        "yourstory.com" => "Your Story",
        "youtu.be" => "Youtube",
        "blog.yoshuawuyts.com" => "Yoshua Wuyts",
        "ypte.org.uk" => "YPTE",
        "www.yubico.com" => "Yubico AB",
        "yuexun.me" => "Yuexun",
        "yukinu.com" => "Yukinu",
        "norikitech.com" => "Yuri Karabatov",
        "molodtsov.me" => "Yury Molodtsov",
        "yusuf.fyi" => "Yusuf Bouzekri",
        "zach.bloomqu.ist" => "Zach Bloomquist",
        "www.zachdaniel.dev" => "Zach Daniel",
        "zach.se" => "Zach Denton",
        "flower.codes" => "Zach Flower",
        "www.dolthub.com" => "Zach Musgrave",
        "zackproser.com" => "Zach Proser",
        "ideolalia.com" => "Zach Tellman",
        "www.zachseward.com" => "Zach Seward",
        "zakaria.org" => "Zakaria",
        "zambianobserver.com" => "The Zambian Observer",
        "zed.dev" => "Zed",
        "zedshaw.com" => "Zed A Shaw",
        "repo.zenk-security.com" => "Zenk-Security",
        "zenodo.org" => "Zenodo",
        "zerforschung.org" => "Zerforschung",
        "zerodayengineering.com" => "Zero Day Engineering",
        "zerodha.tech" => "Zerodha Broking Ltd",
        "www.zerohedge.com" => "ZeroHedge",
        "zettelkasten.de" => "Zettlekasten",
        "ziglang.org" => "Zig",
        "hararelive.com" => "Zimbabwe",
        "www.techzim.co.zw" => "Zimbabwe",
        "www.architectmagazine.com" => "Zonda Media",
        "www.builderonline.com" => "Zonda Media",
        "www.zsl.org" => "The Zoological Society of London",
        "blog.zoom.us" => "Zoom",
        "www.zoommeetingsclassaction.com" => "Zoom",
        "www.getzola.org" => "Zola",
        "blog.zorin.com" => "Zorin Group",
        "blog.hyperknot.com" => "Zsolt Ero",
        "blog.zulip.com" => "Zulip",
        "ztoz.blog" => "Z to Z",
        "lists.zx2c4.com" => "Zx2c4",
        );
    
    state %queryLookup = (
        "www.csmonitor.com" => '\?icid=rss$',
        "www.dw.com" => '\?maca=.*$',
        "www.h2-view.com" => '\?utm.*$',
        "www.truthdig.com" => '\?utm.*$',
        );
    
    sub camelCase {
        my ($site) = (@_);
    
        # CamelCase makes "tags" easier for screen readers
        return(exists($siteLookup{$site}) ? $siteLookup{$site} : 0);
    }
    
    sub cleanQuery {
        my ($site, $url) = (@_);
    
        if (exists($queryLookup{$site})) {
    	$url =~ s/$queryLookup{$site}//;
        }
        return($url);
    }
    

    Links/lib/Links/SpamSites.pm

    package SpamSites 0.03;
    
    use parent qw(Exporter);
    use strict;
    use warnings;
    use feature qw(state);
    
    our @EXPORT = qw(KnownSpamSite);
    
    # see Git regarding update history
    
    sub KnownSpamSite {
        my ($site) = (@_);
    
        # define the hash just once and thereafter just reuse it
        state %junksite = (
    	"bullenweg.com" => 1,
            "bollyinside.com" => 1,
            "annarbortimes.com" => 1,
            "www.bollyinside.com" => 1,
    	"androidgram.com" => 1,
            "www.cvbj.biz" => 1,
    	"blogdot.tv" => 1,
            "www.cengnews.com" => 1,
    	"www.dailyfinland.fi" => 1,
    	"newsazi.com" => 1,
    	"then24.com" => 1,
            "thegoaspotlight.com" => 1,
            "www.juve-patent.com" => 1,
            "www.miragenews.com" => 1,
            "www.aviationanalysis.net" => 1,
    	"www.servethehome.com" => 1,
    	"www.thetoughtackle.com" => 1,
            "www.uktech.news" => 1,
            "newsconcerns.com" => 1,
    	"persiadigest.com" => 1,
            "swiftheadline.com" => 1,
            "foxinterviewer.com" => 1,
            "www.gearrice.com" => 1,
            "itsubuntu.com" => 1,
            "vervetimes.com" => 1,
    	"www.marktechpost.com" => 1,
            "www.thebharatexpressnews.com" => 1,
            "www.socialpost.news" => 1,
            "newsnationusa.com" => 1,
            "todayuknews.com" => 1,
            "thenationroar.com" => 1,
            "www.techgamingreport.com" => 1,
            "lvhspiratepress.org" => 1,
            "dealmakerz.co.uk" => 1,
            "pro.europeana.eu" => 1,
            "it-online.co.za" => 1,
            "d1softballnews.com" => 1,
            "voonze.com" => 1,
            "hspiratepress.org" => 1,
            "www.newspatrolling.com" => 1,
            "www.marketscreener.com" => 1,
            "liverpoolstudentmedia.com" => 1,
            "nation.lk" => 1,
            "thenewstrace.com" => 1,
            "www.sporttechie.com" => 1,
            "securityboulevard.com" => 1,
            "worldtrademarkreview.com" => 1,
            "www.worldtrademarkreview.com" => 1,
            "www.perild.com" => 1,
    	"www.which.co.uk" => 1,
            "venturebeat.com" => 1,
            "www.zdnet.com" => 1,
            "zdnet.com" => 1,
            );
    
        return( exists($junksite{$site}) ? 1 : 0 );
    }
    

    Links/lib/.directory-listing-ok

    Links/tr-old-extract-mysql-to-html-cref-comments.pl

    #!/usr/bin/perl
    
    use utf8;
    use DBI;
    use File::Path qw(make_path);
    use URI;
    use HTML::TreeBuilder::XPath;
    use HTML::Entities qw(decode_entities);
    use URI::Escape qw(uri_unescape);
    use Config::Tiny;
    use Getopt::Long;
    
    use Data::Dumper qw(Dumper);
    
    use open qw(:std :encoding(UTF-8));
    
    use strict;
    use warnings;
    
    my ( $script ) = ( $0 =~ m|(?!.*/)(.*)\.[^\.]*$|);
    
    our %opt = (
        'config'  => '',
        'verbose' => 0,
        'help'    => 0,
        );
    
    GetOptions (\%opt, 'config=s', 'verbose+', 'help' );
    my $config = $opt{config};
    our $VERBOSE = $opt{verbose};
    
    if ($opt{help}) {
        &usage($script);
        exit(0);
    }
    
    if (! -f $config) {
        &usage($script);
        exit(1);
    } elsif (! -r $config) {
        die("Configuration file '$config' is not readable\n");
    }
    my $configuration = Config::Tiny->read($config)
        or die("Could not read configurationn file '$config': $!\n");
    
    my $documentroot = $configuration->{database}->{documentroot}
        or die(" missing from configuration file\n");
    my $subdirectory = $configuration->{database}->{subdirectory}
        or die(" missing from configuration file\n");
    my $database = $configuration->{database}->{database}
        or die(" missing from configuration file\n");
    my $username = $configuration->{database}->{username}
        or die(" missing from configuration file\n");
    my $password = $configuration->{database}->{password}
        or die(" missing from configuration file\n");
    
    if ($VERBOSE) {
        print "DR: $documentroot\n";
        print "SD: $subdirectory\n";
        print "DB: $database\n";
        print "U:  $username\n";
        if ($VERBOSE > 2) {
    	print "P:  $password\n";
        }
    }
    
    my $dsn = "DBI:mysql:$database";
    
    # connect to MySQL database
    my %attr = ( PrintError=>0,	# turn off error reporting via warn()
                 RaiseError=>1);	# turn on error reporting via die()           
    our $dbh  = DBI->connect($dsn,$username,$password, \%attr)
        or die("Could not connect to $dsn using $username and the given password:$!\n");
    
    # ####
    
    # find base comments
    my $query = qq(SELECT comment_ID FROM wp_comments WHERE comment_parent = 0);
    my $sth = $dbh->prepare($query);
    $sth->execute;
    
    my %posts     = ();
    my %comments  = ();
    my %hierarchy = ();
    
    # build hashes of comments and comment hierarchies
    while(my $row = $sth->fetchrow_hashref) {
        &sql_for_comments($row, \%posts, \%comments, \%hierarchy);
    }
    
    # ####
    
    # build hashes of previous/next navigation links
    $query = qq(SELECT ID, post_date, post_name,post_title FROM wp_posts 
       	    	      WHERE post_type="post" AND post_status="publish" 
    		      ORDER BY post_date, ID);
    $sth = $dbh->prepare($query);
    $sth->execute();
    
    our %prev = ();
    our %next= ();
    my $old = 0;
    my $previousl = 0;
    my $previoust = 0;
    my $l = '';
    my $t = '';
    my $oldl = '';
    my $oldt = '';
    while(my $row = $sth->fetchrow_hashref) {
        my $id = $row->{ID};
        my $d = $row->{post_date};
        my $n = $row->{post_name};
        $t = $row->{post_title};
        $d =~ s/ .*$//g;
        $d =~ s|-|/|g;
        $l = "$subdirectory/".$d.'/'.$n.'/';
        print qq($id\t$t\n) if ($VERBOSE > 2);
        if ($old) {
    	$next{$old}->{url} = $l;
    	$next{$old}->{title} = $t;
        }
        if ($previousl) {
            $prev{$old}->{url} = $previousl;
    	$prev{$old}->{title} = $previoust;
        }
        $old = $id;
        $previoust = $oldt;
        $oldt = $t;
        $previousl = $oldl;
        $oldl = $l;
        # print Dumper($row),"\n";
    }
    $next{$old}->{url} = $l;
    $next{$old}->{title} = $t;
    $prev{$old}->{url} = $previousl;
    $prev{$old}->{title} = $previoust;
    
    
    undef($old);
    undef($l);
    undef($t);
    undef($previousl);
    undef($oldl);
    undef($previoust);
    undef($oldt);
    
    # ####
    # convert posts to HTML
    $query = qq(SELECT *, wp_posts.ID as rn FROM wp_posts LEFT JOIN wp_users ON wp_posts.post_author = wp_users.ID
        	       WHERE post_type="post" AND post_status="publish" ORDER BY post_date, wp_posts.ID);
    $sth = $dbh->prepare($query);
    $sth->execute();
    
    while(my $row = $sth->fetchrow_hashref) {
        # print Dumper($row),"\n";
        &sql_to_html($row);
    }       
    
    $sth->finish();
    $dbh->disconnect();
    
    exit(0);
    
    
    sub usage {
        my ($script) = (@_);
    
        print <{rn}\n) if ($VERBOSE);
        my ($path, $html) = &create_html($r);
        my $fullpath = $documentroot . "$subdirectory" . $path;
        print "FULLPATH= $fullpath\n" if ($VERBOSE);
    
        if ( ! -e $fullpath ) {
    	make_path($fullpath,{mode=>0775})
                or die("Could not create path '$fullpath' : $!\n");
            print "Created directory '$fullpath'\n" if ($VERBOSE);
        } elsif ( ! -d $fullpath ) {
    	die("Not a directory: '$fullpath'\n");
        } elsif ( ! -w $fullpath ) {
            die("Not writable: '$fullpath'\n");
        }
        my $file = $fullpath.'index.shtml';
        open(my $post, '>', $file)
    	or die("Could not open '$file': $!\n");
        print $post $html;
        close($post);
        
        return(1);
    }
    
    sub create_html {
        my ($r) = (@_);
    
        # /2022/05/20/kapow-1-6-0-released/
        my $rn = $r->{rn};
        my $post_name = $r->{post_name};
        print "RN= $rn\n $post_name\n" if ($VERBOSE);
        $post_name = uri_unescape($post_name);
        my $path = $r->{post_date};
        $path =~ s/ .*//;
        $path =~ s|-|/|g;
        $path = '/'.$path . '/' . $post_name . '/';
    
        my $post_title = $r->{post_title};
        my $post_date_gmt = $r->{post_date_gmt};
        my $post_modified_gmt = $r->{post_modified_gmt};
        my $pm1 = qq(\n  \n);
        my $pm2 = '';
        if ($post_modified_gmt) {
    	$pm2 = qq(
  • Modified: $post_modified_gmt UTC
  • \n); } my $display_name = $r->{display_name}; my $post_excerpt = $r->{post_excerpt}; my $post_content = $r->{post_content}; $post_content =~ s|(\n\r?)(\n\r?)|$1
    $2
    \n|gm; if ($post_content =~ m/\[cref\s+\d+/m) { $post_content = &cref_masher($post_content); } # make navigation previous, next navigation links for body and header my $p = $prev{$rn}->{url} || 0; my $n = $next{$rn}->{url} || 0; my $pt = $prev{$rn}->{title} || 0; my $nt = $next{$rn}->{title} || 0; my $l = 0; my $ll = 0; if ($nt && $pt) { $l = qq( \n \n); $ll = qq( ← $pt\n | \n $nt →\n); } else { if ($nt) { $l = qq( \n); $ll = qq( $nt →\n); } elsif ($pt) { $l = qq( \n); $ll = qq( ← $pt\n); } else { die("ID: $rn\n"); } } my $c = &get_comments($rn, \%posts, \%comments, \%hierarchy); my $cmnt = ''; if ($c) { $cmnt = qq(
    \n

    Comments

    ) . decode_entities($c->as_XML_indented) . qq(\n
    \n); } # make actual HTML document my $html = < $post_title $pm1 $l

    $post_title

    • $display_name
      • $post_date_gmt UTC
      • $pm2
    $post_content
    $cmnt

    Recent Techrights' Posts

    EOHTML $html =~ s/\s+<\s+/\</gm; $html = &miserable_unicode_hack($html); return($path, $html); } sub cref_masher { my ($post_content) = (@_); my $query = qq(SELECT guid,post_title FROM wp_posts WHERE ID=?); my $sth = $dbh->prepare($query); while ($post_content =~ m/\[cref +(\d+) +([^\]]+)\]/ or $post_content =~ m/\[cref +(\d+)\s*\]/) { my $cref = $1; my $anchor = $2 || ''; my $title = ''; $sth->execute($cref); while(my $row = $sth->fetchrow_hashref) { my $url = URI->new($row->{guid}); my $path = $url->path; my $fragment = $url->fragment; my $link = "$subdirectory/".$path; if ( my $q = $url->query) { if ($q =~ m/p=([0-9]+)$/) { my $id = $1; my $query2 = qq(SELECT post_date,post_name,post_title FROM wp_posts WHERE ID=?); my $sth2 = $dbh->prepare($query2); $sth2->execute($id); if (my $row2 = $sth2->fetchrow_hashref) { if (! $anchor) { $anchor = $row2->{post_title}; } my $u = URI->new($row2->{guid}); my $d = $row2->{post_date}; $d =~ s/ .*$//g; $d =~ s|-|/|g; $link = "$subdirectory/".$d.'/'.$row2->{post_name}.'/'; } else { die; } } else { $link = '?'.$q; } } else { my $query2 = qq(SELECT post_date,post_name,post_title FROM wp_posts WHERE ID=?); my $sth2 = $dbh->prepare($query2); $sth2->execute($cref); if (my $row2 = $sth2->fetchrow_hashref) { if (! $title) { $title = ' : ' . $row2->{post_title}; } if (! $anchor) { $anchor = $row2->{post_title}; } my $u = URI->new($row2->{guid}); my $d = $row2->{post_date}; $d =~ s/ .*$//g; $d =~ s|-|/|g; $link = "$subdirectory/".$d.'/'.$row2->{post_name}.'/'; } else { die; } } if (my $fragment = $url->fragment) { $link = '#'.$fragment; } $link = qq($anchor); $post_content =~ s/\[cref +$cref[^\]]*\]/$link/em; } } $sth->finish(); return($post_content); } sub miserable_unicode_hack { my ($post) = (@_); $post =~ s/é/é/gm; $post =~ s/ê/ê/gm; $post =~ s/î/î/gm; $post =~ s/“/“/gm; # smart open quote $post =~ s/”/”/gm; # smart close quote $post =~ s/“/“/gm; # smart open quote $post =~ s/”/”/gm; # smart close quote $post =~ s/’/’/gm; # smart close single quote $post =~ s/‘/‘/gm; # smart open single quote $post =~ s/—/—/gm; # mdsah $post =~ s/–/–/gm; # ndash $post =~ s/•/●/gm; # list bullet $post =~ s/â–ˆ/⬆/gm; # fat up arrow $post =~ s/£/£/gm; # gbp $post =~ s/©/®/gm; # registered trademark return($post); } sub get_comments { my ($p, $posts, $comments, $hierarchy) = (@_); my $xhtml = HTML::TreeBuilder::XPath->new; $xhtml->implicit_tags(1); $xhtml->no_space_compacting(0); my $ul = HTML::Element->new('ul'); my $count = 0; foreach my $k (@{$posts{$p}}) { print $k,"\n" if ($VERBOSE); my $li = HTML::Element->new('li'); $li->attr('id', "comment$k"); my $p1 = HTML::Element->new('p'); $p1->attr('class','author'); $p1->push_content($comments{$k}->{comment_author} ); $li->push_content($p1); my $p2 = HTML::Element->new('p'); $p2->attr('class','date'); $p2->push_content($comments{$k}->{comment_date_gmt}); $li->push_content($p2); my $div = HTML::Element->new('div'); $div->attr('class','words'); $div->push_content($comments{$k}->{comment_content}); $li->push_content($div); $ul->push_content($li); $count++; my $html = &render(0, $k, $comments, $hierarchy); if ($html) { $ul->push_content($html); } } if ($count) { return($ul); } else { return(0); } } sub render { my ($layer, $k, $comments, $hierarchy) = (@_); my $comment = $hierarchy{$k}; if (!defined($comment)){ return(0); } $layer++; my $ul = HTML::Element->new('ul'); my $count = 0; foreach my $c (@{$comment}) { my $li = HTML::Element->new('li'); $li->attr('id', "comment$c"); my $p1 = HTML::Element->new('p'); $p1->attr('class','author'); $p1->push_content($comments{$c}->{comment_author} ); $li->push_content($p1); my $p2 = HTML::Element->new('p'); $p2->attr('class','date'); $p2->push_content($comments{$c}->{comment_date_gmt}); $li->push_content($p2); my $div = HTML::Element->new('div'); $div->attr('class','words'); $div->push_content($comments{$c}->{comment_content}); $li->push_content($div); $ul->push_content($li); print "."x$layer,$c,"\n" if ($VERBOSE); my $html = &render($layer, $c, $comments, $hierarchy); if ($html) { $ul->push_content($html); $count++; } } return($ul); } sub sql_for_comments { my ($r, $posts, $comments, $hierarchy) = (@_); my $id = $r->{comment_ID}; # comment_ID comment_post_ID comment_author comment_author_email comment_author_url # comment_author_IP comment_date comment_date_gmt comment_content comment_karma # comment_approved comment_agent comment_type comment_parent # user_id comment_subscribe return if (! $id); my $query = qq( with recursive cte (comment_ID, comment_post_ID, comment_author, comment_parent, comment_date_gmt, comment_type, comment_content) as ( select comment_ID, comment_post_ID, comment_author, comment_parent, comment_date_gmt, comment_type, comment_content from wp_comments where comment_ID = ? AND comment_approved = 1 union all select p.comment_ID, p.comment_post_ID, p.comment_author, p.comment_parent, p.comment_date_gmt, p.comment_type, p.comment_content from wp_comments p inner join cte on p.comment_parent = cte.comment_ID ) SELECT * FROM cte ORDER BY comment_date_gmt; ); my $sth = $dbh->prepare($query); $sth->execute($id); while(my $row = $sth->fetchrow_hashref) { my $cid = $row->{comment_ID}; my $parent_id = $row->{comment_parent}; my $post_id = $row->{comment_post_ID}; if ($parent_id eq 0) { push(@{$posts{$post_id}}, $cid); } $comments{$cid}->{comment_post_ID} = $row->{comment_post_ID}; $comments{$cid}->{comment_parent} = $row->{comment_parent}; $comments{$cid}->{comment_author} = $row->{comment_author}; $comments{$cid}->{comment_date_gmt} = $row->{comment_date_gmt}; my $content = $row->{comment_content}; $content =~ s|(\s*)\n(\s*)\n|$1
    \n$2
    \n|gm; $comments{$cid}->{comment_content} = $content; push (@{$hierarchy{$parent_id}}, $cid); } $sth->finish(); return(1); }

    Links/dedupe-filtered.sh

    ./links-multi-file-link-deduplicator.pl  --input  ~/rss-tools/filtered.html  ~/Desktop/Text_Workspace/all-db.txt > ~/rss-tools/filtered-deduped.html
    

    Links/finalise-feedlist.sh

    #!/bin/sh
    #Licence: Public Domain, feel free to share as you see fit
    #
    #Author: Roy Schestowitz
    
    sort_feedlist() {
            SEARHFTERM=$1
            echo >> ~/rss-tools/RSS3.html
            echo "          ====================================== Input string: $1" \
                >> ~/rss-tools/RSS3.html
            echo "          
  • $1

      " >> ~/rss-tools/RSS3.html echo >> ~/rss-tools/RSS3.html awk 'tolower($0) ~ /'$SEARHFTERM'/' RS= RSS-cut.html \ >> RSS3.html } echo '' > RSS3.html # empty the file for w in 'tiktok' 'bytedance' 'smartphone' 'suicide' \ 'corona' 'covid' 'pandemic' 'lockdown' 'booster' \ 'fossforce' 'podcast' 'episode' 'mp3' 'soundcloud' 'upiter.zone' \ 'putin' 'wagner' 'ukrai' 'russia' 'kyiv' 'crimea' 'kherson' \ 'belaru' 'moscow' \ 'copyright' 'trademark' 'tradesec' 'Godot' \ 'documentfoundation' 'LibreOffice' 'opendocument' 'openoffice' \ 'idroot' 'linuxcapa' 'howtofor' 'how-to' 'howto' 'linuxhint' \ 'gemini' 'gemtext' 'geminispa' 'openssl' 'libressl' 'torrent' 'eff.org' \ 'opensource' 'youtube' 'invidious' \ 'linux' 'gnu' 'tecadmin' 'ubuntu' 'canonical' \ 'creativecommons' 'openrightsgroup' 'gsoc' 'tedium' \ 'baronhk' 'bkhome' 'easyos' 'netflix' 'drm' 'android' \ 'spyware' 'apache' 'malware' 'accessnow' 'strike' 'privacy' \ 'osmc' 'surveillance' 'IPv4' 'IPv6' 'cloudnativenow' \ 'rhel' 'coreos' 'centos' 'fedora' 'redhat' 'apnic' 'tortur' \ 'mwl.io' 'ruby' 'laravel' 'golang' 'bailout' 'medevel' \ 'bsd' 'scripting' 'programming' 'java' 'debug' 'open-sour' \ 'coding' 'emacs' 'compiler' 'rakudoweekly' 'vulkan' 'clang' \ 'ultimateedition' 'banking' 'banks' \ 'patent' 'epo.org' 'kluwer' 'craigmurray' 'Istio' \ 'techrights' 'gnome' 'Gedit' 'noyb' 'libeeboot' 'coreboot' \ 'speech' 'censor' 'suse' 'mozil' 'firefox' 'gaming' 'ESP32' \ 'steam' 'wordpress.org' 'bash' 'python' 'two-wrong' \ 'sans.edu' 'photo' 'revoy' 'commondream' 'kdenlive' \ 'schne' 'sches' 'gimp' 'server' 'cnx-software.com' 'GitLab'\ 'postgresql' 'apple' 'microsoft' 'google' 'istleblow' \ 'wikileaks' 'assange' 'chrom' 'slackwa' 'twitter' \ 'facebook' 'debian' 'kde' 'ardui' 'raspb' 'phoronix' \ 'publicdomainreview' 'security' 'amd' 'aws' 'intel' \ 'internet' 'perl' 'rubene' 'qt.io' 'libel' 'thenewstack' \ 'infla' 'hackaday' 'meduza' 'techdi' 'itsfoss' \ 'china' 'malays' 'korea' 'health' 'science' \ 'sport' 'game' 'climate' 'energy' 'player' 'tennis' \ 'athlete' 'score' 'baseball' 'football' 'germa' 'syria' \ 'drone' 'saudi' 'mexic' 'turkey' 'canada' 'africa' \ 'france' 'ncaa' 'twincities' 'sox' 'cubs' 'yankee' \ 'basketball' 'golf' 'singapo' 'japan' \ 'iran' 'afghan' 'drought' 'wildfire' 'lgb' 'trump' \ 'biden' 'funding' 'cloud' 'finland' 'sweden' 'refug' \ 'migra' 'pakist' 'india' 'americ' 'greece' 'itali' \ 'italy' 'denmark' 'tibet' 'taiwan' 'nigeria' 'egypt' \ 'congo' do sort_feedlist ${w} done echo ' ====================================== THE REST' >> RSS3.html cat RSS-cut.html >> RSS3.html awk '!seen[$0]++ { sub(/█████ http/, "\n\n\n\n█████ http"); sub(/======================================/, " \n\n\n\n\n\n\n\n ████████████████ SECTION"); print $0; } ' RSS3.html \ > RSS-final.html exit 0
  • Links/combine-rss-sources.sh

    sed -z  -e 's/\n                
    \n /
    /g' \ -e 's/
  • \n
    \n <\/li>/<\/blockquote><\/li>/g' \ ~/Desktop/Text_Workspace/links.html >> ~/rss-tools/RSS-cut.html cat ~/rss-tools/RSS-final.html >> ~/rss-tools/RSS-cut.html ./finalise-feedlist.sh
  • Links/.directory-listing-ok

    Links/rrrrrr-de-duplicate.pl

    #!/usr/bin/perl
    
    # 2023-03-04
    # scan files for links, and skip nodes with duplicate links
    #
    
    use utf8;
    use Getopt::Long;
    use File::Glob ':bsd_glob';
    use HTML::TreeBuilder::XPath;
    use File::Temp qw(tempfile tempdir);
    use File::Copy qw(move);
    use Cwd qw(abs_path);
    use open qw(:std :utf8);
    use English;
    
    use warnings;
    use strict;
    
    our %opt = (
        'h' => 0,
        'v' => 0,
        'w' => 0,
        );
    
    GetOptions ("help|h" => \$opt{'h'},
    	    "write|w" => \$opt{'w'},
    	    "verbose|v"  => \$opt{'v'});
    
    &usage if ($opt{'h'});
    
    my @filenames;
    while (my $file = shift) {
        my @files = bsd_glob($file);
        foreach my $f (@files) {
            # absolute path needed to identify unique file names later
            push(@filenames, abs_path($f));
        }
    }
    
    &usage if($#filenames < 1);
    
    if ($opt{'v'}) {
        print "F = ", join("\n", @filenames),qq(\n);
    }
    
    my %oldlinks;
    
    my $newfile = shift(@filenames);
    
    # deduplicate file names
    @filenames = grep(!/$newfile$/, @filenames);
    
    while (my $infile = shift(@filenames)) {
        next if ($infile eq $newfile);
        next if ($infile=~/~$/);
        %oldlinks = &oldfiles($infile, %oldlinks);
    }
    
    my $result = &readnewfile($newfile, %oldlinks);
    
    # trim probable trackers
    # see also http://jkorpela.fi/chars/spaces.html
    # $result =~ s/\p{Whitespace}/ /gm;        #
    # $result =~ s/[\x{00AD}]//gm;        #
    # $result =~ s/[\x{200B}]//gm;        #
    # $result =~ s/[\x{2060}]//gm;        #
    
    if($opt{'w'}) {
        my ($fh, $filename) = tempfile();
    
        print $fh $result;
    
        close($fh);
    
        rename($newfile,"$newfile.old")
            or die("$!\n");
    
        move($filename, $newfile)
            or die("$!\n");
    } else {
        print $result;
    }
    
    exit(0);
    
    sub usage {
        $0 =~ s/^.*\///;
        print qq($0: new_file old_file [oldfile...]\n);
    
        print qq(Check links in a file for possible duplicates in other files.\n);
        print qq(Send output to stdout by default.\n);
        print qq( -v increase debugging verbosity.\n);
        print qq( -w overwrite the original first file after comparison.\n);
        print qq( -h print this message.\n);
    
        exit(1);
    }
    
    sub oldfiles {
        my ($file, %newlinks) = ( @_ );
    
        my $xhtml = HTML::TreeBuilder::XPath->new;
        $xhtml->implicit_tags(1);
    
        # force input to be read in as UTF-8
        my $filehandle;
        open ($filehandle, "<", $file)
            or die("Could not open file '$file' : error: $!\n");
    
        # parse UTF-8
        $xhtml->parse_file($filehandle)
            or die("Could not parse file handle for '$file' : $!\n");
    
        for my $link ($xhtml->findnodes('//a')) {
            my $href = $link->attr('href');
            next unless($href);
            next if($href=~/^#/);
            $newlinks{$href}++;
        }
    
        $xhtml->delete;
    
        return(%newlinks);
    }
    
    sub readnewfile {
        my ($file, %oldlinks)= (@_);
    
        my $xhtml = HTML::TreeBuilder::XPath->new;
        $xhtml->implicit_tags(1);
    
        # force input to be read in as UTF-8
        my $filehandle;
        open ($filehandle, "<", $file)
            or die("Could not open file '$file' : error: $!\n");
    
        # parse UTF-8
        $xhtml->parse_file($filehandle)
            or die("Could not parse file handle for '$file' : $!\n");
    
        for my $li ($xhtml->findnodes('//li[a[@href]]')) {
    	for my $anchor ($li->findnodes('./a[@href]')) {
    	    my $href = $anchor->attr('href');
    	    next unless($href);
    	    if ($oldlinks{$href}++) {
    		$li->delete;
    	    }
    	}
        }
    
        # get rid of repeated 
    elements for my $node ($xhtml->findnodes('//body/hr[preceding-sibling::hr]')) { # print STDERR "hr removed\n"; $node->delete; } my $result = $xhtml->as_XML_indented || 0; $xhtml->delete; return ($result); }

    Links/tr-rss-since-scraper.pl

    #!/usr/bin/perl -T
    
    # 2021-05-16
    # XML RSS and Atom feed web scraper,
    # feed it URLs for feeds plus a date-time stamp
    # entries will be parsed and can saved in a file
    # local times will be converted to UTC
    
    use utf8;
    use Getopt::Long;
    use Time::ParseDate;
    use Time::Piece;
    use XML::Feed;
    use URI;
    use LWP::UserAgent;
    use HTTP::Response::Encoding;
    use HTML::TreeBuilder::XPath;
    use HTML::Entities;
    use English;
    
    use strict;
    use warnings;
    
    our $VERBOSE = 0;
    $OUTPUT_AUTOFLUSH=1;
    
    # work-arounds for 'wide character' error from wrong UTF8
    binmode(STDIN,  ":encoding(utf8)");
    binmode(STDOUT, ":encoding(utf8)");
    
    our %opt = ('a' => 0,
    	    'd' => 0,
    	    'h' => 0,
    	    'o' => 0,
    	    't' => 0,
    	    'u' => 0,
    	    'v' => 0,
    	    'L' => 0, );
    
    GetOptions ("append|a"   => \$opt{'a'},
                "date|d=s"   => \$opt{'d'},
                "help"       => \$opt{'h'},
                "output=s"   => \$opt{'o'},
                "title"      => \$opt{'t'},
                "utc"        => \$opt{'u'},
                "verbose+"   => \$opt{'v'},
                "list"       => \$opt{'L'},
        );
    
    my $script = $0;
    
    if ($opt{'h'}) {
        &usage($script);
    }
    
    if ($opt{'v'}) {
        $VERBOSE = $opt{'v'};
    }
    
    my ($output);
    if ($opt{'o'}) {
        # XXX needs proper sanity checking for path and filename at least
        $output = $opt{'o'};
        $output =~ s/[\0-\x1f]//g;
        if ($output =~ /^([-\/\w\.]+)$/) {
            $output = $1;
        } else {
            die("Bad path or file name: '$output'\n");
        }
    } else {
        $output = '/dev/stdout';
    }
    
    my $utc = 0;	# treat date input as a local time by default
    if ($opt{'u'}) {
        $utc = 1;   # treat date input as UTC without conversion
    }
    
    my $sdts;
    if ($opt{'d'}) {
        $sdts = parsedate($opt{'d'}, GMT=>$utc)
    	or die("Invalid date\n");
    } else {
        $sdts = parsedate('yesterday');
    }
    
    print STDERR qq(S=$sdts\n) if ($VERBOSE >1);
    
    my $t = Time::Piece->strptime($sdts, '%s');
    
    print STDERR qq(D=),$t->strftime("%a, %d %b %Y %H:%M:%S %Z"),qq(\n)
        if ($VERBOSE);
    
    my $count = 0;
    my $errors = 0;
    
    while (my $url = shift) {
        next if ($url =~ /^\s*#/u);        # skip comments
    
        print STDERR qq(\nU=$url\n)
            if ($VERBOSE);
        my $r = &get_feed($t,$url,$output);
    
        if ($r) {
            $count++;
        } else {
    	$errors++;
            print STDERR qq(Could not find feed at URL: "$url"\n);
        }
    }
    
    &usage($script) unless ($count || $errors);
    
    exit(0);
    
    sub usage {
        my ($script) = (@_);
        $script =~ s/^.*\///;
    
        print < elements but leave the others.
     -h shows this message.
     Multiple feed URLs can be specified.
     Queries and fragments are trimmed from the URIs.
     Broken or malformed feeds will be skipped completely.
    
    EXAMPLES:
    
     $script -u -d 2019-08-01T00:00 http://example.com/ https://example.org/
    
     $script -o /tmp/foo.html http://example.com/
    
     $script -a -o /tmp/foo.html -d 2019-08-01 https://example.com/
    
     The date for the -d option can be made using command substitution
     and the date(1) utility.
    
     $script -d \$(date -d '2 days ago' +'%Y-%m-%d') https://example.com/
    
    KNOWN BUGS:
    
     As a work-around for UTF-8 in Chromium and Firefox, meta elements
     declaring UTF-8 explicitly are peppered through the output.  The
     placement cannot really be helped and the result is  not valid XHTML
     because these are in the wrong part of the document.
    
     And it goes without saying that scraping sites is very brittle and
     can stop working with even minor changes to the page structure.
    
    EOH
    
        exit(0);
    }
    
    sub get_feed {
        my ($t,$url,$output) = (@_);
    
        my $uri = $url;
    
        my $feed;
    
        eval {
            $feed = XML::Feed->parse(URI->new($uri));
        };
    
        if ($@) {
    	print STDERR $@,qq(\n);
            print STDERR qq(  Failed feed for '$uri'\n);
            return(0);
        } elsif (! defined($feed)) {
    	return(0);
        }
    
        my $feed_title;
    
        eval {
            $feed_title = $feed->title;
        };
    
        if ($@) {
    	print STDERR $@,qq(\n);
    	print STDERR qq(  Failed title for '$uri'\n);
            return(0);
        }
    
        my $feed_modified = encode_entities($feed->modified); # unsupported
        my $feed_format   = encode_entities($feed->format);
    
        print STDERR qq(\tT=$feed_title\n)
            if ($VERBOSE);
        print STDERR qq(\tF=$feed_format\n)
            if ($VERBOSE);
    
        my @entries = ();
        if ($feed->link =~ m|https?://cybershow.uk|) {
    	@entries = &read_feed_instead($t,$feed,$output);
        } else {
    	@entries = &read_entries($t,$feed,$output);
        }
    
        if(@entries) {
    	my $mode;
    	if ($opt{'a'}) {
    	    $mode = '>>';
    	} else {
    	    $mode = '>';
    	}
    
    	# print STDERR Dumper($feed);
    	open(my $out, $mode, $output)
    	    or die("Could not open '$output' for appending: $!\n");
    
    	# work-around for browser not recognizing UTF-8 automatically
    	# print $out qq(\n);
    
    	binmode($out, ":encoding(utf8)");
    
    	if ($opt{'t'}) {
    	    print $out qq(

    $feed_title

    \n); } print $out join("", @entries); close($out); } return(1); } sub read_entries { my ($t,$feed,$output) = (@_); $t = parsedate($t); my @entries = (); my $count = 0; foreach my $entry ($feed->entries) { # print STDERR Dumper($entry),qq(\n\n) # if($VERBOSE); # entry time my $ft = $entry->{entry}{pubDate} || $entry->issued || $entry->modified; # entry time in seconds my $et = parsedate($ft) || 0; next unless($et =~ /^\d+$/ && $et >= $t ); # these links are sometimes redirections from proxies my ($base, $content) = &fetch_page($entry->link) or die("Missing content from '",$entry->link,"'\n"); next if ($base eq -1 || $content eq -1); next if ($base =~ /^\d+/ && $base<0); print STDERR qq(Fetched:),substr($base,0,30),qq(\n) if ($VERBOSE); my $uri = URI->new($base) or die("Bad address, '$base', could not form URI\n"); $uri->query(undef); $uri->fragment(undef); my $site = $uri->authority; # many sites are under feedburner if ($site eq 'feeds.feedburner.com') { if ($VERBOSE) { print STDERR qq(A=Feed Burner\n); } if($uri->path =~ /^projectcensored/) { $site = 'www.projectcensored.org'; } elsif($uri->path =~ /^johnpilger/) { $site = 'johnpilger.com'; } elsif($uri->path =~ /^cubexyz.blogspot.com/) { $site = 'cubexyz.blogspot.com'; } elsif($uri->path =~ /^LnuxTech-lb/) { $site = 'linuxtechlab.com'; } elsif($uri->path =~ /^www.privateinternetaccess.com/) { $site = 'www.privateinternetaccess.com'; } elsif($uri->path =~ /^original.antiwar.com/) { $site = 'original.antiwar.com'; } elsif($uri->path =~ /^\~r\/MichaelGeistsBlog/) { $site = 'www.michaelgeist.ca'; } elsif($uri->path =~ /^EliveLinuxWebsiteUpdates/) { $site = 'www.elivecd.org'; } elsif($uri->path =~ /^www.tecmint.com/) { $site = 'www.tecmint.com'; } } print STDERR qq(A=$site\n) if ($VERBOSE); # remove spammy, paid-for press releases if ($site eq 'www.commondreams.org') { # LLL - todo } &scan_for_scripts($site, $content); my $o = &choose_parser($site, $uri->canonical, $content); if ($o) { $count++; push(@entries, $o); } else { # identify the feed which had the error print STDERR qq(\t),$feed->title,qq(\n); } print STDERR qq(\t\t),$base,qq(\n) if ($VERBOSE); } if ($count) { push(@entries, qq(\n
    \n\n)); } return(@entries); } sub fetch_page { my ($uri) = (@_); my $ua = LWP::UserAgent->new; $ua->agent("NotRSS0day/0.1"); my $request = HTTP::Request->new(GET => $uri); my $result = $ua->request($request); if ($result->is_success) { return($result->base, $result->decoded_content); } else { warn("Could not open '$uri' : ", $result->status_line, "\n"); return(-1,-1); } return(0,0); } sub scan_for_scripts { my ($site, $content) = (@_); my $ent = HTML::TreeBuilder::XPath->new_from_content($content); for my $t ($ent->findnodes('script')) { print STDERR qq(script payload found in $site !\n); exit(2); } $ent->delete; return(1); } sub choose_parser { my ($site, $url, $content) = (@_); my ($xpath_title, $xpath_description) = (0,0); my ($title, $description) = (0,0); print STDERR qq(S=$site\n) if ($VERBOSE); my $ent = HTML::TreeBuilder::XPath->new_from_content($content); if ($site eq '9to5linux.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.aclu.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div/div[@class="panel-pane pane-aclu-components-description description"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'anniemachon.ch') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'original.antiwar.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Antiwar.com Original//u; $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'ar.al') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//body/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'archlinux.org') { $xpath_title = '//h2[@itemprop="headline"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="article-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'blog.arduino.cc') { $xpath_title = '//div[@class="post"]/h3[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'blog.benjojo.co.uk') { $xpath_title = '//head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h1/following-sibling::p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.bunniestudios.com') { $xpath_title = '//h2[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h2/following-sibling::div[1]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'kb.cert.org') { $xpath_title = '//div/div/div/div[@class="large-12 columns"]/h2'; $title = parse_title($ent, $xpath_title); $xpath_description = '//head/meta[@name="Description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.commondreams.org') { return(0) if ($url =~/\/newswire\//); $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # $xpath_description = '//head/meta[@name="description"]'; $xpath_description = '//div[3]/div[@class="body-description"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.counterpunch.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+-\s+CounterPunch.org//u; # $xpath_description = '//div[@class="story-header-area"]/p[1]'; $xpath_description = '//div[@class="story-header-area"]/p[position()<3 and not(contains(text(),"Subscribers content"))]'; $description = parse_description($ent, $xpath_description); $description = 0 if($description =~ /We don't shake our/); unless($description) { $xpath_description = '//div[@class="post_content"]/p[position()<3 and not(contains(text(),"Subscribers content"))]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'couragefound.org') { $xpath_title = '//html/head/meta[@name="twitter:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'cpj.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # .col-sm-7 > article:nth-child(1) > p:nth-child(3) $xpath_description = '//div[@class="col-sm-7"]/p[1]'; $description = parse_description($ent, $xpath_description); $description =~ s/>[^>]*—/>/; } elsif ($site eq 'climatenewsnetwork.net') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Climate News Network//u; $xpath_description = '//div[@class="entry-content-post"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.craigmurray.org.uk') { $xpath_title = '//html/head/meta[@name="twitter:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h1/following-sibling::p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'creativecommons.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Creative Commons//u; $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); unless($description eq '

    ') { $xpath_description = '//div[@class="entry-content"]/p[2]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'cubexyz.blogspot.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@id="mainClm"]/div[@class="blogPost"]'; $description = parse_description($ent, $xpath_description); $description =~ s/\s+//u; # $description =~ s/\s\s+.*<\/blockquote>/<\/blockquote>/mu; } elsif ($site eq 'danielmiessler.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); # remove podcasts return(0) if ($title =~ m/Unsupervised Learning: No\./); $xpath_description = '//div[@class="entry-content"]/p[position()>=last()-1]'; $description = parse_description($ent, $xpath_description); # remove adverts for social control media # my $de = HTML::TreeBuilder::XPath->new_from_content($description); # for my $p ($de->findnodes('//p')) { # if($p->as_text =~ m/^Discuss on Tw/) { # $p->delete; # } # } # $description = $de->as_XML_compact; # $de->delete(); $description =~ s/^.*(
    )/$1/; $description =~ s/(<\/blockquote>).*$/$1/; } elsif ($site eq 'dataswamp.org') { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h1/following-sibling::p[position()>1 and position()<4]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.democracynow.org') { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); return(0) if ($title =~ m/recent shows/i); return(0) if ($title =~ m/^headlines/i); $xpath_description = '(//div[@class="headline_body"]/div[@class="headline_summary"]/p[1])[1]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '(//div[@class="text"]/p[1])[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'www.digitalmusicnews.com') { $xpath_title = '//html/head/title'; $title = parse_title($xpath_title, $content); $title = failed_utf($title); $xpath_description = '//div[@id="main"]//h2'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.desmog.com') { $xpath_title = '//div[@class="elementor-widget-container"]/h1'; $title = parse_title($ent, $xpath_title); # $xpath_description = '//div[@class="elementor-widget-container"]/div/p[position()<3]'; $xpath_description = '(//div[@class="elementor-widget-container"]/div/p)[position()<3]'; $description = parse_description($ent, $xpath_description); # xxx work-around to eliminate site signature :( $description =~ s/

    Website by.*//ms; } elsif ($site eq 'www.desmogblog.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="field-items"]/div[1]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'thedissenter.org') { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'dontextraditeassange.com') { $xpath_title = '//div[@class="entry-categories"]/following-sibling::h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()>1 and position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.dw.com') { $xpath_title = '//div[1]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[1]/h1[1]/following-sibling::p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.elivecd.org') { $xpath_title = '//h1[@class="post-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="post-content"]/h5[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.theenergymix.com') { # lll $xpath_title = '//h1[@class="jeg_post_title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="content-inner"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.eff.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # work-around for something broken with p[1] $xpath_description = '//div[@class="field__items"]/div[1]/p[position()>1 and position()<=4]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.exposedbycmd.org') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<=2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'fair.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # .entry-content > p:nth-child(4) $xpath_description = '//div[@class="entry-content"]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'femtejuli.se') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//html/head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'ferd.ca') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h2/following-sibling::p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'fortran-lang.org') { $xpath_title = '//div[@class="newsletter col-wide"]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="newsletter col-wide"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'fossforce.com') { $xpath_title = '//div//h1[@class="post-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="post-content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.fossmint.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.france24.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="t-content t-content--article"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.gamingonlinux.com') { $xpath_title = '//div/h1[@class="title p-name"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="content group e-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'godotengine.org') { # lll $xpath_title = '//div[@class="info"]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="info"]/following-sibling::p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'thegrayzone.com') { $xpath_title = '//h1[@class="entry-title" and 1]'; unless($title) { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); } $xpath_description = '//div[@class="entry-content"]/h3[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'greenparty.org.uk' or $site eq 'www.greenparty.org.uk') { # LLL fix this above with $et, does not currently get this far $xpath_title = '//div[@class="container"]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@id="news"]/div[position()<6]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'hackaday.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); # $xpath_description = '//html/head/meta[@property="og:description"]'; $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.hrw.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # $xpath_description = '//html/head/meta[@property="og:description"]'; $xpath_description = '//div[@class="article-body article-body--contained"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'infojustice.org') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="post-content entry-content"]/p[position()>1 and position()<4]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'insighthungary.444.hu' or $site eq '444.hu') { $xpath_title = '//div[@id="headline"]/h1'; $title = parse_title($ent, $xpath_title); $xpath_description = '//p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.itwire.com') { $xpath_title = '//h2[@class="itemTitle"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+Featured.*//u; # should have been in XPath instead $xpath_description = '//div[@class="itemIntroText"]/p'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'jacobinmag.com') { $xpath_title = '//body/h1[@class="po-hr-cn__title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h1/following-sibling::p[@class="po-hr-cn__dek"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'johnpilger.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title = &title_case($title); $xpath_description = '//div[@class="text book last full" and position()=1]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'krebsonsecurity.com') { $xpath_title = '//div/h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'kubernetes.io') { $xpath_title = '//div[@class="content"]/h1'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="td-content"]/p[position()>1 and position() < 5 and not(preceding-sibling::h2)]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.laquadrature.net') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content entry-content-single"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.lightbluetouchpaper.org') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<=2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.linuxandubuntu.com') { $xpath_title = '//div/h1[@class="alignwide wp-block-post-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[contains(@class, "entry-content")]/p[position() < 5 and not(preceding-sibling::h2)]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.linuxbuzz.com') { $xpath_title = '//div[@class="inside-article"]/h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.linuxcloudvps.com') { $xpath_title = '//h2[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//p[position()>1 and position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'linuxhandbook.com') { $xpath_title = '//div/h1[@class="hero__title text-center"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="content js-toc-content"]/p[1]'; $description = parse_description($ent, $xpath_description); # skip newsletters and such if(!$description) { return(0); } } elsif ($site eq 'www.linuxtechi.com') { $xpath_title = '//div/h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="nv-content-wrap entry-content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'linuxgizmos.com') { $xpath_title = '//div[@class="post"]/h2'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entrytext"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'linuxtechlab.com') { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="text"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'lunduke.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//html/head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'markcurtis.info') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Meduza//u; $xpath_description = '//div[@class="entry-content"]/p[position()>=3 and position()<=4]'; $description = parse_description($ent, $xpath_description); unless($description) { # some do not have the extra byline # but it is hard to parse which do: $xpath_description = '//div[@class="entry-content"]/p[position()>=2 and position()<=3]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'meduza.io') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Meduza//u; $xpath_description = '//div[@class="GeneralMaterial-article"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.michaelgeist.ca') { $xpath_title = '//h1[@class="title"]'; $title = parse_title($ent, $xpath_title); return(0) if($title=~/^The LawBytes Podcast/); $xpath_description = '//div[@class="entry"]/p[last()]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'michaelwest.com.au') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Michael West.*//u; $xpath_description = '//div[@class="et_pb_title_container"]/p[@class="et_pb_title_meta_container"]'; $description = parse_description($ent, $xpath_description); if ($description =~ m/\bAAP\b/) { return(0); } $xpath_description = '//div[@id="old-post"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.michaelwest.com.au') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Michael West.*//u; $xpath_description = '//head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.mintpressnews.com') { $xpath_title = '//head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'blog.mozilla.org') { $xpath_title = '//div[1]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="ft-c-single-post__body"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.thenation.com') { $xpath_title = '//div[@class="article-header-content"]/h1[@class="title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="article-body-inner"]/p[position()<3 and @class!="caption"]'; $description = parse_description($ent, $xpath_description); $description =~ s/[\d\s]*Ad Policy.*$//i; } elsif ($site eq 'newmatilda.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+New Matilda.*//u; $xpath_description = '//div/div[@class="post-content text-font description"]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'oceanservice.noaa.gov') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\W\s+Michael West.*//u; $xpath_description = '//head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'off-guardian.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//h6/following-sibling::p[@class="dropcap"]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//div[@class="transcript"]/p[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'papersplease.org') { $xpath_title = '//h1[@class="post-title entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<4]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'news.opensuse.org') { $xpath_title = '//h1[@class="decorated-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="col-md-7 col-12 mx-auto text-justify"]/p[position() <3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'opensource.com') { $xpath_title = '//h1[@class="published page-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@id="article_content"]//div[@class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"]/p[not(preceding-sibling::h2) and position() < 5]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'opensourcesecurity.io') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'ostechnix.com') { $xpath_title = '//div/h1[@class="post-title single-post-title entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="inner-post-entry entry-content"]/div/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.pclinuxos.com') { $xpath_title = '//div[@class="title"]/h2[1]'; $title = parse_title($ent, $xpath_title); $title =~ s/^\s+//u; $xpath_description = '//div[@class="entry"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'perens.com') { # header.entry-header h1.entry-title $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//div[@class="entry-content"]/descendant::p[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'perlweeklychallenge.org') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="post-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.projectcensored.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="inner-post-entry entry-content"]/p[2]'; $description = parse_description($ent, $xpath_description); if(!$description || $description =~ /Listen to all of our previous/) { $xpath_description = '//div[@id="penci-post-entry-inner"]/div/div/div[1]'; $description = parse_description($ent, $xpath_description); } if(!$description || $description =~ /Listen to all of our previous/) { $xpath_description = '//div[@id="penci-post-entry-inner"]/p[1]'; $description = parse_description($ent, $xpath_description); } if(!$description || $description =~ /Listen to all of our previous/) { $xpath_description = '//div[@id="penci-post-entry-inner"]/div/div[1]'; $description = parse_description($ent, $xpath_description); } if(!$description || $description =~ /Listen to all of our previous/) { $xpath_description = '//div[@id="penci-post-entry-inner"]/div[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'pluralistic.net') { 1; # placeholder } elsif ($site eq 'www.privateinternetaccess.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="detail-ct"]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'projects.propublica.org') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s*\|.*$//u; $xpath_description = '//html/head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'features.propublica.org') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//html/head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.propublica.org') { # $xpath_title = '//html/head/meta[@name="dcterms.Title"]'; $xpath_title = '//html/head/meta[@property="headline"]'; $title = parse_title($ent, $xpath_title); unless($title) { $xpath_title = '//h2[@class="hed"]'; $title = parse_title($ent, $xpath_title); } $xpath_description = '//div[@class="article-body"]/p[position()<=2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.openrightsgroup.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="sixteen columns"]/*/p[1]'; $description = parse_description($ent, $xpath_description); unless ($description) { $xpath_description = '//div[@class="sixteen columns"]/p[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'puri.sm') { $xpath_title = '//div[@class="container"]/h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="blog-entry e-content"]/p[not(preceding-sibling::h1) and position() < 4]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.qt.io') { $xpath_title = '//div[@class="h-wysiwyg-html/h1"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//span[@id="hs_cos_wrapper_post_body"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'rakudoweekly.blog') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.raspberrypi.org') { $xpath_title = '//h1[2]'; $title = parse_title($ent, $xpath_title); unless ($title) { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); } $xpath_description = '//html/head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//div[contains(@class,"c-post-content__wysiwyg")]/p[1]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'www.redhat.com') { $xpath_title = '//div[@class="rh-article-teaser--component"]/h1'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[starts-with(@class,"rh-generic")]//p[not(preceding-sibling::h3) and position() < 3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'respectfulinsolence.com' || $site eq 'www.respectfulinsolence.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'therevelator.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+.bull\;.*//u; $title =~ s/\s+•.*//u; $xpath_description = '(//div[@id="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.rferl.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@id="article-content"]/div[1]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'robertreich.org') { $xpath_title = '//div[@class="caption"]/h2/b'; $title = parse_title($ent, $xpath_title); if (!$title) { $xpath_title = '//li[@class="post"]/a/h2'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@class="caption"])/p[2]'; $description = parse_description($ent, $xpath_description); } else { $xpath_description = '(//div[@class="caption"])[last()]/p[last()]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'robert.ocallahan.org') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@class="post-body entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.rosehosting.com') { $xpath_title = '//div/h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '(//div[@class="entry-content"]/p[not(preceding-sibling::h3) and position() < 3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'shadowproof.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); # div.vw-post-content.clearfix p $xpath_description = '//div[@class="vw-post-content clearfix"]/p[position()<=2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'scheerpost.com') { $xpath_title = '//h1[contains(@class,"entry-title")]'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+-\s+CounterPunch.org//u; $xpath_description = '//head/meta[@property="og:description"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.spiegel.de') { $xpath_title = '//h2[@class="article-title lp-article-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div/h2/following-sibling::p[@class="article-intro"]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'digit.site36.net') { $xpath_title = '//h3[@class="wp-block-post-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="has-global-padding is-layout-constrained entry-content cat-links entry-meta tag-links entry-content edit-link page-links wp-block-post-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'blog.steve.fi') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()>=last()-1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'techcrunch.com') { $xpath_title = '//html/head/meta[@name="sailthru.title"]'; $title = parse_title($ent, $xpath_title); $title = failed_utf($title); $xpath_description = '//html/head/meta[@name="sailthru.description"]'; $description = parse_description($ent, $xpath_description); $description = failed_utf($description); $url =~ s/\?[^\?]*$//; } elsif ($site eq 'www.techdirt.com') { $xpath_title = '//h1[@class="posttitle"]'; $title = parse_title($ent, $xpath_title); # remove Daily Deals return (0) if ($title =~ m/^Daily Deal/); # remove Funniest return (0) if ($title =~ m/^Funniest/i); # skip recaps return(0) if ($title =~ m/^This Week In Techdirt History/i); $xpath_description = '//div[@class="byline"]/following-sibling::p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.tecmint.com') { $xpath_title = '//h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); # lll } elsif ($site eq 'www.technologyreview.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[1]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.tedunangst.com') { # http://www.tedunangst.com/flak/rss $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="byline"]/following-sibling::p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'threatpost.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="c-article__intro"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'telex.hu') { $xpath_title = '//div[1]/div[1]/h1'; $title = parse_title($ent, $xpath_title); # $xpath_description = '//div[@class="top-section"]/following-sibling::p[1]'; $xpath_description = '//div[@class="article-html-content"]/div/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'blog.torproject.org') { $xpath_title = '//h1[@class="title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="body"]/p[position()<3]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '(//p)[2]'; $description = parse_description($ent, $xpath_description); } } elsif ($site eq 'torrentfreak.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s[\-\*]\sTorrentFreak$//u; return (0) if ($title =~ /Most Torrented Movie of The Week/i); # '//div[@class="entry-summary"]/p[@class="entry-lead"]' $xpath_description = '//p[@class="article__excerpt"]'; $description = parse_description($ent, $xpath_description); $url =~ s/\?.*$//; } elsif ($site eq 'blog.trailofbits.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.truthdig.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); unless($title) { $xpath_title = '//html/head/meta[@name="twitter:title"]'; $title = parse_title($ent, $xpath_title); } $xpath_description = '//div[@class="article-item__content am2-content"]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'truthout.org') { $xpath_title = '//h1[1]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@id="article-content"]/p[1]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//p[@data-pp-id="1.0"]'; $description = parse_description($ent, $xpath_description); } # LLL - truthout's XHTML has multiple fatal validation errors # cannot be processed, yet } elsif ($site eq 'ubuntu.com') { $xpath_title = '//html/head/title'; $title = parse_title($ent, $xpath_title); $title =~ s/\s+\|.*$//u; $xpath_description = '//div[@class="p-post__content"]//p[not(preceding-sibling::h2) and position() < 3]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.ubuntubuzz.com') { $xpath_title = '//div[@class="title"]/h1'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry"]/p[2]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.unixmen.com') { $xpath_title = '//div/h1[@class="entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="td-post-content"]//p[not(preceding-sibling::h2) and position() < 4]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//div[@class="td-post-content"]/p[position()>2 and position()<5]'; $description = parse_description($xpath_description, $content); } } elsif ($site eq 'vitux.com') { $xpath_title = '//div[@class="post-title-wrapper"]/h1'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="entry-content clearfix"]/p[not(preceding-sibling::h2) and position() < 3]'; $description = parse_description($ent, $xpath_description); unless($description) { $xpath_description = '//div[@class="entry-content clearfix"]/p[1]'; $description = parse_description($xpath_description, $content); } unless($description) { $xpath_description = '//div[@class="entry-content clearfix"]/p[2]'; $description = parse_description($xpath_description, $content); } } elsif ($site eq 'yottadb.com') { $xpath_title = '//html/head/meta[@property="og:title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div/div[@class="col-sm-20" and position()=3]/p[1]'; $description = parse_description($ent, $xpath_description); } elsif ($site eq 'www.zenwalk.org') { $xpath_title = '//h3[@class="post-title entry-title"]'; $title = parse_title($ent, $xpath_title); $xpath_description = '//div[@class="post-body entry-content"]'; $description = parse_description($ent, $xpath_description); } else { # the site does not yet have XPaths, return with an error print STDERR qq(Site "$site" is not yet configured,); print STDERR qq(\tSee "$url"\n); $ent->delete; return(0); } # LLL - should print warning if no title or description is found if ( $description !~ /

    / ) { $description = "

    $description

    "; } $ent->delete; return( &print_item($title, $url, $description) ); } sub parse_title { my ($ent, $xpath_title) = (@_); my $title = 0; for my $t ($ent->findnodes($xpath_title)) { if($t->tag eq 'meta') { $title = $t->attr('content') || 0; } else { $title = $t->as_text || 0; } } $title =~ s/\x{A0}/ /mg; $title =~ s/\s+$//mu; $title =~ s/^\s+//mgu; $title = encode_entities($title); return($title); } sub parse_description { my ($ent, $xpath_description) = (@_); my $description = ''; for my $d ($ent->findnodes($xpath_description)) { if($d->tag eq 'meta') { my $desc = encode_entities($d->attr('content')); $description .= '

    '.$desc."

    \n" || 0; } elsif($d->tag eq 'p') { if($d->as_trimmed_text) { my $desc = encode_entities($d->as_trimmed_text); $description .= '

    '.$desc."

    \n"; } } else { $description .= encode_entities($d->as_trimmed_text).qq(\n); } } if ($description) { $description =~ s/>\s+/>/gmu; $description = qq(
    $description
    \n); } # delete hidden soft-hyphen and zero-width space trackers $description =~ s/[\x{A0}\x{00AD}\x{200B}]//mg; return($description); } sub failed_utf { my ($text) = (@_); # crude work-arounds for failed utf-8 / unicode # $text =~ s/’/'/g; $text =~ s/\x{2060}//g; return($text); } sub print_item { my ($title, $url, $description) = (@_); my $output; if(!$opt{'L'}) { $output .= qq(
  • ); } $output .= qq(
    $title
    \n); if($description) { $output .= qq($description); } else { $output .= qq(
    \n
    \n); } if(!$opt{'L'}) { $output .= qq(
  • \n\n); } return($output); } sub title_case { my ($title) = (@_); # based on Chapter 1.14.2, Perl Cookbook, 2nd ed. our %nocap; unless(keys %nocap) { foreach my $w (qw(a an the and but or as at but by for from in into of off on onto per to with)) { $nocap{$w}++; } } # put into lowercase if on stop list, else titlecase $title =~ s/(\pL[\pL']*)/$nocap{$1} ? lc($1) : ucfirst(lc($1))/ge; # last word guaranteed to cap $title =~ s/^(\pL[\pL']*) /\u\L$1/x; # first word guaranteed to cap $title =~ s/ (\pL[\pL']*)$/\u\L$1/x; # treat parenthesized portion as a complete title $title =~ s/\( (\pL[\pL']*) /(\u\L$1/x; $title =~ s/(\pL[\pL']*) \) /\u\L$1)/x; # capitalize first word following colon or semi-colon $title =~ s/ ( [:;] \s+ ) (\pL[\pL']* ) /$1\u\L$2/xu; return ($title); } sub read_feed_instead { my ($t,$feed,$output) = (@_); # use feed metadata instead of parsing fetched articles $t = parsedate($t); my @entries = (); my $count = 0; foreach my $entry ($feed->entries) { # print STDERR Dumper($entry),qq(\n\n) # if($VERBOSE); # entry time my $ft = $entry->{entry}{pubDate} || $entry->issued || $entry->modified; # entry time in seconds my $et = parsedate($ft) || 0; next unless($et =~ /^\d+$/ && $et >= $t ); my $title = $entry->title || 0; my $url = $entry->link || 0; my $description = $entry->{entry}{description} || 0; if ($description) { $description = "

    ". $description. "

    "; } my $o = &print_item($title, $url, $description); push(@entries, $o); } if ($count) { push(@entries, qq(\n
    \n\n)); } return(@entries); }

    Links/tr-links-check-spam-sites.pl

    #!/usr/bin/perl
    
    # 2021-08-20
    # find links and make sure they are not junk sites
    
    # use utf8;
    use Getopt::Std;
    use File::Glob ':bsd_glob';
    use HTML::TreeBuilder::XPath;
    use URI;
    use open qw(:std :utf8);
    use Term::ANSIColor qw(:constants);
    
    use lib "$ENV{HOME}/lib/";
    use Links::SpamSites qw(KnownSpamSite);
    
    use English;
    
    use warnings;
    use strict;
    
    our %opt;
    our %tags;
    
    getopts('h', \%opt);
    
    &usage if ($opt{'h'});
    
    my @filenames;
    while (my $file = shift) {
        my @files = bsd_glob($file);
        foreach my $f (@files) {
            push(@filenames, $f);
        }
    }
    
    &usage if($#filenames < 0);
    
    while (my $infile = shift(@filenames)) {
        next if ($infile=~/~$/);
        my $result = &interleave($infile);
    
        if(keys %tags) {
            print STDERR BRIGHT_RED ON_BLUE "Check these probably junk sites: \n ";
            # print join("\n ", @tags);
            foreach my $site (sort keys %tags) {
                print qq( $site\n);
            }
            print qq(\n);
            print STDERR RESET;
            print qq(\n);
            exit(1);
        }
    }
    
    exit(0);
    
    sub usage {
        print qq(Check URLs and verify that they are not junk sites.\n);
        $0 =~ s/^.*\///;
        print qq($0: new_file old_file [oldfile...]\n);
        exit(1);
    }
    
    sub interleave {
        my ($file)= (@_);
    
        my $xhtml = HTML::TreeBuilder::XPath->new;
        $xhtml->implicit_tags(1);
        $xhtml->parse_file($file)
            or die("Could not parse '$file' : $!\n");
    
        for my $node ($xhtml->findnodes('//li[h5]')) {
            for my $anchor ($node->findnodes('./h5/a[@href]')) {
                my $href = $anchor->attr('href');
                next unless($href);
    
                my $sitetag = sitetag($href);
    
                if($sitetag && SpamSites::KnownSpamSite($sitetag)) {
    		$tags{$sitetag}++;
                }
            }
        }
    
        $xhtml->delete;
        return (1);
    }
    
    sub sitetag {
        my ($href) = (@_);
    
        my $uri = URI->new($href);
        return(0) unless(defined $uri->scheme && $uri->scheme =~ /^http/);
        my $domain = $uri->host || 0;
    
        return($domain);
    }
    

    Links/finalise-daily-links.sh

    # Prepare and finalise Daily Links (News Roundup) for Techrights
    #
    # Licence: Public domain
    # Author: Roy Schestowitz
    # Date: 2018-2022
    
    # Bring tags up to date
    
    ~/sync-camelcase.sh
    
    # Remove empty bits
    
    sed 's/
  • <\/a><\/h5><\/li>/ /g' links-before.html > \ links-clean.html && perl ./links-cull-empty.pl links-clean.html | \ perl ./links-toc.pl > links-after.html # Add tags # cp links-after.html links-clean.html perl ~/Git/Links/links-interleave-social-control-media.pl \ links-after.html > links-clean.html # Invalid tags sed 's/\[\[\[\[\[0\]\]\]\]\] //g' links-clean.html > links-after.html # Trim the ends (WordPress post isn't a full page) head -n -1 links-after.html > links-clean.html tail -n +6 links-clean.html > links-after.html # Body is irrelevant to WordPress in this context sed 's// /g' links-after.html > links-clean.html sed 's/<\/body>/ /g' links-clean.html > links-after.html sed 's/
      <\/ul>/ /g' links-after.html > links-clean.html sed 's/<\/head>/ /g' links-clean.html > links-after.html # Make fancier site tags with basic style sed 's/\[\[\[\[\[//g' links-after.html > links-clean.html sed 's/\]\]\]\]\]/<\/em><\/b> ☛/g' links-clean.html > links-after.html # Open to present the output (editor of choice here is KDE's Kate) kate links-after.html # Run some sanity checks (common errors), leave them visible for # ~5 seconds, let it self-terminate after that echo "========== QUOTES (missing URL possible)" grep \"\" links-after.html echo "========== NO ANCHOR (probably missing title)" grep "><\/a" links-after.html echo "========== TM (tuxmachines.org URLs)" grep "tuxmachines" links-after.html # Alter the template to make unique IDs todaydate=`date '+%d\/%m\/%Y'` yesterdaydate=`date --date="yesterday" '+%d\/%m\/%Y'` sed "s/$yesterdaydate/$todaydate/" /home/roy/Desktop/Text_Workspace/template.html > /home/roy/Desktop/Text_Workspace/template_last.html sed 's/id=\"/id=\"_/g' /home/roy/Desktop/Text_Workspace/template_last.html \ > /home/roy/Desktop/Text_Workspace/template.html rm /home/roy/Desktop/Text_Workspace/template_last.html cat links-before.html >> /home/roy/Desktop/Text_Workspace/all-db.txt sleep 5
  • Links/daily.feeds

    # 2020-08-15
    # keep uptodate in Git!
    # todo: https://feeds.feedburner.com/NiemanJournalismLab
    
    https://cybershow.uk/feed.php
    
    # https://www.thenation.com/feed/?post_type=article
    https://www.greenparty.org.uk/news2.rss
    # ACLU seems blocked by Javascript and malformed feeds
    # https://www.aclu.org/taxonomy/feed-term/936/feed
    # https://www.aclu.org/taxonomy/feed-term/2152/feed
    # https://www.aclu.org/taxonomy/channel-term/1/feed
    # https://www.aclu.org/taxonomy/feed-term/8/feed
    # https://www.aclu.org/taxonomy/feed-term/362/feed
    # http://www.craigmurray.org.uk/rss
    http://fair.org/feed/
    http://www.laquadrature.net/en/rss.xml
    # http://www.openrightsgroup.org/feed
    http://shadowproof.com/feed
    https://creativecommons.org/blog/feed/
    # https://www.truthdig.com/feed/
    # https://www.commondreams.org/rss.xml
    # http://robertreich.org/rss
    # https://feeds.feedburner.com/MichaelGeistsBlog
    https://meduza.io/rss/en/all
    # https://www.eff.org/rss/updates.xml
    https://ar.al/index.xml
    # https://www.techdirt.com/techdirt_rss.xml
    https://www.propublica.org/feeds/54Ghome
    # https://anniemachon.ch/feed
    # https://fossforce.com/feed/
    # http://feeds.feedburner.com/projectcensored/gEpu
    # https://www.projectcensored.org/feed/		# captured by CAIR
    # http://feeds.feedburner.com/johnpilger
    https://www.desmogblog.com/rss.xml
    https://therevelator.org/feed/
    https://thegrayzone.com/feed
    # https://freeassange.org/feed/
    https://papersplease.org/wp/feed/
    # https://www.mintpressnews.com/feed/  # use sheer instead
    # https://scheerpost.com/feed/
    https://telex.hu/rss/archivum?filters=%7B%22flags%22%3A%5B%22english%22%5D%2C%22parentId%22%3A%5B%22null%22%5D%7D
    https://insighthungary.444.hu/feed
    
    # https://couragefound.org/feed 403 Forbidden
    # https://www.theenergymix.com/feed/	questionable
    # https://climatenewsnetwork.net/feed/  rebranded as TheEnergyMix
    # https://www.privateinternetaccess.com/blog/feed/  defunct feed
    # https://www.truth-out.org/feed?format=feed
    # https://newmatilda.com/feed/
    # https://www.technologyreview.com/stories.rss
    https://respectfulinsolence.com/feed/
    # https://danielmiessler.com/feed/
    https://digit.site36.net/feed/
    # https://www.itwire.com/journalist/sam-varghese.html?format=feed
    https://thedissenter.org/rss/
    
    https://torrentfreak.com/feed/
    # https://rakudoweekly.blog/feed/
    https://www.raspberrypi.org/feed/
    # http://perlsphere.net/atom.xml
    # https://perlweeklychallenge.org/rss.xml
    # http://lunduke.com/index.xml
    # https://www.democracynow.org/podcast.xml
    # https://www.democracynow.org/democracynow.rss
    https://blog.torproject.org/rss.xml
    https://krebsonsecurity.com/feed/
    
    https://fortran-lang.org/en/news/atom.xml
    https://hackaday.com/feed/
    
    
    # cover manually:
    
    # https://www.digitalmusicnews.com/feed/
    # https://9to5linux.com/feed/
    
    
    # avoid:
    
    # https://www.truthdig.com/articles/human-rights-watch-accepted-money-from-a-saudi-billionaire-it-investigated-for-worker-abuse/
    # https://www.hrw.org/rss/news
    # http://www.counterpunch.org/feed/
    

    Links/tr-links-toc.pl

    #!/usr/bin/perl
    
    # Parse a lean hierarchy and generate a table of contents with internal links
    
    use utf8;
    use Getopt::Long;
    use HTML::TreeBuilder::XPath;
    use HTML::Entities;
    use open qw(:std :utf8);
    
    use English;
    
    use warnings;
    use strict;
    
    our %opt = ( 'h' => 0, 'v' => 0, );
    
    GetOptions ('verbose+' => \$opt{'v'},
                'help|h'   => \$opt{'h'},
        );
    
    &usage if ($opt{'h'});
    
    # read directly from stdin or else get a list of file names
    push(@ARGV, '/dev/stdin') if ($#ARGV < 0);
    
    while (my $infile = shift) {
        &readthefile($infile, $opt{'w'});
    }
    
    exit(0);
    
    sub readthefile {
        my ($file) = (@_);
    
        my $xhtml = HTML::TreeBuilder::XPath->new;
        $xhtml->implicit_tags(1);
        $xhtml->no_space_compacting(1);
    
        # force input to be read in as UTF-8
        my $filehandle;
        open ($filehandle, "<", $file)
            or die("Could not open file '$file' : error: $!\n");
    
        # parse UTF-8
        $xhtml->parse_file($filehandle)
            or die("Could not parse file handle for '$file' : $!\n");
    
        close ($filehandle);
    
        open (OUT, ">", "/dev/stdout")
            or die("Could not open file 'stdout' : error: $!\n");
    
        # unique id attributes are needed, even when files are combined
        my ($second, $minute, $hour, $day) = gmtime(time);
        my $stamp = sprintf("%02d%02d%02d%02d", $day, $hour, $minute, $second);
        my $id = 0;
        for my $h3 ($xhtml->findnodes('//h3')) {
    	$h3->attr('id',sprintf("m%08d%02d", $stamp, $id++));
        }
    
        my $toc = $xhtml->clone();
        for my $h5 ($toc->findnodes('//ul[li[h5]]')) {
    	$h5->delete();
        }
    
        for my $h3 ($toc->findnodes('//h3')) {
    	my $id = $h3->attr('id');
    	my $c = $h3->detach_content();
    	my $new = HTML::Element->new('a');
    	$new->push_content($c);
    	$new->attr('href',"#$id");
    	$h3->replace_with($new);
        }
    
        my $t = HTML::Element->new('ul');;
        for my $ul ($toc->findnodes('/html/body/div/ul')) {
    	$t->push_content($ul->detach_content());
        }
    
        $toc->delete;
    
        for $toc ($xhtml->findnodes('//div/div/ul[1]')) {
    	$toc->replace_with($t);
    	last;
        }
    
        for $toc ($xhtml->findnodes('//body/div/div[contains(@id,"contents")]')) {
    	$toc->attr('id', 'contents'.$stamp);
        }
    
    #    print OUT $t->as_XML_indented;
    #    print OUT $toc->as_XML_indented;
        print OUT $xhtml->as_XML_indented;
    
        $xhtml->delete;
        return (1);
    }
    
    sub usage {
        my $script = $PROGRAM_NAME;
    
        $script =~ s/^.*\///;
    
        print qq(Usage: $script [hv] filename [filename...] \n);
        print qq(\t-h\tthis output\n);
        print qq(\t-v\tincrease verbosity\n);
        exit 0;
    }
    
    sub trim_white_space {
        my $element = shift;
    
        # see: HTML::Element and HTML::Element::traverse
        for my $itemref ($element->content_refs_list) {
            if($element->starttag =~ m/^

    Links/sort-feedlist.sh

    #!/bin/bash
    #Licence: Public Domain, feel free to share as you see fit
    #
    #Author: Roy Schestowitz
    
    echo   >> ~/rss-tools/RSS3.html
    echo             ====================================== Input string: $1   >> ~/rss-tools/RSS3.html
    echo   >> ~/rss-tools/RSS3.html
    SEARHFTERM=$1
    awk 'tolower($0) ~ /'$SEARHFTERM'/' RS=    RSS2.html >> RSS3.html
    

    Links/tr-links-de-duplicate.pl

    #!/usr/bin/perl
    
    # 2023-03-26
    
    use Cwd qw(abs_path);
    use DBI qw(:sql_types);
    use File::Basename qw(fileparse);
    use File::Copy qw(move);
    use File::Glob ':bsd_glob';
    use File::Path qw(make_path);
    use File::Path::Expand qw(expand_filename);
    use File::Temp qw(tempfile tempdir);
    use Date::Calc qw(Gmtime);
    use Getopt::Long;
    use HTML::TreeBuilder::XPath;
    use URI;
    use autodie;
    
    use open qw(:std :encoding(UTF-8));
    
    use strict;
    use warnings;
    
    use English;
    
    # default database file
    our $dbfile="~/.local/links-de-duplicate/tr.urls.sqlite3";
    my $script = $0;
    
    our %opt = (
        'clear' => 0,
        'decruftify' => 0,
        'ignore' => 0,
        'verbose' => 0,
        'write' => 0,
        'help' => 0,
    );
    
    GetOptions (
        "clear|c"      => \$opt{'clear'},		# flag
        "decruftify|d" => \$opt{'decruftify'},	# flag
        "file|f=s"     => \$opt{'dbfile'},		# string
        "help|h"       => \$opt{'help'},		# flag
        "ignore|i"     => \$opt{'ignore'},		# flag
        "undo|u"       => \$opt{'undo'},		# flag
        "verbose|v+"   => \$opt{'verbose'},		# flag, multiple settings
        "write|w"      => \$opt{'write'},		# flag
        );
    
    if ($opt{'help'}) {
        &help($script);
    }
    
    my $dbpath = &prepare_dbpath($dbfile);
    my $result = &prepare_db($dbfile);
    
    # erase the table's contents first if requested
    if ($opt{'clear'}) {
        $result = &clear_db($dbfile);
        print qq(Cleared '$dbfile' successfully\n);
    } elsif ($opt{'undo'}) {
        $result = &clear_latest_batch($dbfile);
        print qq(Rolled back '$dbfile' one step\n);
        exit(0);
    }
    
    # read the file names from the runtime arguments
    my @filenames;
    while (my $file = shift) {
        my @files = bsd_glob($file);
        foreach my $f (@files) {
    	push(@filenames, abs_path($f));
        }
    }
    
    # remove any repeated file names but keep the sequence
    my %ff;
    my @tmp;
    foreach my $f (@filenames) {
        if ($ff{$f}++) {
    	next;
        }
        push(@tmp, $f);
    }
    @filenames = @tmp;
    undef(@tmp);
    
    if ($#filenames < 0) {
        print qq(Target file missing\n);
        &help($script);
    }
    
    if ($opt{'verbose'}) {
        print "Attempting to read these files:\n\t";
        print join("\n\t", @filenames),qq(\n);
    }
    
    # use the same time stamp for all transactions
    our $epoch = time();
    
    # check each file in sequence
    foreach my $file (@filenames) {
        my $xhtml_result = &get_urls_from_file($file);
    
        # overwrite if requested
        if ($opt{'write'}) {
    	# use a temporary file first, save the original as a backup
    	# then rename the temporary file to the original name
    
    	my ($fh, $filename) = tempfile();
    	print $fh $xhtml_result;
    	close($fh);
    
    	rename($file,"$file.old")
    	    or die("$!\n");
    
    	move($filename, $file)
    	    or die("$!\n");
    
        } else {
    	print $xhtml_result;
        }
    }
    
    exit(0);
    
    sub get_urls_from_file {
        my ($file) = (@_);
    
        # force input to be read in as UTF-8
        my $linkfile;
        open ($linkfile, "<", $file)
    	or die("Could not open file '$file' : error: $!\n");
    
        # use this pattern to find the start of URLs in the text
        my $scheme = qr/gemini|https|http|ftp|sftp|ssh|rtsp|rsync|gopher/x;
    
        # go through the file a line at a time, looking for URL patterns
        my %urls;
    
        my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", undef, undef,
                               { AutoCommit => 0, RaiseError => 1 })
            or die("Could not open database '$dbfile': $!\n");
    
        my $searchquery = qq(SELECT url FROM links WHERE url = ?);
        my $sthsearch = $dbh->prepare($searchquery)
            or die("prepare statement failed: $dbh->errstr()\n");
    
        my $insertquery = qq(INSERT INTO links (firstseen, url) VALUES (?,?));
        my $sthinsert = $dbh->prepare($insertquery)
            or die("prepare statement failed: $dbh->errstr()\n");
    
        my $xhtml = HTML::TreeBuilder::XPath->new;
        $xhtml->implicit_tags(1);
    
        # parse UTF-8
        $xhtml->parse_file($linkfile)
            or die("Could not parse file handle for '$file' : $!\n");
    
        close($linkfile);
    
        my $redundant = HTML::Element->new('div', 'class'=> 'duplicates');
        my $redundant_ul = HTML::Element->new('ul', 'class'=> 'duplicates');
        $redundant->insert_element($redundant_ul);
    
        for my $node ($xhtml->findnodes('//li[h5]')) {
            for my $anchor ($node->findnodes('./h5/a[@href]')) {
                my $href = $anchor->attr('href');
                next unless($href);
    
    	    if($opt{'decruftify'}) {
    		my $cleaned_href = &decruftify($href);
                    if ($cleaned_href) {
                        $anchor->attr('href', $cleaned_href);
                        $href = $cleaned_href;
                    }
    	    }
    
    	    if ($opt{'verbose'} > 1) {
    		print qq($href\n);
    	    }
    
    	    eval {
    		$sthsearch->execute($href);
    	    };
    	    if ($@) {
    		$sthsearch->finish;
    		$dbh->rollback;
    		$dbh->disconnect;
    		die("execute statement failed: $dbh->errstr()\n");
    	    }
    
    	    my $hash_ref = $sthsearch->fetchall_hashref('url');
    	    my $rv = $sthsearch->rows;
    	    if ($rv > 0) {
    		# duplicate exists
    		if ($opt{'verbose'}) {
    		    print "Deleting: $href\n";
    		}
    		if (!$opt{'ignore'}) {
    		    my $copy = $node->clone();
    		    $copy->attr('class','duplicate');
    		    $redundant_ul->postinsert($copy);
    		    $node->delete;
    		}
    	    } else {
    		eval {
    		    $sthinsert->execute($epoch, $href);
    		};
    		if ($@) {
    		    $sthinsert->finish;
    		    $dbh->rollback;
    		    $dbh->disconnect;
    		    die("execute statement failed: $dbh->errstr()\n");
    		}
    	    }
    	}
        }
    
        # get rid of repeated 
    elements for my $node ($xhtml->findnodes('//body/hr[preceding-sibling::hr]')) { # print STDERR "hr removed\n"; $node->delete; } # only add these elements if there were any duplicates if ($redundant_ul->descendants()) { # add the division containing the list of duplicates inside the end of body for my $node ($xhtml->findnodes('//body[1]')) { $node->insert_element($redundant); last; } } $dbh->commit; $sthinsert->finish; $dbh->disconnect; my $result = $xhtml->as_XML_indented || 0; $redundant->delete; $xhtml->delete; return ($result); } sub prepare_dbpath { my ($dbpath) = (@_); $dbfile = expand_filename($dbfile); my ($filename, $dirs, $suffix) = fileparse($dbpath); $dirs = expand_filename($dirs); if (! -e $dirs) { my @created = make_path($dirs, { verbose => $opt{'verbose'}, chmod => 0755, }) or die("Could not create path '$dirs' : $!\n"); if ($opt{'verbose'} > 1) { print "Directory ",join(',', @created), " added\n"; } } elsif (! -d $dirs) { die("'$dbpath' exists but is not a directory.\n"); } elsif (! -w $dirs) { die("Directory '$dbpath' is not writable.\n"); } return($dirs); } sub prepare_db { my ($dbfile) = (@_); my $schema = qq(CREATE TABLE IF NOT EXISTS links (firstseen INTEGER DEFAULT 0, url TEXT NOT NULL UNIQUE)); my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", undef, undef, { AutoCommit => 0, RaiseError => 1 }) or die("Could not open database '$dbfile': $!\n"); my $sth = $dbh->prepare($schema) or die("prepare statement failed: $dbh->errstr()\n"); eval { $sth->execute(); }; if ($@) { $sth->finish; $dbh->rollback; $dbh->disconnect; die("execute statement failed: $dbh->errstr()\n"); } my $query = qq(SELECT url FROM links LIMIT 1); eval { $sth = $dbh->prepare($query) }; if ($@) { $dbh->disconnect; die("prepare statement failed: $dbh->errstr()\n"); } eval { $sth->execute(); }; if ($@) { $sth->finish; $dbh->rollback; $dbh->disconnect; die("execute statement failed: $dbh->errstr()\n"); } $dbh->commit; $sth->finish; $dbh->disconnect; return(1); } sub clear_db { my ($dbfile) = (@_); my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", undef, undef, { AutoCommit => 0, RaiseError => 1 }) or die("Could not open database '$dbfile': $!\n"); my $deletequery = qq(DELETE FROM links); my $sthdelete = $dbh->prepare($deletequery) or die("prepare statement failed: $dbh->errstr()\n"); eval { $sthdelete->execute(); }; if ($@) { $sthdelete->finish; $dbh->rollback; $dbh->disconnect; die("execute statement failed: $dbh->errstr()\n"); } $dbh->commit; $sthdelete->finish; $dbh->disconnect; return(1); } sub clear_latest_batch { my ($dbfile) = (@_); my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", undef, undef, { AutoCommit => 0, RaiseError => 1 }) or die("Could not open database '$dbfile': $!\n"); my $deletequery = qq(DELETE FROM links WHERE firstseen = (SELECT max(firstseen) FROM links)); my $sthdelete = $dbh->prepare($deletequery) or die("prepare statement failed: $dbh->errstr()\n"); eval { $sthdelete->execute(); }; if ($@) { $sthdelete->finish; $dbh->rollback; $dbh->disconnect; die("execute statement failed: $dbh->errstr()\n"); } $dbh->commit; $deletequery = qq(SELECT max(firstseen) AS firstseen FROM links); $sthdelete = $dbh->prepare($deletequery) or die("prepare statement failed: $dbh->errstr()\n"); eval { $sthdelete->execute(); }; if ($@) { $sthdelete->finish; $dbh->rollback; $dbh->disconnect; die("execute statement failed: $dbh->errstr()\n"); } my $firstseen; my $rv = $sthdelete->bind_columns(\$firstseen); if ($rv) { $sthdelete->fetch; my ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Gmtime($firstseen); printf "Rolled back to %04d-%02d-%02d %02d:%02d\n", $year,$month,$day, $hour,$min,$sec; } $sthdelete->finish; $dbh->disconnect; return(1); } sub decruftify { my ($href) = (@_); my $uri = URI->new($href); my $host; eval { $host = $uri->host; }; if ($@) { return(0); } if ($host eq 'www.cnet.com') { $uri->fragment(undef); } elsif ($host eq 'www.thenation.com') { $uri->query(undef); } elsif ($host eq 'www.csmonitor.com') { $uri->query(undef); } elsif ($host eq 'www.theatlantic.com/') { $uri->query(undef); } elsif ($host eq 'emorywheel.com') { $uri->query(undef); } elsif ($host eq 'scheerpost.com') { $uri->query(undef); } elsif ($host eq 'www.michaelgeist.ca') { $uri->query(undef); } elsif ($host eq 'www.engadget.com') { $uri->query(undef); } elsif ($host eq 'www.cbc.ca') { $uri->query(undef); } elsif ($host eq 'www.theage.com.au') { $uri->query(undef); } elsif ($host eq 'www.spiegel.de') { $uri->fragment(undef); } elsif ($host eq 'www.dw.com') { $uri->query(undef); } elsif ($host eq 'eng.lsm.lv') { $uri->query(undef); } elsif ($host eq 'yle.fi') { $uri->query(undef); } else { return(0); } $href=$uri->canonical; if ($opt{'verbose'} > 1) { print qq(D = $href\n); } return($href); } sub help { my ($script) = (@_); $script =~ s|.*/||; print <

    => Back to main index

    Proxy Information
    Original URL
    gemini://gemini.techrights.org/git/tr-git/Links
    Status Code
    Success (20)
    Meta
    text/gemini;lang=en-GB
    Capsule Response Time
    461.523758 milliseconds
    Gemini-to-HTML Time
    14.698022 milliseconds

    This content has been proxied by September (ba2dc).