Additions to the database and feedWatcher
feedWatcher: added the parsing of HTML feeds to get the title tag in the <head> area; new database fields relating to the copyright check done, and why the feed was allowed in if done so manually; added dry run mode; changed the way -load and -delete work so each can be given URLs on the command line; starting to report settings at start time (needs work); -load and -delete not allowed together; more logging; addition of a _debug function; enhancement of reportFeed to show one feed and a summary of relevant details (more useful than dumping the entire database this way); added getHTMLTitle for parsing out the HTML title; enhanced checkCopyright to get a reason if in manual mode and a feed is allowed in; needs a lot of clean-up! feedWatcher.{html,json,mkd,opml,pdf}: various reports. feedWatcher_3.tpl: For making Markdown which is turned into PDF. 'Licence' becomes 'Copyright' feedWatcher_5.tpl: for dumping all the URLs in the database & regenerating everything feedWatcher_schema.sql: new fields added
This commit is contained in:
parent
01ec2cf92f
commit
db39655199
513
feedWatcher
513
feedWatcher
@ -48,8 +48,8 @@ use feature qw{ postderef say signatures state };
|
|||||||
no warnings qw{ experimental::postderef experimental::signatures } ;
|
no warnings qw{ experimental::postderef experimental::signatures } ;
|
||||||
|
|
||||||
#
|
#
|
||||||
# There's an issue in XML::RSS, so we're using a loocal version with a hack.
|
# There's an issue in XML::RSS, so we're using a local version with a hack.
|
||||||
# It's in ./lib/ and FiindBin::libs looks there to find it.
|
# It's in ./lib/ and FindBin::libs looks there to find it.
|
||||||
#
|
#
|
||||||
use FindBin::libs;
|
use FindBin::libs;
|
||||||
use XML::RSS;
|
use XML::RSS;
|
||||||
@ -77,6 +77,7 @@ use Template::Filters;
|
|||||||
Template::Filters->use_html_entities; # Use HTML::Entities in the template
|
Template::Filters->use_html_entities; # Use HTML::Entities in the template
|
||||||
|
|
||||||
use HTML::Entities;
|
use HTML::Entities;
|
||||||
|
use HTML::Parser ();
|
||||||
|
|
||||||
use IO::Prompter;
|
use IO::Prompter;
|
||||||
|
|
||||||
@ -102,14 +103,17 @@ our $VERSION = '0.1.2';
|
|||||||
#
|
#
|
||||||
# Declarations
|
# Declarations
|
||||||
#
|
#
|
||||||
my ( @new_urls, @deletions );
|
my ( $action_mode, @urls, @deletions );
|
||||||
my ( $rules, $robot_name ) = ( undef, "$PROG/$VERSION" );
|
my ( $rules, $robot_name ) = ( undef, "$PROG/$VERSION" );
|
||||||
my ($search_target);
|
my ( $sth1, $h1, $rv, $search_target, $rejectcount );
|
||||||
my ( $sth1, $h1, $rv );
|
|
||||||
my ($rejectcount);
|
|
||||||
|
|
||||||
my $feeds;
|
my $feeds;
|
||||||
|
|
||||||
|
#
|
||||||
|
# To be written by a handler subroutine called by HTML::Parser
|
||||||
|
#
|
||||||
|
our $html_title;
|
||||||
|
|
||||||
#
|
#
|
||||||
# File and directory paths
|
# File and directory paths
|
||||||
#
|
#
|
||||||
@ -127,6 +131,7 @@ my $deftemplate = "$basedir/${PROG}.tpl";
|
|||||||
my %keymap = (
|
my %keymap = (
|
||||||
AUTHOR => 'author',
|
AUTHOR => 'author',
|
||||||
COPYRIGHT => 'copyright',
|
COPYRIGHT => 'copyright',
|
||||||
|
CHECKTYPE => 'check_type',
|
||||||
DESCRIPTION => 'description',
|
DESCRIPTION => 'description',
|
||||||
DNS => 'dns',
|
DNS => 'dns',
|
||||||
# ENCLOSURES => undef,
|
# ENCLOSURES => undef,
|
||||||
@ -142,6 +147,7 @@ my %keymap = (
|
|||||||
LINK => 'link',
|
LINK => 'link',
|
||||||
MODIFIED => 'modified',
|
MODIFIED => 'modified',
|
||||||
# PORT => undef,
|
# PORT => undef,
|
||||||
|
REASON_ACCEPTED => 'reason_accepted',
|
||||||
# ROBOTS => undef,
|
# ROBOTS => undef,
|
||||||
# SAVE => undef,
|
# SAVE => undef,
|
||||||
TITLE => 'title',
|
TITLE => 'title',
|
||||||
@ -178,7 +184,7 @@ Options( \%options );
|
|||||||
#
|
#
|
||||||
# Any arguments are taken to be URLs
|
# Any arguments are taken to be URLs
|
||||||
#
|
#
|
||||||
@new_urls = @ARGV;
|
@urls = @ARGV;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Default help
|
# Default help
|
||||||
@ -199,11 +205,14 @@ my $DEBUG = ( $options{'debug'} ? $options{'debug'} : 0 );
|
|||||||
|
|
||||||
my $cfgfile
|
my $cfgfile
|
||||||
= ( defined( $options{config} ) ? $options{config} : $configfile );
|
= ( defined( $options{config} ) ? $options{config} : $configfile );
|
||||||
|
my $dry_run = ( defined( $options{'dry-run'} ) ? $options{'dry-run'} : 0 );
|
||||||
my $silent = ( defined( $options{silent} ) ? $options{silent} : 0 );
|
my $silent = ( defined( $options{silent} ) ? $options{silent} : 0 );
|
||||||
|
|
||||||
my $loadfile = $options{'load'};
|
my $loadfile = $options{'load'};
|
||||||
my $deletefile = $options{'delete'};
|
my $deletefile = $options{'delete'};
|
||||||
|
|
||||||
my $scan = ( defined( $options{scan} ) ? $options{scan} : 0 );
|
my $scan = ( defined( $options{scan} ) ? $options{scan} : 0 );
|
||||||
|
my $html = ( defined( $options{html} ) ? $options{html} : 0 );
|
||||||
|
|
||||||
my $check = $options{check};
|
my $check = $options{check};
|
||||||
my $outfile = $options{out};
|
my $outfile = $options{out};
|
||||||
@ -213,32 +222,58 @@ my $json = $options{json};
|
|||||||
my $opml = $options{opml};
|
my $opml = $options{opml};
|
||||||
my $template = $options{template};
|
my $template = $options{template};
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Validate and process options
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Sanity
|
||||||
|
#
|
||||||
|
die "Choose either -load or -delete, not both\n"
|
||||||
|
if (defined($loadfile) && defined($deletefile));
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check the configuration file
|
# Check the configuration file
|
||||||
#
|
#
|
||||||
die "Unable to find configuration file $cfgfile\n" unless ( -e $cfgfile );
|
die "Unable to find configuration file $cfgfile\n" unless ( -e $cfgfile );
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check the load file
|
# Process the load option and the delete option, checking any files mentioned,
|
||||||
|
# and determining the primary action we're aiming for.
|
||||||
#
|
#
|
||||||
if ($loadfile) {
|
if (optionalFile('load', $loadfile)) {
|
||||||
die "File $loadfile does not exist\n" unless -e $loadfile;
|
$action_mode = 'load';
|
||||||
die "File $loadfile is not readable\n" unless -r $loadfile;
|
_debug(
|
||||||
|
$DEBUG > 0,
|
||||||
|
"Action mode: $action_mode",
|
||||||
|
( $loadfile eq ''
|
||||||
|
? "Load from arguments"
|
||||||
|
: "File to load: $loadfile"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elsif (optionalFile('delete', $deletefile)) {
|
||||||
|
$action_mode = 'delete';
|
||||||
|
_debug(
|
||||||
|
$DEBUG > 0,
|
||||||
|
"Action mode: $action_mode",
|
||||||
|
( $deletefile eq ''
|
||||||
|
? "Delete from arguments"
|
||||||
|
: "File to delete from $deletefile"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$action_mode = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check the delete file
|
# The copyright checking mode defaults to 'auto' if the option has no value,
|
||||||
|
# or may be 'manual' or 'none'. If the option is not used at all it defaults
|
||||||
|
# to 'none'. It's only relevant to the 'load' action though.
|
||||||
#
|
#
|
||||||
if ($deletefile) {
|
if ( $action_mode eq 'load' ) {
|
||||||
die "File $deletefile does not exist\n" unless -e $deletefile;
|
if ( $action_mode eq 'load' && defined($check) ) {
|
||||||
die "File $deletefile is not readable\n" unless -r $deletefile;
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# The checking mode defaults to 'auto' if the option has no value, or may be
|
|
||||||
# 'manual' or 'none'. If the option is not used at all it defaults to 'none'.
|
|
||||||
#
|
|
||||||
if ( defined($check) ) {
|
|
||||||
$check =~ s/(^\s+|\s+$)//g;
|
$check =~ s/(^\s+|\s+$)//g;
|
||||||
if ($check =~ /^$/) {
|
if ($check =~ /^$/) {
|
||||||
$check = "auto";
|
$check = "auto";
|
||||||
@ -249,14 +284,21 @@ if ( defined($check) ) {
|
|||||||
"Values are <blank>, auto and manual\n"
|
"Values are <blank>, auto and manual\n"
|
||||||
unless ($check =~ /^(auto|manual|none)$/)
|
unless ($check =~ /^(auto|manual|none)$/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$check = 'none';
|
$check = 'none';
|
||||||
|
}
|
||||||
|
emit($silent,"Copyright check mode = $check\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit($silent,"Dry run mode = " . ($dry_run ? "On" : "Off") . "\n");
|
||||||
|
emit($silent,"----\n");
|
||||||
|
|
||||||
|
# TODO: Does it make sense to have -load and -report, etc at the same time?
|
||||||
#
|
#
|
||||||
# We accept -report, meaning report everything or -report='title' to report
|
# We accept -report, meaning report everything or -report='title' to report
|
||||||
# just the feed with the given title.
|
# just the feed with the given title (actually, the title which contains the
|
||||||
|
# given string).
|
||||||
#
|
#
|
||||||
if ( defined($report) ) {
|
if ( defined($report) ) {
|
||||||
if ($report =~ /^$/) {
|
if ($report =~ /^$/) {
|
||||||
@ -266,6 +308,7 @@ if ( defined($report) ) {
|
|||||||
$search_target = $report;
|
$search_target = $report;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# We accept -json or -json=filename. In the former case we make a default
|
# We accept -json or -json=filename. In the former case we make a default
|
||||||
# name, otherwise we use the one provided.
|
# name, otherwise we use the one provided.
|
||||||
@ -298,9 +341,9 @@ if ( defined($template) ) {
|
|||||||
die "Error: Unable to find template $template\n" unless -r $template;
|
die "Error: Unable to find template $template\n" unless -r $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#-------------------------------------------------------------------------------
|
||||||
# Load configuration data
|
# Load configuration data
|
||||||
#
|
#-------------------------------------------------------------------------------
|
||||||
my $conf = new Config::General(
|
my $conf = new Config::General(
|
||||||
-ConfigFile => $cfgfile,
|
-ConfigFile => $cfgfile,
|
||||||
-InterPolateVars => 1,
|
-InterPolateVars => 1,
|
||||||
@ -308,9 +351,9 @@ my $conf = new Config::General(
|
|||||||
);
|
);
|
||||||
my %config = $conf->getall();
|
my %config = $conf->getall();
|
||||||
|
|
||||||
#
|
#-------------------------------------------------------------------------------
|
||||||
# Connect to the database
|
# Connect to the database
|
||||||
#
|
#-------------------------------------------------------------------------------
|
||||||
my $dbtype = $config{database}->{type};
|
my $dbtype = $config{database}->{type};
|
||||||
my $dbfile = $config{database}->{file};
|
my $dbfile = $config{database}->{file};
|
||||||
my $dbuser = $config{database}->{user};
|
my $dbuser = $config{database}->{user};
|
||||||
@ -331,9 +374,7 @@ $dbh->do('PRAGMA foreign_keys = ON');
|
|||||||
#
|
#
|
||||||
my $rows = countRows( $dbh, 'SELECT count(*) FROM urls' );
|
my $rows = countRows( $dbh, 'SELECT count(*) FROM urls' );
|
||||||
my $work = (
|
my $work = (
|
||||||
scalar(@new_urls) > 0
|
( scalar(@urls) > 0 && $action_mode =~ /load|delete/ )
|
||||||
|| defined($loadfile)
|
|
||||||
|| defined($deletefile)
|
|
||||||
|| ( defined($report)
|
|| ( defined($report)
|
||||||
|| defined($json)
|
|| defined($json)
|
||||||
|| defined($opml)
|
|| defined($opml)
|
||||||
@ -341,7 +382,10 @@ my $work = (
|
|||||||
|| $scan && $rows > 0 )
|
|| $scan && $rows > 0 )
|
||||||
);
|
);
|
||||||
|
|
||||||
die "Nothing to do!\n" unless $work;
|
unless ($work) {
|
||||||
|
print STDERR "Nothing to do!\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Set up logging keeping the default log layout except for the date
|
# Set up logging keeping the default log layout except for the date
|
||||||
@ -391,9 +435,14 @@ if ($rejectfile) {
|
|||||||
$rules = WWW::RobotRules->new($robot_name);
|
$rules = WWW::RobotRules->new($robot_name);
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Slurp the load file into @new_urls if the file is provided
|
# Check the mode we are in and prepare to load or delete according to the
|
||||||
|
# answer.
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if ($loadfile) {
|
if ($action_mode eq 'load') {
|
||||||
|
#
|
||||||
|
# Slurp the load file into @urls if the file is provided
|
||||||
|
#
|
||||||
|
if ($loadfile) {
|
||||||
#
|
#
|
||||||
# Load the input file
|
# Load the input file
|
||||||
#
|
#
|
||||||
@ -408,49 +457,49 @@ if ($loadfile) {
|
|||||||
#
|
#
|
||||||
# Add the loaded URLs to the array
|
# Add the loaded URLs to the array
|
||||||
#
|
#
|
||||||
push( @new_urls, @loaded );
|
push( @urls, @loaded );
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Now, we either have URLs from the command line, or from the load file (or
|
# Now, we either have URLs from the command line, or from the load file (or
|
||||||
# both), so we process these.
|
# both), so we process these.
|
||||||
#
|
#
|
||||||
# It's a loop because 'loadUrls' might find some more URLs by scanning HTML
|
# It's a loop because 'loadUrls' might find some more URLs by scanning HTML
|
||||||
# URLs if given them. If it does we replace @new_urls with the found URLs and
|
# URLs if given them. If it does we replace @urls with the found URLs and
|
||||||
# go again. When there's nothing returned the loop stops.
|
# go again. When there's nothing returned the loop stops.
|
||||||
# ----
|
# ----
|
||||||
# NOTE: This seems dirty, but all the 'while' is testing is whether the array
|
# NOTE: This seems dirty, but all the 'while' is testing is whether the array
|
||||||
# contains anything or not. It's not iterating over it or anything, which would
|
# contains anything or not. It's not iterating over it or anything, which would
|
||||||
# be messy!
|
# be messy!
|
||||||
#
|
#
|
||||||
while (@new_urls) {
|
while (@urls) {
|
||||||
#
|
#
|
||||||
# Remove duplicates, finish if it deletes them all!
|
# Remove duplicates, finish if it deletes them all!
|
||||||
#
|
#
|
||||||
@new_urls = uniq(@new_urls);
|
@urls = uniq(@urls);
|
||||||
last unless @new_urls;
|
last unless @urls;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Remove any commented out lines, finish if it deletes them all!
|
# Remove any commented out lines, finish if it deletes them all!
|
||||||
#
|
#
|
||||||
@new_urls = grep {!/^\s*#/} @new_urls;
|
@urls = grep {!/^\s*#/} @urls;
|
||||||
last unless @new_urls;
|
last unless @urls;
|
||||||
|
|
||||||
$LOG->info( "Received ", scalar(@new_urls),
|
$LOG->info( "Loading ", scalar(@urls), " URLs to the database" );
|
||||||
" URLs to add to the database" );
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Load these URLs as appropriate, returning any more that we find by
|
# Load these URLs as appropriate, returning any more that we find by
|
||||||
# following HTML urls. We overwrite the original list and start all over
|
# following HTML urls. We overwrite the original list and start all over
|
||||||
# again.
|
# again.
|
||||||
#
|
#
|
||||||
@new_urls = loadUrls( $dbh, \@new_urls, $rules, \%keymap );
|
@urls = loadUrls( $dbh, \@urls, $rules, \%keymap, $dry_run );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
elsif ($action_mode eq 'delete') {
|
||||||
#
|
#
|
||||||
# Process the delete file if there is one
|
# Process the delete file if there is one
|
||||||
#
|
#
|
||||||
if ($deletefile) {
|
if ($deletefile) {
|
||||||
#
|
#
|
||||||
# Load the delete file
|
# Load the delete file
|
||||||
#
|
#
|
||||||
@ -458,35 +507,48 @@ if ($deletefile) {
|
|||||||
or die "$PROG : failed to open load file '$deletefile' : $!\n";
|
or die "$PROG : failed to open load file '$deletefile' : $!\n";
|
||||||
chomp( @deletions = <$del> );
|
chomp( @deletions = <$del> );
|
||||||
close($del)
|
close($del)
|
||||||
or warn "$PROG : failed to close load file '$deletefile' : $!\n";
|
or warn "$PROG : failed to close delete file '$deletefile' : $!\n";
|
||||||
|
|
||||||
|
#
|
||||||
|
# Add the loaded URLs to the array
|
||||||
|
#
|
||||||
|
push( @urls, @deletions );
|
||||||
|
|
||||||
#
|
#
|
||||||
# Remove duplicates
|
# Remove duplicates
|
||||||
#
|
#
|
||||||
@deletions = uniq(@deletions);
|
@urls = uniq(@urls);
|
||||||
|
}
|
||||||
$LOG->info( "Deleting ", scalar(@deletions), " URLs from the database" );
|
|
||||||
|
|
||||||
|
if (@urls) {
|
||||||
#
|
#
|
||||||
# There are URLs to delete. Process them on by one.
|
# TODO: check that these URLs are actually in the database! Seems
|
||||||
|
# silly to report "Failed to delete" when it's not there anyway!
|
||||||
#
|
#
|
||||||
if (@deletions) {
|
# There are URLs to delete. Process them one by one.
|
||||||
|
#
|
||||||
|
if ($dry_run) {
|
||||||
|
emit( $silent,
|
||||||
|
"Would have deleted " . scalar(@urls) . " URLs\n" )
|
||||||
|
}
|
||||||
|
else {
|
||||||
$sth1 = $dbh->prepare(q{DELETE from urls WHERE url = ?});
|
$sth1 = $dbh->prepare(q{DELETE from urls WHERE url = ?});
|
||||||
foreach my $rec (@deletions) {
|
foreach my $rec (@urls) {
|
||||||
$rv = $sth1->execute($rec);
|
$rv = $sth1->execute($rec);
|
||||||
if ( $dbh->err ) {
|
if ( $dbh->err ) {
|
||||||
warn $dbh->errstr;
|
warn $dbh->errstr;
|
||||||
}
|
}
|
||||||
if ( $rv != 0 ) {
|
if ( $rv != 0 ) {
|
||||||
emit ( $silent, "Deleted $rec ($rv rows)\n" );
|
emit ( $silent, "Deleted $rec ($rv rows)\n" );
|
||||||
|
$LOG->info( "Deleted URL '$rec' from the database" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit ( $silent, "Failed to delete $rec\n" );
|
emit ( $silent, "Failed to delete $rec\n" );
|
||||||
|
$LOG->warning( "Failed to delete '$rec' from the database" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -494,9 +556,9 @@ if ($deletefile) {
|
|||||||
# TODO: Needs to be developed; does nothing at the moment.
|
# TODO: Needs to be developed; does nothing at the moment.
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if ($scan) {
|
if ($scan) {
|
||||||
$LOG->info( "Scan is not fully implemented yet" );
|
$LOG->warning( "Scan is not fully implemented yet" );
|
||||||
# Testing. Processes the first two feeds
|
# Testing. Processes the first two feeds
|
||||||
scanDB($dbh, \%keymap);
|
scanDB($dbh, \%keymap, $dry_run);
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -625,7 +687,7 @@ if ($opml) {
|
|||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Fill and print the template if requested
|
# Fill and print the TT² template if requested
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if ($template) {
|
if ($template) {
|
||||||
my $tt = Template->new(
|
my $tt = Template->new(
|
||||||
@ -664,12 +726,14 @@ exit;
|
|||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
# NAME: loadUrls
|
# NAME: loadUrls
|
||||||
# PURPOSE: To load URLs read from the input file into the database
|
# PURPOSE: To load URLs read from the input file (and the arguments) into
|
||||||
|
# the database
|
||||||
# PARAMETERS: $dbh database handle
|
# PARAMETERS: $dbh database handle
|
||||||
# $new_urls arrayref containing URLs
|
# $new_urls arrayref containing URLs
|
||||||
# $rules WWW::RobotRules object
|
# $rules WWW::RobotRules object
|
||||||
# $keymap hashref containing a map of key names to
|
# $keymap hashref containing a map of key names to
|
||||||
# database field names
|
# database field names
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# RETURNS: Any new URLs discovered by investigating non-feed URLs.
|
# RETURNS: Any new URLs discovered by investigating non-feed URLs.
|
||||||
# DESCRIPTION:
|
# DESCRIPTION:
|
||||||
# THROWS: No exceptions
|
# THROWS: No exceptions
|
||||||
@ -677,7 +741,7 @@ exit;
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub loadUrls {
|
sub loadUrls {
|
||||||
my ( $dbh, $new_urls, $rules, $keymap ) = @_;
|
my ( $dbh, $new_urls, $rules, $keymap, $dry_run ) = @_;
|
||||||
|
|
||||||
my ( $stream, $feed );
|
my ( $stream, $feed );
|
||||||
my ( %uridata, $roboturl, @found_urls );
|
my ( %uridata, $roboturl, @found_urls );
|
||||||
@ -751,7 +815,7 @@ sub loadUrls {
|
|||||||
emit( $silent, "Search for robots.txt file failed\n" );
|
emit( $silent, "Search for robots.txt file failed\n" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit( $silent, "Check of robots.txt rules failed\n" );
|
emit( $silent, "Check of robots.txt rules blocks access\n" );
|
||||||
$uridata{SAVE} = 0;
|
$uridata{SAVE} = 0;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
@ -790,13 +854,14 @@ sub loadUrls {
|
|||||||
# weirdness of RSS and poor adherence to what standards there
|
# weirdness of RSS and poor adherence to what standards there
|
||||||
# are).
|
# are).
|
||||||
#
|
#
|
||||||
print Dumper($feed), "\n" if ( $DEBUG > 2 );
|
_debug( $DEBUG > 2, Dumper($feed));
|
||||||
storeFeed($feed,\%uridata);
|
storeFeed($feed,\%uridata);
|
||||||
|
|
||||||
#
|
#
|
||||||
# Perform a check on the copyright. The routine sets
|
# Perform a check on the copyright. The routine sets
|
||||||
# $uridata{SAVE} = 0 if the copyright is not acceptable.
|
# $uridata{SAVE} = 0 if the copyright is not acceptable.
|
||||||
#
|
#
|
||||||
|
$uridata{CHECKMODE} = $check;
|
||||||
if ( $check ne 'none' ) {
|
if ( $check ne 'none' ) {
|
||||||
unless (checkCopyright( $check, \%uridata )) {
|
unless (checkCopyright( $check, \%uridata )) {
|
||||||
#
|
#
|
||||||
@ -848,7 +913,7 @@ sub loadUrls {
|
|||||||
# Decide whether to save what we have collected
|
# Decide whether to save what we have collected
|
||||||
#
|
#
|
||||||
if ( $uridata{SAVE} ) {
|
if ( $uridata{SAVE} ) {
|
||||||
if ( addURI( $dbh, \%uridata, $keymap ) ) {
|
if ( addURI( $dbh, \%uridata, $keymap, $dry_run ) ) {
|
||||||
emit( $silent, "$uridata{URI} added to the database\n" );
|
emit( $silent, "$uridata{URI} added to the database\n" );
|
||||||
$LOG->info("$uridata{TYPE} ",$uridata{URI},' added to the database');
|
$LOG->info("$uridata{TYPE} ",$uridata{URI},' added to the database');
|
||||||
|
|
||||||
@ -864,7 +929,7 @@ sub loadUrls {
|
|||||||
if ( defined( $uridata{ENCLOSURE_COUNT} )
|
if ( defined( $uridata{ENCLOSURE_COUNT} )
|
||||||
&& $uridata{ENCLOSURE_COUNT} > 0 )
|
&& $uridata{ENCLOSURE_COUNT} > 0 )
|
||||||
{
|
{
|
||||||
if ( addEnclosures( $dbh, \%uridata ) ) {
|
if ( addEnclosures( $dbh, \%uridata, $dry_run ) ) {
|
||||||
emit( $silent, $uridata{ENCLOSURE_COUNT},
|
emit( $silent, $uridata{ENCLOSURE_COUNT},
|
||||||
" enclosures for $uridata{URI} added to the database\n"
|
" enclosures for $uridata{URI} added to the database\n"
|
||||||
);
|
);
|
||||||
@ -882,7 +947,7 @@ sub loadUrls {
|
|||||||
#
|
#
|
||||||
# Dump what we have if requested
|
# Dump what we have if requested
|
||||||
#
|
#
|
||||||
print Dumper( \%uridata ), "\n" if ( $DEBUG > 1 );
|
_debug( $DEBUG > 1, Dumper( \%uridata ) );
|
||||||
|
|
||||||
emit( $silent, '-' x 80, "\n" );
|
emit( $silent, '-' x 80, "\n" );
|
||||||
}
|
}
|
||||||
@ -969,6 +1034,7 @@ sub searchTitle {
|
|||||||
# PARAMETERS: $dbh database handle
|
# PARAMETERS: $dbh database handle
|
||||||
# $keymap hashref containing a map of key names to
|
# $keymap hashref containing a map of key names to
|
||||||
# database field names
|
# database field names
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# RETURNS: Nothing
|
# RETURNS: Nothing
|
||||||
# DESCRIPTION:
|
# DESCRIPTION:
|
||||||
# THROWS: No exceptions
|
# THROWS: No exceptions
|
||||||
@ -976,8 +1042,9 @@ sub searchTitle {
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub scanDB {
|
sub scanDB {
|
||||||
my ($dbh, $keymap) = @_;
|
my ($dbh, $keymap, $dry_run) = @_;
|
||||||
|
|
||||||
|
# TODO: dry-run mode not implemented here yet
|
||||||
my ( $sql1, $sth1, $rv1, $h1 );
|
my ( $sql1, $sth1, $rv1, $h1 );
|
||||||
my ( $aref, @urls, $DT, $stream, $feed );
|
my ( $aref, @urls, $DT, $stream, $feed );
|
||||||
my ( %uridata, $urichanges, $enc_changes );
|
my ( %uridata, $urichanges, $enc_changes );
|
||||||
@ -1259,7 +1326,7 @@ sub scanFeed {
|
|||||||
#
|
#
|
||||||
# Save the important feed components in the %uridata hash
|
# Save the important feed components in the %uridata hash
|
||||||
#
|
#
|
||||||
print Dumper($feed), "\n" if ( $DEBUG > 2 );
|
_debug( $DEBUG > 2, Dumper( $feed ) );
|
||||||
storeFeed( $feed, $uridata );
|
storeFeed( $feed, $uridata );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1372,7 +1439,7 @@ sub findFeed {
|
|||||||
sub reportFeed {
|
sub reportFeed {
|
||||||
my ($feed, $fh) = @_;
|
my ($feed, $fh) = @_;
|
||||||
|
|
||||||
my $lwidth = 12;
|
my $lwidth = 15;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Hash for converting database keys to labels for the report and arrays
|
# Hash for converting database keys to labels for the report and arrays
|
||||||
@ -1397,6 +1464,7 @@ sub reportFeed {
|
|||||||
'ep_title' => 'Title',
|
'ep_title' => 'Title',
|
||||||
'ep_urls_id' => 'URL key',
|
'ep_urls_id' => 'URL key',
|
||||||
'urls_author' => 'Author',
|
'urls_author' => 'Author',
|
||||||
|
'urls_check_type' => 'Check type',
|
||||||
'urls_content_type' => 'Content type',
|
'urls_content_type' => 'Content type',
|
||||||
'urls_copyright' => 'Copyright',
|
'urls_copyright' => 'Copyright',
|
||||||
'urls_description' => 'Description',
|
'urls_description' => 'Description',
|
||||||
@ -1411,6 +1479,7 @@ sub reportFeed {
|
|||||||
'urls_last_update' => 'Last updated',
|
'urls_last_update' => 'Last updated',
|
||||||
'urls_link' => 'Link',
|
'urls_link' => 'Link',
|
||||||
'urls_modified' => 'Modified on',
|
'urls_modified' => 'Modified on',
|
||||||
|
'urls_reason_accepted' => 'Reason accepted',
|
||||||
'urls_title' => 'Title',
|
'urls_title' => 'Title',
|
||||||
'urls_url' => 'Feed URL',
|
'urls_url' => 'Feed URL',
|
||||||
'urls_urltype' => 'URL type',
|
'urls_urltype' => 'URL type',
|
||||||
@ -1426,6 +1495,8 @@ sub reportFeed {
|
|||||||
'urls_author',
|
'urls_author',
|
||||||
'urls_content_type',
|
'urls_content_type',
|
||||||
'urls_copyright',
|
'urls_copyright',
|
||||||
|
'urls_check_type',
|
||||||
|
'urls_reason_accepted',
|
||||||
'urls_description',
|
'urls_description',
|
||||||
'urls_dns',
|
'urls_dns',
|
||||||
'urls_generator',
|
'urls_generator',
|
||||||
@ -1577,6 +1648,7 @@ sub dbSearch {
|
|||||||
# PURPOSE: To perform a non-SELECT query
|
# PURPOSE: To perform a non-SELECT query
|
||||||
# PARAMETERS: $dbh database handle
|
# PARAMETERS: $dbh database handle
|
||||||
# $sql SQL expression to use
|
# $sql SQL expression to use
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# @args arguments for the 'execute'
|
# @args arguments for the 'execute'
|
||||||
# RETURNS: True (1) if the query succeeded, otherwise false (0).
|
# RETURNS: True (1) if the query succeeded, otherwise false (0).
|
||||||
# DESCRIPTION: Uses 'prepare_cached' to allow repeated calls with the same
|
# DESCRIPTION: Uses 'prepare_cached' to allow repeated calls with the same
|
||||||
@ -1587,10 +1659,15 @@ sub dbSearch {
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub execSQL {
|
sub execSQL {
|
||||||
my ( $dbh, $sql, @args ) = @_;
|
my ( $dbh, $sql, $dry_run, @args ) = @_;
|
||||||
|
|
||||||
my ( $sth1, $rv );
|
my ( $sth1, $rv );
|
||||||
|
|
||||||
|
if ($dry_run) {
|
||||||
|
emit($silent,"Dry-run: Would have run SQL '$sql'\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$sth1 = $dbh->prepare_cached($sql);
|
$sth1 = $dbh->prepare_cached($sql);
|
||||||
try {
|
try {
|
||||||
$rv = $sth1->execute(@args);
|
$rv = $sth1->execute(@args);
|
||||||
@ -1792,12 +1869,16 @@ sub checkContentType {
|
|||||||
my ( $uri, $uridata, $headers, $children, $log ) = @_;
|
my ( $uri, $uridata, $headers, $children, $log ) = @_;
|
||||||
|
|
||||||
my @feeds;
|
my @feeds;
|
||||||
|
my $content;
|
||||||
|
|
||||||
$uridata->{HTTP_STATUS} = 'Unknown';
|
$uridata->{HTTP_STATUS} = 'Unknown';
|
||||||
|
|
||||||
my $browser = LWP::UserAgent->new or return 0;
|
my $browser = LWP::UserAgent->new or return 0;
|
||||||
|
$browser->timeout(10);
|
||||||
|
$browser->agent("$PROG/$VERSION");
|
||||||
|
|
||||||
my $response = $browser->head( $uri->as_string, %{$headers} )
|
#my $response = $browser->head( $uri->as_string, %{$headers} )
|
||||||
|
my $response = $browser->get( $uri->as_string, %{$headers} )
|
||||||
or return 0;
|
or return 0;
|
||||||
|
|
||||||
$uridata->{HTTP_STATUS} = $response->status_line;
|
$uridata->{HTTP_STATUS} = $response->status_line;
|
||||||
@ -1830,15 +1911,25 @@ sub checkContentType {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#
|
#
|
||||||
# This HTML and we found 'child' feeds of some kind
|
# This is HTML and we found 'child' feeds of some kind
|
||||||
#
|
#
|
||||||
emit( $silent, "Found ", scalar(@feeds),
|
emit( $silent, "Found ", scalar(@feeds),
|
||||||
" feeds within this HTML page\n" );
|
" feeds within this HTML page\n" );
|
||||||
print Dumper( \@feeds ), "\n" if $DEBUG > 0;
|
_debug( $DEBUG > 0, Dumper( \@feeds ) );
|
||||||
push(@{$children}, @feeds);
|
push(@{$children}, @feeds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# TODO: Get the title for an HTML page by parsing the source
|
||||||
|
#
|
||||||
|
if ( $uridata->{TYPE} eq 'HTML' ) {
|
||||||
|
unless ($uridata->{TITLE}) {
|
||||||
|
$content = $response->decoded_content;
|
||||||
|
$uridata->{TITLE} = getHTMLTitle($uri->as_string, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$log->info( "URL content classified as: ", $uridata->{TYPE} );
|
$log->info( "URL content classified as: ", $uridata->{TYPE} );
|
||||||
emit( $silent, "URL content classified as: ", $uridata->{TYPE}, "\n" );
|
emit( $silent, "URL content classified as: ", $uridata->{TYPE}, "\n" );
|
||||||
return 1;
|
return 1;
|
||||||
@ -1849,6 +1940,41 @@ sub checkContentType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#=== FUNCTION ================================================================
|
||||||
|
# NAME: getURL
|
||||||
|
# PURPOSE: Download the contents of an URL
|
||||||
|
# PARAMETERS: $url URL of the page to download
|
||||||
|
# RETURNS: String representation of the contents or undef if the
|
||||||
|
# download failed.
|
||||||
|
# DESCRIPTION: Issues a GET on the URL. If successful the contents are
|
||||||
|
# decoded and returned, otherwise undef is returned.
|
||||||
|
# THROWS: No exceptions
|
||||||
|
# COMMENTS: None
|
||||||
|
# SEE ALSO:
|
||||||
|
#===============================================================================
|
||||||
|
sub getURL {
|
||||||
|
my ($url) = @_;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Use LWP::UserAgent to get the feed and handle errors
|
||||||
|
#
|
||||||
|
my $ua = LWP::UserAgent->new;
|
||||||
|
$ua->timeout(10);
|
||||||
|
$ua->agent("$PROG/$VERSION");
|
||||||
|
my $response = $ua->get($url);
|
||||||
|
|
||||||
|
my $content;
|
||||||
|
if ( $response->is_success ) {
|
||||||
|
$content = $response->decoded_content;
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
warn "Failed to get $url\n";
|
||||||
|
warn $response->status_line, "\n";
|
||||||
|
return; # undef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
# NAME: getFeed
|
# NAME: getFeed
|
||||||
# PURPOSE: Download the contents of a feed URL
|
# PURPOSE: Download the contents of a feed URL
|
||||||
@ -1885,6 +2011,98 @@ sub getFeed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#=== FUNCTION ================================================================
|
||||||
|
# NAME: start_handler
|
||||||
|
# PURPOSE: HTTP::Parser handler for <title> events
|
||||||
|
# PARAMETERS: <first> the name of the tag found
|
||||||
|
# <second> the object being processed
|
||||||
|
# RETURNS: Nothing (ignored anyway)
|
||||||
|
# DESCRIPTION:
|
||||||
|
# THROWS: No exceptions
|
||||||
|
# COMMENTS: None
|
||||||
|
# SEE ALSO: N/A
|
||||||
|
#===============================================================================
|
||||||
|
#sub start_handler {
|
||||||
|
#
|
||||||
|
# #
|
||||||
|
# # Ignore any tags which are not 'title'
|
||||||
|
# #
|
||||||
|
# return if shift ne "title";
|
||||||
|
#
|
||||||
|
# #
|
||||||
|
# # Define more handlers if we have a title. One to collect the title string
|
||||||
|
# # and the other to abort the parse on encountering the end of the title.
|
||||||
|
# #
|
||||||
|
# my $self = shift;
|
||||||
|
# $self->handler(text => sub { $main::html_title = shift }, "dtext");
|
||||||
|
# $self->handler(
|
||||||
|
# end => sub {
|
||||||
|
# shift->eof if shift eq "title";
|
||||||
|
# },
|
||||||
|
# "tagname,self"
|
||||||
|
# );
|
||||||
|
#}
|
||||||
|
|
||||||
|
#=== FUNCTION ================================================================
|
||||||
|
# NAME: getHTMLTitle
|
||||||
|
# PURPOSE: Parse an HTML page to get data. At the moment this is just the
|
||||||
|
# title in the header section.
|
||||||
|
# PARAMETERS: $url URL of the page; only used for messages and as
|
||||||
|
# a fallback title.
|
||||||
|
# $content Decoded content of the HTML page
|
||||||
|
# RETURNS: The title, if there is one, otherwise the URL
|
||||||
|
# DESCRIPTION:
|
||||||
|
# THROWS: No exceptions
|
||||||
|
# COMMENTS: None
|
||||||
|
# SEE ALSO: N/A
|
||||||
|
#===============================================================================
|
||||||
|
sub getHTMLTitle {
|
||||||
|
my ($url, $content) = @_;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Is this effectively a local subroutine?
|
||||||
|
#
|
||||||
|
my $start_handler = sub {
|
||||||
|
#
|
||||||
|
# Ignore any tags which are not 'title'
|
||||||
|
#
|
||||||
|
return if shift ne "title";
|
||||||
|
|
||||||
|
#
|
||||||
|
# Define more handlers if we have a title. One to collect the title string
|
||||||
|
# and the other to abort the parse on encountering the end of the title.
|
||||||
|
#
|
||||||
|
my $self = shift;
|
||||||
|
$self->handler(text => sub { $main::html_title = shift }, "dtext");
|
||||||
|
$self->handler(
|
||||||
|
end => sub {
|
||||||
|
shift->eof if shift eq "title";
|
||||||
|
},
|
||||||
|
"tagname,self"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create the HTML::Parser object
|
||||||
|
#
|
||||||
|
my $p = HTML::Parser->new(api_version => 3);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Define a 'start' handler. When called with 'title' as the 'tagname' it
|
||||||
|
# creates a 'text' event handler to print the text and an 'end' handler to
|
||||||
|
# quit when the closing '</title' tag is found.
|
||||||
|
#
|
||||||
|
#$p->handler(start => \&start_handler, "tagname,self");
|
||||||
|
$p->handler(start => $start_handler, "tagname,self");
|
||||||
|
|
||||||
|
#
|
||||||
|
# Invoke the parser on the string containing the returned HTML.
|
||||||
|
#
|
||||||
|
$p->parse($content);
|
||||||
|
|
||||||
|
return $main::html_title // $url;
|
||||||
|
}
|
||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
# NAME: parseFeed
|
# NAME: parseFeed
|
||||||
# PURPOSE: Parse a podcast feed that has already been downloaded
|
# PURPOSE: Parse a podcast feed that has already been downloaded
|
||||||
@ -2014,7 +2232,7 @@ sub storeFeed {
|
|||||||
sub checkCopyright {
|
sub checkCopyright {
|
||||||
my ($checkmode, $uridata) = @_;
|
my ($checkmode, $uridata) = @_;
|
||||||
|
|
||||||
my ( $copyright, $re, $decision );
|
my ( $copyright, $re, $decision, $reason );
|
||||||
$LOG->info("Checking copyright of feed (mode: $checkmode)");
|
$LOG->info("Checking copyright of feed (mode: $checkmode)");
|
||||||
|
|
||||||
if ( $checkmode eq 'manual' ) {
|
if ( $checkmode eq 'manual' ) {
|
||||||
@ -2040,14 +2258,36 @@ sub checkCopyright {
|
|||||||
warn "Problem processing copyright decision: $_";
|
warn "Problem processing copyright decision: $_";
|
||||||
$decision = 0;
|
$decision = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ($decision) {
|
||||||
|
#
|
||||||
|
# If accepted we want a reason for this manual check
|
||||||
|
#
|
||||||
|
try {
|
||||||
|
$reason = prompt(
|
||||||
|
-in => *STDIN,
|
||||||
|
-out => *STDERR,
|
||||||
|
-prompt => 'Please give a reason for this decision:',
|
||||||
|
-style => 'bold red underlined',
|
||||||
|
-default => 'No reason given'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
warn "Problem processing reason for copyright decision: $_";
|
||||||
|
$reason = 'Error while processing the reason';
|
||||||
|
};
|
||||||
|
|
||||||
|
$uridata->{REASON_ACCEPTED} = $reason;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#
|
#
|
||||||
# Careful. Un-escaped spaces are ignored
|
# Automatic mode.
|
||||||
|
# Careful. Un-escaped spaces are ignored in the regex
|
||||||
#
|
#
|
||||||
$re = qr{(
|
$re = qr{(
|
||||||
CC|
|
\bCC\b|
|
||||||
Creative\ Commons|
|
\bCreative\ Commons\b|
|
||||||
creativecommons.org|
|
creativecommons.org|
|
||||||
Attribution.NonCommercial.No.?Derivatives?
|
Attribution.NonCommercial.No.?Derivatives?
|
||||||
)}xmi;
|
)}xmi;
|
||||||
@ -2106,9 +2346,10 @@ sub parseRSS {
|
|||||||
# $uridata hashref containing data for the current URI
|
# $uridata hashref containing data for the current URI
|
||||||
# $keymap hashref containing a map of key names to
|
# $keymap hashref containing a map of key names to
|
||||||
# database field names
|
# database field names
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# RETURNS: True (1) if the insert succeeded, false (0) otherwise
|
# RETURNS: True (1) if the insert succeeded, false (0) otherwise
|
||||||
# DESCRIPTION: The hash keys are defined as an array to make it easy to slice
|
# DESCRIPTION: The hash keys are defined as an array to make it easy to slice
|
||||||
# the hash and the SQL is defined internally using the size of
|
# the hash, and the SQL is defined internally using the size of
|
||||||
# the key array as a guide to the number of '?' placeholders.
|
# the key array as a guide to the number of '?' placeholders.
|
||||||
# These are passed to execSQL to do the work.
|
# These are passed to execSQL to do the work.
|
||||||
# THROWS: No exceptions
|
# THROWS: No exceptions
|
||||||
@ -2116,7 +2357,7 @@ sub parseRSS {
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub addURI {
|
sub addURI {
|
||||||
my ( $dbh, $uridata, $keymap ) = @_;
|
my ( $dbh, $uridata, $keymap, $dry_run ) = @_;
|
||||||
|
|
||||||
my @keys = (
|
my @keys = (
|
||||||
'URI', 'DNS',
|
'URI', 'DNS',
|
||||||
@ -2126,6 +2367,7 @@ sub addURI {
|
|||||||
'DESCRIPTION', 'AUTHOR',
|
'DESCRIPTION', 'AUTHOR',
|
||||||
'MODIFIED', 'LINK',
|
'MODIFIED', 'LINK',
|
||||||
'IMAGE', 'COPYRIGHT',
|
'IMAGE', 'COPYRIGHT',
|
||||||
|
'CHECKTYPE', 'REASON_ACCEPTED',
|
||||||
'GENERATOR', 'LANGUAGE',
|
'GENERATOR', 'LANGUAGE',
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2135,9 +2377,9 @@ sub addURI {
|
|||||||
. 'VALUES('
|
. 'VALUES('
|
||||||
. join( ',', ('?') x scalar(@keys) ) . ')';
|
. join( ',', ('?') x scalar(@keys) ) . ')';
|
||||||
|
|
||||||
print "addURI query: $sql\n" if $DEBUG > 0;
|
_debug( $DEBUG > 0, "addURI query: $sql");
|
||||||
|
|
||||||
return execSQL( $dbh, $sql, @{$uridata}{@keys} );
|
return execSQL( $dbh, $sql, $dry_run, @{$uridata}{@keys} );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2206,6 +2448,7 @@ sub extractEnclosures {
|
|||||||
# $uridata hashref containing data for the current URI
|
# $uridata hashref containing data for the current URI
|
||||||
# including an arrayref of hashrefs of episode
|
# including an arrayref of hashrefs of episode
|
||||||
# data
|
# data
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# RETURNS: True (1) if all the inserts succeeded, false (0) otherwise
|
# RETURNS: True (1) if all the inserts succeeded, false (0) otherwise
|
||||||
# DESCRIPTION: The SQL is defined internally and the hash keys are defined as
|
# DESCRIPTION: The SQL is defined internally and the hash keys are defined as
|
||||||
# an array to make it easy to slice the hash. The enclosures (or
|
# an array to make it easy to slice the hash. The enclosures (or
|
||||||
@ -2219,7 +2462,7 @@ sub extractEnclosures {
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub addEnclosures {
|
sub addEnclosures {
|
||||||
my ( $dbh, $uridata ) = @_;
|
my ( $dbh, $uridata, $dry_run ) = @_;
|
||||||
|
|
||||||
my $sql = q{INSERT INTO episodes
|
my $sql = q{INSERT INTO episodes
|
||||||
(urls_id, link, enclosure, title, author, category, source, ep_id,
|
(urls_id, link, enclosure, title, author, category, source, ep_id,
|
||||||
@ -2233,7 +2476,7 @@ sub addEnclosures {
|
|||||||
my $successes = 0;
|
my $successes = 0;
|
||||||
|
|
||||||
foreach my $enc ( @{ $uridata->{ENCLOSURES} } ) {
|
foreach my $enc ( @{ $uridata->{ENCLOSURES} } ) {
|
||||||
if ( execSQL( $dbh, $sql, $uridata->{URI_ID}, @{$enc}{@keys} ) ) {
|
if ( execSQL( $dbh, $sql, $dry_run, $uridata->{URI_ID}, @{$enc}{@keys} ) ) {
|
||||||
$successes++;
|
$successes++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2253,6 +2496,7 @@ sub addEnclosures {
|
|||||||
# data
|
# data
|
||||||
# $keymap hashref containing a map of key names to
|
# $keymap hashref containing a map of key names to
|
||||||
# database field names
|
# database field names
|
||||||
|
# $dry_run Boolean, set if in dry-run mode
|
||||||
# RETURNS: The number of changes made
|
# RETURNS: The number of changes made
|
||||||
# DESCRIPTION:
|
# DESCRIPTION:
|
||||||
# THROWS: No exceptions
|
# THROWS: No exceptions
|
||||||
@ -2260,8 +2504,9 @@ sub addEnclosures {
|
|||||||
# SEE ALSO: N/A
|
# SEE ALSO: N/A
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sub updateURI {
|
sub updateURI {
|
||||||
my ( $dbh, $uridata, $keymap ) = @_;
|
my ( $dbh, $uridata, $keymap, $dry_run ) = @_;
|
||||||
|
|
||||||
|
# TODO: dry-run mode not implemented here yet
|
||||||
my ( $sql1, $sth1, $rv1, $h1 );
|
my ( $sql1, $sth1, $rv1, $h1 );
|
||||||
my ( %fieldvals, %where );
|
my ( %fieldvals, %where );
|
||||||
my ( $diffs, $updates ) = ( 0, 0 );
|
my ( $diffs, $updates ) = ( 0, 0 );
|
||||||
@ -2353,6 +2598,7 @@ sub updateURI {
|
|||||||
sub updateEnclosures {
|
sub updateEnclosures {
|
||||||
my ( $dbh, $uridata ) = @_;
|
my ( $dbh, $uridata ) = @_;
|
||||||
|
|
||||||
|
# TODO: This doesn't acttually update annything!
|
||||||
my ( $sql1, $sth1, $rv1, $h1 );
|
my ( $sql1, $sth1, $rv1, $h1 );
|
||||||
my ( %fieldvals, %where );
|
my ( %fieldvals, %where );
|
||||||
my ( $diffs, $updates ) = ( 0, 0 );
|
my ( $diffs, $updates ) = ( 0, 0 );
|
||||||
@ -2372,6 +2618,40 @@ sub updateEnclosures {
|
|||||||
$h1 = $sth1->fetchrow_hashref;
|
$h1 = $sth1->fetchrow_hashref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#=== FUNCTION ================================================================
|
||||||
|
# NAME: optionalFile
|
||||||
|
# PURPOSE: Process an option of the form '-opt:s' where 's' is an
|
||||||
|
# optional filename.
|
||||||
|
# PARAMETERS: $optionName Name of option
|
||||||
|
# $optionValue Value of option (assumed to be blank of
|
||||||
|
# a filename)
|
||||||
|
# RETURNS: A boolean: 1 (true) if there is a filename, 0 (false) if the
|
||||||
|
# name has been omitted.
|
||||||
|
# DESCRIPTION: The $optionValue will be blank or a filename. If the latter
|
||||||
|
# then the existence of the file and its readbility are checked
|
||||||
|
# and the script dies if either test fails.
|
||||||
|
# THROWS: No exceptions
|
||||||
|
# COMMENTS: None
|
||||||
|
# SEE ALSO: N/A
|
||||||
|
#===============================================================================
|
||||||
|
sub optionalFile {
|
||||||
|
my ( $optionName, $optionValue ) = @_;
|
||||||
|
|
||||||
|
if (defined($optionValue)) {
|
||||||
|
if ( $optionValue =~ /^$/ ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "File in '-$optionName=$optionValue' does not exist\n"
|
||||||
|
unless -e $optionValue;
|
||||||
|
die "File in '-$optionName=$optionValue' is not readable\n"
|
||||||
|
unless -r $optionValue;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
# NAME: equal
|
# NAME: equal
|
||||||
# PURPOSE: Compare two strings even if undefined
|
# PURPOSE: Compare two strings even if undefined
|
||||||
@ -2504,6 +2784,32 @@ sub emit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#=== FUNCTION ================================================================
|
||||||
|
# NAME: _debug
|
||||||
|
# PURPOSE: Prints debug reports
|
||||||
|
# PARAMETERS: $active Boolean: 1 for print, 0 for no print
|
||||||
|
# $messages... Arbitrary list of messages to print
|
||||||
|
# RETURNS: Nothing
|
||||||
|
# DESCRIPTION: Outputs messages if $active is true. It removes any trailing
|
||||||
|
# newline from each one and then adds one in the 'print' to the
|
||||||
|
# caller doesn't have to bother. Prepends each message with 'D>'
|
||||||
|
# to show it's a debug message.
|
||||||
|
# THROWS: No exceptions
|
||||||
|
# COMMENTS: Differs from other functions of the same name
|
||||||
|
# SEE ALSO: N/A
|
||||||
|
#===============================================================================
|
||||||
|
sub _debug {
|
||||||
|
my $active = shift;
|
||||||
|
|
||||||
|
my $message;
|
||||||
|
return unless $active;
|
||||||
|
|
||||||
|
while ($message = shift) {
|
||||||
|
chomp($message);
|
||||||
|
print STDERR "D> $message\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
# NAME: Options
|
# NAME: Options
|
||||||
# PURPOSE: Processes command-line options
|
# PURPOSE: Processes command-line options
|
||||||
@ -2518,10 +2824,11 @@ sub Options {
|
|||||||
my ($optref) = @_;
|
my ($optref) = @_;
|
||||||
|
|
||||||
my @options = (
|
my @options = (
|
||||||
"help", "manpage", "debug=i", "silent!",
|
"help", "manpage", "debug=i", "dry-run!",
|
||||||
"load=s", "delete=s", "scan!", "report:s",
|
"silent!", "load:s", "delete:s", "scan!",
|
||||||
"check:s", "json:s", "opml:s", "config=s",
|
"report:s", "html!", "check:s", "json:s",
|
||||||
"out=s", "rejects:s", "template:s",
|
"opml:s", "config=s", "out=s", "rejects:s",
|
||||||
|
"template:s",
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( !GetOptions( $optref, @options ) ) {
|
if ( !GetOptions( $optref, @options ) ) {
|
||||||
|
BIN
feedWatcher.db
BIN
feedWatcher.db
Binary file not shown.
@ -198,6 +198,14 @@
|
|||||||
<dl>
|
<dl>
|
||||||
|
|
||||||
|
|
||||||
|
<dt><a href="https://2.5admins.com">2.5 Admins</a> (<a href="https://2.5admins.com/feed/podcast">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
|
<dd>2.5 Admins is a podcast featuring two sysadmins called Allan Jude and Jim Salter, and a producer/editor who can just about configure a Samba share called Joe Ressington. Every two weeks we get together, talk about recent tech news, and answer some of your admin-related questions.</dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="https://www.adminadminpodcast.co.uk">Admin Admin Podcast</a> (<a href="http://feeds.feedburner.com/TheAdminAdminPodcast">feed</a>)</dt>
|
<dt><a href="https://www.adminadminpodcast.co.uk">Admin Admin Podcast</a> (<a href="http://feeds.feedburner.com/TheAdminAdminPodcast">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
@ -558,6 +566,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt><a href="https://www.linuxuserspace.show">Linux User Space</a> (<a href="https://www.linuxuserspace.show/rss">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
|
<dd>How did your favorite Linux distribution get its start? Join us and find out! Linux User Space is hosted by Leo and Dan, and every two weeks we deep dive into the history of Linux distributions and the things that matter to us. Episodes drop every other Monday.</dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="https://www.linuxatwork.org">Linux at Work</a> (<a href="http://feeds.podtrac.com/mBdfP0QTX0iY">feed</a>)</dt>
|
<dt><a href="https://www.linuxatwork.org">Linux at Work</a> (<a href="http://feeds.podtrac.com/mBdfP0QTX0iY">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
@ -702,6 +718,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt><a href="http://www.scienceforthepeople.ca/">Science for the People</a> (<a href="http://feeds.feedburner.com/SkepticallySpeaking">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
|
<dd>Science for the People is a long-format interview podcast that explores the connections between science, popular culture, history, and public policy, to help listeners understand the evidence and arguments behind what's in the news and on the shelves. Our hosts sit down with science researchers, writers, authors, journalists, and experts to discuss science from the past, the science that affects our lives today, and how science might change our future.</dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="https://twit.tv/shows/security-now">Security Now (Audio)</a> (<a href="http://feeds.twit.tv/sn.xml">feed</a>)</dt>
|
<dt><a href="https://twit.tv/shows/security-now">Security Now (Audio)</a> (<a href="http://feeds.twit.tv/sn.xml">feed</a>)</dt>
|
||||||
|
|
||||||
|
|
||||||
|
480
feedWatcher.json
480
feedWatcher.json
File diff suppressed because it is too large
Load Diff
195
feedWatcher.mkd
195
feedWatcher.mkd
@ -2,459 +2,474 @@
|
|||||||
|
|
||||||
### The finest selection of Free Culture Podcasts spanning the genres of Discussion, Drama, Education, Music, and beyond.
|
### The finest selection of Free Culture Podcasts spanning the genres of Discussion, Drama, Education, Music, and beyond.
|
||||||
|
|
||||||
|
- **2.5 Admins**
|
||||||
|
- Website: https://2.5admins.com
|
||||||
|
- Feed: https://2.5admins.com/feed/podcast
|
||||||
|
- Copyright:
|
||||||
|
|
||||||
- **Admin Admin Podcast**
|
- **Admin Admin Podcast**
|
||||||
- Website: https://www.adminadminpodcast.co.uk
|
- Website: https://www.adminadminpodcast.co.uk
|
||||||
- Feed: http://feeds.feedburner.com/TheAdminAdminPodcast
|
- Feed: http://feeds.feedburner.com/TheAdminAdminPodcast
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **All About Android (Audio)**
|
- **All About Android (Audio)**
|
||||||
- Website: https://twit.tv/shows/all-about-android
|
- Website: https://twit.tv/shows/all-about-android
|
||||||
- Feed: http://feeds.twit.tv/aaa.xml
|
- Feed: http://feeds.twit.tv/aaa.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **All In IT Radio (ogg)**
|
- **All In IT Radio (ogg)**
|
||||||
- Website: http://aiit.se/radio/
|
- Website: http://aiit.se/radio/
|
||||||
- Feed: http://feeds.aiit.se/allinit-radio-ogg
|
- Feed: http://feeds.aiit.se/allinit-radio-ogg
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **AmateurLogic.TV**
|
- **AmateurLogic.TV**
|
||||||
- Website: http://www.amateurlogic.tv
|
- Website: http://www.amateurlogic.tv
|
||||||
- Feed: http://amateurlogic.tv/transmitter/feeds/ipod.xml
|
- Feed: http://amateurlogic.tv/transmitter/feeds/ipod.xml
|
||||||
- Licence: Creative Commons
|
- Copyright: Creative Commons
|
||||||
|
|
||||||
- **Ask Noah Show**
|
- **Ask Noah Show**
|
||||||
- Website: https://podcast.asknoahshow.com
|
- Website: https://podcast.asknoahshow.com
|
||||||
- Feed: https://feeds.fireside.fm/asknoah/rss
|
- Feed: https://feeds.fireside.fm/asknoah/rss
|
||||||
- Licence: © 2023 CC-BY-ND
|
- Copyright: © 2023 CC-BY-ND
|
||||||
|
|
||||||
- **CCHits.net**
|
- **CCHits.net**
|
||||||
- Website: https://cchits.net/daily
|
- Website: https://cchits.net/daily
|
||||||
- Feed: https://cchits.net/daily/rss
|
- Feed: https://cchits.net/daily/rss
|
||||||
- Licence: The content created by this site is generated by a script which is licensed under the Affero General Public License version 3 (AGPL3). The generated content is released under a Creative Commons By-Attribution License.
|
- Copyright: The content created by this site is generated by a script which is licensed under the Affero General Public License version 3 (AGPL3). The generated content is released under a Creative Commons By-Attribution License.
|
||||||
|
|
||||||
- **CCJam**
|
- **CCJam**
|
||||||
- Website: https://ccjam.otherside.network/
|
- Website: https://ccjam.otherside.network/
|
||||||
- Feed: https://ccjam.otherside.network/feed/podcast/
|
- Feed: https://ccjam.otherside.network/feed/podcast/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Destination Linux**
|
- **Destination Linux**
|
||||||
- Website: https://destinationlinux.org
|
- Website: https://destinationlinux.org
|
||||||
- Feed: http://destinationlinux.org/feed/mp3/
|
- Feed: http://destinationlinux.org/feed/mp3/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Edict Zero**
|
- **Edict Zero**
|
||||||
- Website: https://edictzero.com
|
- Website: https://edictzero.com
|
||||||
- Feed: https://edictzero.wordpress.com/feed/
|
- Feed: https://edictzero.wordpress.com/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **English – Wikipediapodden**
|
- **English – Wikipediapodden**
|
||||||
- Website: http://wikipediapodden.se
|
- Website: http://wikipediapodden.se
|
||||||
- Feed: http://wikipediapodden.se/tag/english/feed/
|
- Feed: http://wikipediapodden.se/tag/english/feed/
|
||||||
- Licence: CC BY-SA 4.0 Wikipediapodden
|
- Copyright: CC BY-SA 4.0 Wikipediapodden
|
||||||
|
|
||||||
- **Escape Pod**
|
- **Escape Pod**
|
||||||
- Website: https://escapepod.org
|
- Website: https://escapepod.org
|
||||||
- Feed: http://escapepod.org/feed/
|
- Feed: http://escapepod.org/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Expedition Sasquatch**
|
- **Expedition Sasquatch**
|
||||||
- Website: https://ExpeditionSasquatch.org
|
- Website: https://ExpeditionSasquatch.org
|
||||||
- Feed: https://expeditionsasquatch.org/episodes.mp3.rss
|
- Feed: https://expeditionsasquatch.org/episodes.mp3.rss
|
||||||
- Licence: CC BY SA 4.0
|
- Copyright: CC BY SA 4.0
|
||||||
|
|
||||||
- **FLOSS Weekly (Audio)**
|
- **FLOSS Weekly (Audio)**
|
||||||
- Website: https://twit.tv/shows/floss-weekly
|
- Website: https://twit.tv/shows/floss-weekly
|
||||||
- Feed: http://leoville.tv/podcasts/floss.xml
|
- Feed: http://leoville.tv/podcasts/floss.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **FLOSS Weekly (Audio)**
|
- **FLOSS Weekly (Audio)**
|
||||||
- Website: https://twit.tv/shows/floss-weekly
|
- Website: https://twit.tv/shows/floss-weekly
|
||||||
- Feed: http://feeds.twit.tv/floss.xml
|
- Feed: http://feeds.twit.tv/floss.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **FOSS and Crafts**
|
- **FOSS and Crafts**
|
||||||
- Website: https://fossandcrafts.org
|
- Website: https://fossandcrafts.org
|
||||||
- Feed: https://fossandcrafts.org/rss-feed.rss
|
- Feed: https://fossandcrafts.org/rss-feed.rss
|
||||||
- Licence: Licensed under CC BY-SA 4.0 International
|
- Copyright: Licensed under CC BY-SA 4.0 International
|
||||||
|
|
||||||
- **FSFE Events**
|
- **FSFE Events**
|
||||||
- Website: https://fsfe.org/events/
|
- Website: https://fsfe.org/events/
|
||||||
- Feed: https://fsfe.org/events/events.en.rss
|
- Feed: https://fsfe.org/events/events.en.rss
|
||||||
- Licence: Copyright (c) Free Software Foundation Europe. Verbatim copying and distribution
|
- Copyright: Copyright (c) Free Software Foundation Europe. Verbatim copying and distribution
|
||||||
of this entire article is permitted in any medium, provided this
|
of this entire article is permitted in any medium, provided this
|
||||||
notice is preserved.
|
notice is preserved.
|
||||||
|
|
||||||
- **FSFE News**
|
- **FSFE News**
|
||||||
- Website: https://fsfe.org/news/
|
- Website: https://fsfe.org/news/
|
||||||
- Feed: https://fsfe.org/news/news.en.rss
|
- Feed: https://fsfe.org/news/news.en.rss
|
||||||
- Licence: Copyright (c) Free Software Foundation Europe. Verbatim copying and distribution
|
- Copyright: Copyright (c) Free Software Foundation Europe. Verbatim copying and distribution
|
||||||
of this entire article is permitted in any medium, provided this
|
of this entire article is permitted in any medium, provided this
|
||||||
notice is preserved.
|
notice is preserved.
|
||||||
|
|
||||||
- **Free as in Freedom**
|
- **Free as in Freedom**
|
||||||
- Website: http://faif.us/cast/
|
- Website: http://faif.us/cast/
|
||||||
- Feed: http://faif.us/feeds/cast-ogg/
|
- Feed: http://faif.us/feeds/cast-ogg/
|
||||||
- Licence: 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021, Free as in Freedom. Licensed under a Creative Commons Attribution-Share Alike 3.0 USA License.
|
- Copyright: 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021, Free as in Freedom. Licensed under a Creative Commons Attribution-Share Alike 3.0 USA License.
|
||||||
|
|
||||||
- **Free as in Freedom**
|
- **Free as in Freedom**
|
||||||
- Website: http://faif.us/cast/
|
- Website: http://faif.us/cast/
|
||||||
- Feed: http://faif.us/feeds/cast-mp3/
|
- Feed: http://faif.us/feeds/cast-mp3/
|
||||||
- Licence: 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021, Free as in Freedom. Licensed under a Creative Commons Attribution-Share Alike 3.0 USA License.
|
- Copyright: 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021, Free as in Freedom. Licensed under a Creative Commons Attribution-Share Alike 3.0 USA License.
|
||||||
|
|
||||||
- **GAMERadio**
|
- **GAMERadio**
|
||||||
- Website: http://www.hwhq.com/
|
- Website: http://www.hwhq.com/
|
||||||
- Feed: http://hwhq.com/rss.xml
|
- Feed: http://hwhq.com/rss.xml
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **GNU World Order Linux Cast**
|
- **GNU World Order Linux Cast**
|
||||||
- Website: http://www.gnuworldorder.info
|
- Website: http://www.gnuworldorder.info
|
||||||
- Feed: https://gnuworldorder.info/ogg.xml
|
- Feed: https://gnuworldorder.info/ogg.xml
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **GNU/Linux RTM**
|
- **GNU/Linux RTM**
|
||||||
- Website: http://gnulinuxrtm.blogspot.com/
|
- Website: http://gnulinuxrtm.blogspot.com/
|
||||||
- Feed: http://feeds.feedburner.com/GNULinuxRTM
|
- Feed: http://feeds.feedburner.com/GNULinuxRTM
|
||||||
- Licence: This work is licensed under Creative Commons Attribution 4.0
|
- Copyright: This work is licensed under Creative Commons Attribution 4.0
|
||||||
|
|
||||||
- **Geek Speak with Lyle Troxell**
|
- **Geek Speak with Lyle Troxell**
|
||||||
- Website: https://geekspeak.org/
|
- Website: https://geekspeak.org/
|
||||||
- Feed: https://geekspeak.org/episodes/rss.xml
|
- Feed: https://geekspeak.org/episodes/rss.xml
|
||||||
- Licence: Creative Commons Attribution 3.0 United States License
|
- Copyright: Creative Commons Attribution 3.0 United States License
|
||||||
|
|
||||||
- **GeekNights Mondays: Science Technology Computing**
|
- **GeekNights Mondays: Science Technology Computing**
|
||||||
- Website: http://frontrowcrew.com/geeknights/monday/
|
- Website: http://frontrowcrew.com/geeknights/monday/
|
||||||
- Feed: http://feeds.feedburner.com/GNSciTech
|
- Feed: http://feeds.feedburner.com/GNSciTech
|
||||||
- Licence: Creative Commons
|
- Copyright: Creative Commons
|
||||||
|
|
||||||
- **Going Linux**
|
- **Going Linux**
|
||||||
- Website: https://goinglinux.com
|
- Website: https://goinglinux.com
|
||||||
- Feed: http://goinglinux.com/oggpodcast.xml
|
- Feed: http://goinglinux.com/oggpodcast.xml
|
||||||
- Licence: Creative Commons Attribution 4.0 International License.
|
- Copyright: Creative Commons Attribution 4.0 International License.
|
||||||
|
|
||||||
- **Hacker Public Radio**
|
- **Hacker Public Radio**
|
||||||
- Website: http://hackerpublicradio.org/about.php
|
- Website: http://hackerpublicradio.org/about.php
|
||||||
- Feed: http://hackerpublicradio.org/hpr_ogg_rss.php
|
- Feed: http://hackerpublicradio.org/hpr_ogg_rss.php
|
||||||
- Licence: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License
|
- Copyright: Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License
|
||||||
|
|
||||||
- **How to Fix the Internet**
|
- **How to Fix the Internet**
|
||||||
- Website: https://www.eff.org/how-to-fix-the-internet-podcast
|
- Website: https://www.eff.org/how-to-fix-the-internet-podcast
|
||||||
- Feed: https://feeds.eff.org/howtofixtheinternet
|
- Feed: https://feeds.eff.org/howtofixtheinternet
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **International Open Podcast**
|
- **International Open Podcast**
|
||||||
- Website: http://internationalopenmagazine.org/category/podcast.html
|
- Website: http://internationalopenmagazine.org/category/podcast.html
|
||||||
- Feed: http://spielend-programmieren.at/intopenpodcast.xml
|
- Feed: http://spielend-programmieren.at/intopenpodcast.xml
|
||||||
- Licence: Copyright 2015 CC-BY-SA
|
- Copyright: Copyright 2015 CC-BY-SA
|
||||||
|
|
||||||
- **Internet Archive**
|
- **Internet Archive**
|
||||||
- Website: https://archive.org/
|
- Website: https://archive.org/
|
||||||
- Feed: http://feeds.feedburner.com/archive/Lqwl
|
- Feed: http://feeds.feedburner.com/archive/Lqwl
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Knightwise.com Audio Feed.**
|
- **Knightwise.com Audio Feed.**
|
||||||
- Website: https://knightwise.com
|
- Website: https://knightwise.com
|
||||||
- Feed: http://feeds.feedburner.com/knightcastpodcast
|
- Feed: http://feeds.feedburner.com/knightcastpodcast
|
||||||
- Licence: Creative commons apply ! Non commercial re-use is allowed.
|
- Copyright: Creative commons apply ! Non commercial re-use is allowed.
|
||||||
|
|
||||||
- **LQ Radio**
|
- **LQ Radio**
|
||||||
- Website: http://radio.linuxquestions.org
|
- Website: http://radio.linuxquestions.org
|
||||||
- Feed: http://feeds.feedburner.com/linuxquestions/LQRadioALL-ogg
|
- Feed: http://feeds.feedburner.com/linuxquestions/LQRadioALL-ogg
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **LaGER: GNU/Linux and Games/Entertainment Radio**
|
- **LaGER: GNU/Linux and Games/Entertainment Radio**
|
||||||
- Website: http://thelinuxlink.net/lager
|
- Website: http://thelinuxlink.net/lager
|
||||||
- Feed: http://feeds.feedburner.com/thelinuxlink/Paek
|
- Feed: http://feeds.feedburner.com/thelinuxlink/Paek
|
||||||
- Licence: Creative Commons License Some Rights Reserved
|
- Copyright: Creative Commons License Some Rights Reserved
|
||||||
|
|
||||||
- **Late Night Linux (Ogg)**
|
- **Late Night Linux (Ogg)**
|
||||||
- Website: https://latenightlinux.com
|
- Website: https://latenightlinux.com
|
||||||
- Feed: http://latenightlinux.com/feed/ogg
|
- Feed: http://latenightlinux.com/feed/ogg
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Libre Lounge**
|
- **Libre Lounge**
|
||||||
- Website: https://librelounge.org
|
- Website: https://librelounge.org
|
||||||
- Feed: https://librelounge.org/rss-feed.rss
|
- Feed: https://librelounge.org/rss-feed.rss
|
||||||
- Licence: Licensed under CC BY-SA 4.0 International
|
- Copyright: Licensed under CC BY-SA 4.0 International
|
||||||
|
|
||||||
- **Line Noise Podcast**
|
- **Line Noise Podcast**
|
||||||
- Website: https://www.eff.org/rss/podcast/mp3.xml
|
- Website: https://www.eff.org/rss/podcast/mp3.xml
|
||||||
- Feed: http://www.eff.org/rss/podcast/mp3.xml
|
- Feed: http://www.eff.org/rss/podcast/mp3.xml
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Linux After Dark**
|
- **Linux After Dark**
|
||||||
- Website: https://linuxafterdark.net
|
- Website: https://linuxafterdark.net
|
||||||
- Feed: https://linuxafterdark.net/feed/podcast
|
- Feed: https://linuxafterdark.net/feed/podcast
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Linux Downtime**
|
- **Linux Downtime**
|
||||||
- Website: https://linuxdowntime.com
|
- Website: https://linuxdowntime.com
|
||||||
- Feed: https://latenightlinux.com/feed/extra
|
- Feed: https://latenightlinux.com/feed/extra
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Linux Game Cast**
|
- **Linux Game Cast**
|
||||||
- Website: https://linuxgamecast.com
|
- Website: https://linuxgamecast.com
|
||||||
- Feed: https://linuxgamecast.com/feed/
|
- Feed: https://linuxgamecast.com/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Linux Game Cast**
|
- **Linux Game Cast**
|
||||||
- Website: https://linuxgamecast.com
|
- Website: https://linuxgamecast.com
|
||||||
- Feed: http://feeds.feedburner.com/LinuxgamecastWeeklyMp3
|
- Feed: http://feeds.feedburner.com/LinuxgamecastWeeklyMp3
|
||||||
- Licence: CC BY-SA LinuxGameCast LLP 2022
|
- Copyright: CC BY-SA LinuxGameCast LLP 2022
|
||||||
|
|
||||||
- **Linux In Da House MP3 Feed**
|
- **Linux In Da House MP3 Feed**
|
||||||
- Website: http://linuxindahouse.com
|
- Website: http://linuxindahouse.com
|
||||||
- Feed: http://linuxindahouse.com/linuxindahouse_mp3.rss
|
- Feed: http://linuxindahouse.com/linuxindahouse_mp3.rss
|
||||||
- Licence: Creative Commons License Some Rights Reserved
|
- Copyright: Creative Commons License Some Rights Reserved
|
||||||
|
|
||||||
- **Linux Inlaws**
|
- **Linux Inlaws**
|
||||||
- Website: https://linuxinlaws.eu
|
- Website: https://linuxinlaws.eu
|
||||||
- Feed: https://linuxinlaws.eu/inlaws_rss.xml
|
- Feed: https://linuxinlaws.eu/inlaws_rss.xml
|
||||||
- Licence: Linux Inlaws (c) 2020 CC-BY-SA
|
- Copyright: Linux Inlaws (c) 2020 CC-BY-SA
|
||||||
|
|
||||||
- **Linux Lads**
|
- **Linux Lads**
|
||||||
- Website: https://linuxlads.com
|
- Website: https://linuxlads.com
|
||||||
- Feed: https://linuxlads.com/feed_ogg.rss
|
- Feed: https://linuxlads.com/feed_ogg.rss
|
||||||
- Licence: Released under the Creative Commons Attribution-Share Alike 3.0 Unported Licence
|
- Copyright: Released under the Creative Commons Attribution-Share Alike 3.0 Unported Licence
|
||||||
|
|
||||||
- **Linux Outlaws**
|
- **Linux Outlaws**
|
||||||
- Website: http://sixgun.org
|
- Website: http://sixgun.org
|
||||||
- Feed: http://feeds.feedburner.com/linuxoutlaws
|
- Feed: http://feeds.feedburner.com/linuxoutlaws
|
||||||
- Licence: Copyright © 2007-2012 Sixgun Productions http://creativecommons.org/licenses/by-sa/3.0/
|
- Copyright: Copyright © 2007-2012 Sixgun Productions http://creativecommons.org/licenses/by-sa/3.0/
|
||||||
|
|
||||||
- **Linux Reality Podcast (MP3 Feed)**
|
- **Linux Reality Podcast (MP3 Feed)**
|
||||||
- Website: http://www.linuxreality.com
|
- Website: http://www.linuxreality.com
|
||||||
- Feed: http://feeds.feedburner.com/linuxreality
|
- Feed: http://feeds.feedburner.com/linuxreality
|
||||||
- Licence: Linux Reality is released under a Attribution-Noncommercial-No Derivative Works 3.0 United States licence.
|
- Copyright: Linux Reality is released under a Attribution-Noncommercial-No Derivative Works 3.0 United States licence.
|
||||||
|
|
||||||
- **Linux Trivia Podcast**
|
- **Linux Trivia Podcast**
|
||||||
- Website: http://setbit.org/lt.html
|
- Website: http://setbit.org/lt.html
|
||||||
- Feed: http://setbit.org/lt-ogg.xml
|
- Feed: http://setbit.org/lt-ogg.xml
|
||||||
- Licence: Creative Commons License Some Rights Reserved
|
- Copyright: Creative Commons License Some Rights Reserved
|
||||||
|
|
||||||
|
- **Linux User Space**
|
||||||
|
- Website: https://www.linuxuserspace.show
|
||||||
|
- Feed: https://www.linuxuserspace.show/rss
|
||||||
|
- Copyright: © 2023 Dan Simmons & Leo Chavez
|
||||||
|
|
||||||
- **Linux at Work**
|
- **Linux at Work**
|
||||||
- Website: https://www.linuxatwork.org
|
- Website: https://www.linuxatwork.org
|
||||||
- Feed: http://feeds.podtrac.com/mBdfP0QTX0iY
|
- Feed: http://feeds.podtrac.com/mBdfP0QTX0iY
|
||||||
- Licence: CC BY 4.0
|
- Copyright: CC BY 4.0
|
||||||
|
|
||||||
- **Linux in the Ham Shack**
|
- **Linux in the Ham Shack**
|
||||||
- Website: https://lhspodcast.info/category/podcast-mp3/
|
- Website: https://lhspodcast.info/category/podcast-mp3/
|
||||||
- Feed: http://lhspodcast.info/category/podcast-mp3/feed/
|
- Feed: http://lhspodcast.info/category/podcast-mp3/feed/
|
||||||
- Licence: CC-BY-NC-4.0
|
- Copyright: CC-BY-NC-4.0
|
||||||
|
|
||||||
- **Linux in the Ham Shack (OGG Feed)**
|
- **Linux in the Ham Shack (OGG Feed)**
|
||||||
- Website: https://lhspodcast.info/category/podcast-ogg/
|
- Website: https://lhspodcast.info/category/podcast-ogg/
|
||||||
- Feed: https://lhspodcast.info/category/podcast-ogg/feed/
|
- Feed: https://lhspodcast.info/category/podcast-ogg/feed/
|
||||||
- Licence: Attribution-NonCommercial-NoDerivatives 4.0 International
|
- Copyright: Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||||
|
|
||||||
- **Linuxlugcast**
|
- **Linuxlugcast**
|
||||||
- Website: https://linuxlugcast.com
|
- Website: https://linuxlugcast.com
|
||||||
- Feed: http://feeds.feedburner.com/linuxlugcast-ogg
|
- Feed: http://feeds.feedburner.com/linuxlugcast-ogg
|
||||||
- Licence: Creative commons Attribution 4.0 International (CC BY 4.0)
|
- Copyright: Creative commons Attribution 4.0 International (CC BY 4.0)
|
||||||
|
|
||||||
- **Linuxlugcast**
|
- **Linuxlugcast**
|
||||||
- Website: https://linuxlugcast.com
|
- Website: https://linuxlugcast.com
|
||||||
- Feed: http://feeds.feedburner.com/linuxlugcast/dBDY
|
- Feed: http://feeds.feedburner.com/linuxlugcast/dBDY
|
||||||
- Licence: Creative commons Attribution 4.0 International (CC BY 4.0)
|
- Copyright: Creative commons Attribution 4.0 International (CC BY 4.0)
|
||||||
|
|
||||||
- **LugRadio (high-quality ogg)**
|
- **LugRadio (high-quality ogg)**
|
||||||
- Website: http://www.lugradio.org/episodes.ogg.rss
|
- Website: http://www.lugradio.org/episodes.ogg.rss
|
||||||
- Feed: http://www.lugradio.org/episodes.ogg.rss
|
- Feed: http://www.lugradio.org/episodes.ogg.rss
|
||||||
- Licence: LUGRadio is released under a Creative Commons Attribution
|
- Copyright: LUGRadio is released under a Creative Commons Attribution
|
||||||
NonCommercial NoDerivs licence.
|
NonCommercial NoDerivs licence.
|
||||||
|
|
||||||
- **Makers Corner, with Nate and Yannick**
|
- **Makers Corner, with Nate and Yannick**
|
||||||
- Website: https://makerscorner.tech
|
- Website: https://makerscorner.tech
|
||||||
- Feed: https://makerscorner.tech/feed/podcast/
|
- Feed: https://makerscorner.tech/feed/podcast/
|
||||||
- Licence: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
- Copyright: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
||||||
|
|
||||||
- **OGG – mintCast**
|
- **OGG – mintCast**
|
||||||
- Website: https://mintcast.org
|
- Website: https://mintcast.org
|
||||||
- Feed: https://mintcast.org/category/ogg/feed/
|
- Feed: https://mintcast.org/category/ogg/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **OggcastSoftware Freedom Law Center**
|
- **OggcastSoftware Freedom Law Center**
|
||||||
- Website: http://www.softwarefreedom.org/podcast/http://www.softwarefreedom.org/
|
- Website: http://www.softwarefreedom.org/podcast/http://www.softwarefreedom.org/
|
||||||
- Feed: http://www.softwarefreedom.org/feeds/podcast-mp3/
|
- Feed: http://www.softwarefreedom.org/feeds/podcast-mp3/
|
||||||
- Licence: 2008, 2009, 2010, 2011, Software Freedom Law Center. Licensed under a Creative Commons Attribution-No Derivative Works 3.0 United States License.
|
- Copyright: 2008, 2009, 2010, 2011, Software Freedom Law Center. Licensed under a Creative Commons Attribution-No Derivative Works 3.0 United States License.
|
||||||
|
|
||||||
- **Open Minds … from Creative Commons**
|
- **Open Minds … from Creative Commons**
|
||||||
- Website: https://anchor.fm/creativecommons
|
- Website: https://anchor.fm/creativecommons
|
||||||
- Feed: https://anchor.fm/s/4d70d828/podcast/rss
|
- Feed: https://anchor.fm/s/4d70d828/podcast/rss
|
||||||
- Licence: Creative Commons
|
- Copyright: Creative Commons
|
||||||
|
|
||||||
- **Open Source Security Podcast**
|
- **Open Source Security Podcast**
|
||||||
- Website: http://opensourcesecuritypodcast.com
|
- Website: http://opensourcesecuritypodcast.com
|
||||||
- Feed: https://opensourcesecuritypodcast.libsyn.com/rss
|
- Feed: https://opensourcesecuritypodcast.libsyn.com/rss
|
||||||
- Licence: This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
- Copyright: This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||||
|
|
||||||
- **PodCastle**
|
- **PodCastle**
|
||||||
- Website: https://podcastle.org/
|
- Website: https://podcastle.org/
|
||||||
- Feed: http://podcastle.org/feed/
|
- Feed: http://podcastle.org/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Podcast Ubuntu Portugal**
|
- **Podcast Ubuntu Portugal**
|
||||||
- Website: https://podcastubuntuportugal.org/
|
- Website: https://podcastubuntuportugal.org/
|
||||||
- Feed: https://podcastubuntuportugal.org/feed/podcast/
|
- Feed: https://podcastubuntuportugal.org/feed/podcast/
|
||||||
- Licence: Este trabalho está licenciado com uma Licença Creative Commons - Atribuição 4.0 Internacional - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: Este trabalho está licenciado com uma Licença Creative Commons - Atribuição 4.0 Internacional - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **Podcast – Cory Doctorow's craphound.com**
|
- **Podcast – Cory Doctorow's craphound.com**
|
||||||
- Website: https://craphound.com
|
- Website: https://craphound.com
|
||||||
- Feed: http://feeds.feedburner.com/doctorow_podcast
|
- Feed: http://feeds.feedburner.com/doctorow_podcast
|
||||||
- Licence: Creative Commons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/2.5/
|
- Copyright: Creative Commons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/2.5/
|
||||||
|
|
||||||
- **Podcast – Launchpad blog**
|
- **Podcast – Launchpad blog**
|
||||||
- Website: https://blog.launchpad.net
|
- Website: https://blog.launchpad.net
|
||||||
- Feed: http://news.launchpad.net/category/podcast/feed
|
- Feed: http://news.launchpad.net/category/podcast/feed
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **PseudoPod**
|
- **PseudoPod**
|
||||||
- Website: https://pseudopod.org
|
- Website: https://pseudopod.org
|
||||||
- Feed: http://pseudopod.org/feed/
|
- Feed: http://pseudopod.org/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **RadioTux**
|
- **RadioTux**
|
||||||
- Website: https://www.radiotux.de/
|
- Website: https://www.radiotux.de/
|
||||||
- Feed: http://radiotux.de/podcast/rss/radiotux-all.xml
|
- Feed: http://radiotux.de/podcast/rss/radiotux-all.xml
|
||||||
- Licence: © Creative Commons - BY-SA 3.0 Unported
|
- Copyright: © Creative Commons - BY-SA 3.0 Unported
|
||||||
|
|
||||||
- **RatholeRadio.org (Ogg Version)**
|
- **RatholeRadio.org (Ogg Version)**
|
||||||
- Website: https://ratholeradio.org
|
- Website: https://ratholeradio.org
|
||||||
- Feed: http://feeds.feedburner.com/RatholeRadio-ogg
|
- Feed: http://feeds.feedburner.com/RatholeRadio-ogg
|
||||||
- Licence: Creative Commons BY-SA Licensed
|
- Copyright: Creative Commons BY-SA Licensed
|
||||||
|
|
||||||
|
- **Science for the People**
|
||||||
|
- Website: http://www.scienceforthepeople.ca/
|
||||||
|
- Feed: http://feeds.feedburner.com/SkepticallySpeaking
|
||||||
|
- Copyright: Copyright now Science for the People
|
||||||
|
|
||||||
- **Security Now (Audio)**
|
- **Security Now (Audio)**
|
||||||
- Website: https://twit.tv/shows/security-now
|
- Website: https://twit.tv/shows/security-now
|
||||||
- Feed: http://feeds.twit.tv/sn.xml
|
- Feed: http://feeds.twit.tv/sn.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **Skepticule**
|
- **Skepticule**
|
||||||
- Website: http://www.skepticule.co.uk/
|
- Website: http://www.skepticule.co.uk/
|
||||||
- Feed: http://www.skepticule.co.uk/feeds/posts/default?alt=rss
|
- Feed: http://www.skepticule.co.uk/feeds/posts/default?alt=rss
|
||||||
- Licence: Creative Commons Attribution-NonCommercial-No Derivative Works 2.0 UK: England & Wales
|
- Copyright: Creative Commons Attribution-NonCommercial-No Derivative Works 2.0 UK: England & Wales
|
||||||
|
|
||||||
- **Software Freedom Podcast**
|
- **Software Freedom Podcast**
|
||||||
- Website: https://fsfe.org/news/podcast
|
- Website: https://fsfe.org/news/podcast
|
||||||
- Feed: http://fsfe.org/news/podcast.en.rss
|
- Feed: http://fsfe.org/news/podcast.en.rss
|
||||||
- Licence: Copyright (c) Free Software Foundation Europe. Creative Commons BY-SA 4.0
|
- Copyright: Copyright (c) Free Software Foundation Europe. Creative Commons BY-SA 4.0
|
||||||
|
|
||||||
- **Software Freedom Podcast**
|
- **Software Freedom Podcast**
|
||||||
- Website: https://fsfe.org/news/podcast
|
- Website: https://fsfe.org/news/podcast
|
||||||
- Feed: http://fsfe.org/news/podcast-opus.en.rss
|
- Feed: http://fsfe.org/news/podcast-opus.en.rss
|
||||||
- Licence: Copyright (c) Free Software Foundation Europe. Creative Commons BY-SA 4.0
|
- Copyright: Copyright (c) Free Software Foundation Europe. Creative Commons BY-SA 4.0
|
||||||
|
|
||||||
- **Tea, Earl Grey, Hot !**
|
- **Tea, Earl Grey, Hot !**
|
||||||
- Website: https://teaearlgreyhot.org/
|
- Website: https://teaearlgreyhot.org/
|
||||||
- Feed: https://teaearlgreyhot.org/feed/podcast
|
- Feed: https://teaearlgreyhot.org/feed/podcast
|
||||||
- Licence: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
- Copyright: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
||||||
|
|
||||||
- **The Big Slurp**
|
- **The Big Slurp**
|
||||||
- Website: https://thelovebug.org/series/slurp/
|
- Website: https://thelovebug.org/series/slurp/
|
||||||
- Feed: https://thelovebug.org/feed/podcast/slurp
|
- Feed: https://thelovebug.org/feed/podcast/slurp
|
||||||
- Licence: CC BY-NC-SA 4.0 Attribution-NonCommercial-ShareAlike 4.0 International
|
- Copyright: CC BY-NC-SA 4.0 Attribution-NonCommercial-ShareAlike 4.0 International
|
||||||
|
|
||||||
- **The Binary Times Audiocast - ogg**
|
- **The Binary Times Audiocast - ogg**
|
||||||
- Website: https://www.thebinarytimes.net
|
- Website: https://www.thebinarytimes.net
|
||||||
- Feed: https://www.thebinarytimes.net/rss-ogg.xml
|
- Feed: https://www.thebinarytimes.net/rss-ogg.xml
|
||||||
- Licence: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
- Copyright: Unless otherwise stated, this podcast is released under a Creative Commons, By Attribution, Share Alike license.
|
||||||
|
|
||||||
- **The Bugcast - Ogg Feed**
|
- **The Bugcast - Ogg Feed**
|
||||||
- Website: https://thebugcast.org/
|
- Website: https://thebugcast.org/
|
||||||
- Feed: http://thebugcast.org/feed/ogg/
|
- Feed: http://thebugcast.org/feed/ogg/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **The Dub Zone**
|
- **The Dub Zone**
|
||||||
- Website: http://petecogle.co.uk/category/the-dub-zone/
|
- Website: http://petecogle.co.uk/category/the-dub-zone/
|
||||||
- Feed: http://feeds.feedburner.com/TheDubZone
|
- Feed: http://feeds.feedburner.com/TheDubZone
|
||||||
- Licence: Creative Commons
|
- Copyright: Creative Commons
|
||||||
|
|
||||||
- **The Duffercast in Ogg Vorbis**
|
- **The Duffercast in Ogg Vorbis**
|
||||||
- Website: https://duffercast.org/
|
- Website: https://duffercast.org/
|
||||||
- Feed: http://duffercast.org/feed/podcast/
|
- Feed: http://duffercast.org/feed/podcast/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **The Full Circle Weekly News**
|
- **The Full Circle Weekly News**
|
||||||
- Website: https://fullcirclemagazine.org/
|
- Website: https://fullcirclemagazine.org/
|
||||||
- Feed: https://fullcirclemagazine.org/feed/podcast
|
- Feed: https://fullcirclemagazine.org/feed/podcast
|
||||||
- Licence: CC-SA 2016-present, Full Circle Magazine
|
- Copyright: CC-SA 2016-present, Full Circle Magazine
|
||||||
|
|
||||||
- **The Jodcast (high bandwidth)**
|
- **The Jodcast (high bandwidth)**
|
||||||
- Website: http://www.jodcast.net/
|
- Website: http://www.jodcast.net/
|
||||||
- Feed: http://www.jodcast.net/rss-high.xml
|
- Feed: http://www.jodcast.net/rss-high.xml
|
||||||
- Licence: Licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.0 England & Wales Licence
|
- Copyright: Licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.0 England & Wales Licence
|
||||||
|
|
||||||
- **The Linux Action Show! OGG**
|
- **The Linux Action Show! OGG**
|
||||||
- Website: http://www.jupiterbroadcasting.com
|
- Website: http://www.jupiterbroadcasting.com
|
||||||
- Feed: http://feeds2.feedburner.com/TheLinuxActionShowOGG
|
- Feed: http://feeds2.feedburner.com/TheLinuxActionShowOGG
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **The Linux Cast**
|
- **The Linux Cast**
|
||||||
- Website: https://thelinuxcast.org/
|
- Website: https://thelinuxcast.org/
|
||||||
- Feed: https://thelinuxcast.org/feed/feed.xml
|
- Feed: https://thelinuxcast.org/feed/feed.xml
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **The Linux Link Tech Show Ogg-Vorbis Feed**
|
- **The Linux Link Tech Show Ogg-Vorbis Feed**
|
||||||
- Website: http://www.tllts.org
|
- Website: http://www.tllts.org
|
||||||
- Feed: http://feeds.feedburner.com/TheLinuxLinkTechShowOgg-vorbisFeed
|
- Feed: http://feeds.feedburner.com/TheLinuxLinkTechShowOgg-vorbisFeed
|
||||||
- Licence: TLLTS is licensed under Creative Commons License for Non-Commercial Use
|
- Copyright: TLLTS is licensed under Creative Commons License for Non-Commercial Use
|
||||||
|
|
||||||
- **The Linux Link Tech Show Ogg-Vorbis Feed**
|
- **The Linux Link Tech Show Ogg-Vorbis Feed**
|
||||||
- Website: http://www.tllts.org
|
- Website: http://www.tllts.org
|
||||||
- Feed: http://www.thelinuxlink.net/tllts/tllts_ogg.rss
|
- Feed: http://www.thelinuxlink.net/tllts/tllts_ogg.rss
|
||||||
- Licence: TLLTS is licensed under Creative Commons License for Non-Commercial Use
|
- Copyright: TLLTS is licensed under Creative Commons License for Non-Commercial Use
|
||||||
|
|
||||||
- **This Week in Computer Hardware (Audio)**
|
- **This Week in Computer Hardware (Audio)**
|
||||||
- Website: https://twit.tv/shows/this-week-in-computer-hardware
|
- Website: https://twit.tv/shows/this-week-in-computer-hardware
|
||||||
- Feed: http://feeds.twit.tv/twich.xml
|
- Feed: http://feeds.twit.tv/twich.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **This Week in Google (Audio)**
|
- **This Week in Google (Audio)**
|
||||||
- Website: https://twit.tv/shows/this-week-in-google
|
- Website: https://twit.tv/shows/this-week-in-google
|
||||||
- Feed: http://feeds.twit.tv/twig.xml
|
- Feed: http://feeds.twit.tv/twig.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **This Week in Microbiology**
|
- **This Week in Microbiology**
|
||||||
- Website: http://www.asm.org/twim/
|
- Website: http://www.asm.org/twim/
|
||||||
- Feed: http://feeds.feedburner.com/twim
|
- Feed: http://feeds.feedburner.com/twim
|
||||||
- Licence: Creative Commons Attribution - Noncommercial
|
- Copyright: Creative Commons Attribution - Noncommercial
|
||||||
|
|
||||||
- **This Week in Tech (Audio)**
|
- **This Week in Tech (Audio)**
|
||||||
- Website: https://twit.tv/shows/this-week-in-tech
|
- Website: https://twit.tv/shows/this-week-in-tech
|
||||||
- Feed: http://feeds.twit.tv/twit.xml
|
- Feed: http://feeds.twit.tv/twit.xml
|
||||||
- Licence: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
- Copyright: This work is licensed under a Creative Commons License - Attribution-NonCommercial-NoDerivatives 4.0 International - http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||||
|
|
||||||
- **TuxJam OGG**
|
- **TuxJam OGG**
|
||||||
- Website: https://tuxjam.otherside.network/
|
- Website: https://tuxjam.otherside.network/
|
||||||
- Feed: https://tuxjam.otherside.network/?feed=podcast
|
- Feed: https://tuxjam.otherside.network/?feed=podcast
|
||||||
- Licence: Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
- Copyright: Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
|
||||||
- **Ubuntu Podcast**
|
- **Ubuntu Podcast**
|
||||||
- Website: https://ubuntupodcast.org
|
- Website: https://ubuntupodcast.org
|
||||||
- Feed: http://ubuntupodcast.org/feed/
|
- Feed: http://ubuntupodcast.org/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **Ubuntu Podcast**
|
- **Ubuntu Podcast**
|
||||||
- Website: https://ubuntupodcast.org
|
- Website: https://ubuntupodcast.org
|
||||||
- Feed: http://feed.ubuntupodcast.org/mp3
|
- Feed: http://feed.ubuntupodcast.org/mp3
|
||||||
- Licence: Copyright Ubuntu Podcast Team. Some rights reserved. This audio is released under a Creative Commons Attribution-Share Alike license.
|
- Copyright: Copyright Ubuntu Podcast Team. Some rights reserved. This audio is released under a Creative Commons Attribution-Share Alike license.
|
||||||
|
|
||||||
- **Wikipediapodden**
|
- **Wikipediapodden**
|
||||||
- Website: http://wikipediapodden.se/prenumerera/
|
- Website: http://wikipediapodden.se/prenumerera/
|
||||||
- Feed: http://wikipediapodden.se/feed/podcast/
|
- Feed: http://wikipediapodden.se/feed/podcast/
|
||||||
- Licence: CC BY-SA 4.0 Wikipediapodden
|
- Copyright: CC BY-SA 4.0 Wikipediapodden
|
||||||
|
|
||||||
- **bsdtalk**
|
- **bsdtalk**
|
||||||
- Website: http://bsdtalk.blogspot.com/
|
- Website: http://bsdtalk.blogspot.com/
|
||||||
- Feed: http://feeds.feedburner.com/Bsdtalk
|
- Feed: http://feeds.feedburner.com/Bsdtalk
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **podcast – Full Circle Magazine**
|
- **podcast – Full Circle Magazine**
|
||||||
- Website: https://fullcirclemagazine.org
|
- Website: https://fullcirclemagazine.org
|
||||||
- Feed: http://fullcirclemagazine.org/category/podcast/feed/
|
- Feed: http://fullcirclemagazine.org/category/podcast/feed/
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
- **urandom podcast**
|
- **urandom podcast**
|
||||||
- Website: https://urandom-podcast.info/
|
- Website: https://urandom-podcast.info/
|
||||||
- Feed: http://feeds.feedburner.com/urandom-podcast/ogg
|
- Feed: http://feeds.feedburner.com/urandom-podcast/ogg
|
||||||
- Licence:
|
- Copyright:
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
<opml version="1.1">
|
<opml version="1.1">
|
||||||
<head>
|
<head>
|
||||||
<title>Free Culture Podcasts</title>
|
<title>Free Culture Podcasts</title>
|
||||||
<dateCreated>2023-01-11 09:44:06</dateCreated>
|
<dateCreated>2023-01-14 23:09:26</dateCreated>
|
||||||
<dateModified>2023-01-11 09:44:06</dateModified>
|
<dateModified>2023-01-14 23:09:26</dateModified>
|
||||||
<ownerName></ownerName>
|
<ownerName></ownerName>
|
||||||
<ownerEmail></ownerEmail>
|
<ownerEmail></ownerEmail>
|
||||||
<expansionState></expansionState>
|
<expansionState></expansionState>
|
||||||
@ -14,6 +14,7 @@
|
|||||||
<windowRight></windowRight>
|
<windowRight></windowRight>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<outline description="2.5 Admins is a podcast featuring two sysadmins called Allan Jude and Jim Salter, and a producer/editor who can just about configure a Samba share called Joe Ressington. Every two weeks we get together, talk about recent tech news, and answer some of your admin-related questions." htmlUrl="https://2.5admins.com" text="2.5 Admins" title="2.5 Admins" xmlUrl="https://2.5admins.com/feed/podcast" />
|
||||||
<outline description="A Podcast about servers and Networking" htmlUrl="https://www.adminadminpodcast.co.uk" text="Admin Admin Podcast" title="Admin Admin Podcast" xmlUrl="http://feeds.feedburner.com/TheAdminAdminPodcast" />
|
<outline description="A Podcast about servers and Networking" htmlUrl="https://www.adminadminpodcast.co.uk" text="Admin Admin Podcast" title="Admin Admin Podcast" xmlUrl="http://feeds.feedburner.com/TheAdminAdminPodcast" />
|
||||||
<outline description="All About Android delivers everything you want to know about Android each week--the biggest news, freshest hardware, best apps and geekiest how-tos--with Android enthusiasts Jason Howell, Ron Richards, Huyen Tue Dao, and a variety of special guests along the way. Records live every Tuesday at 8:00pm Eastern / 5:00pm Pacific / 01:00 (Wed) UTC." htmlUrl="https://twit.tv/shows/all-about-android" text="All About Android (Audio)" title="All About Android (Audio)" xmlUrl="http://feeds.twit.tv/aaa.xml" />
|
<outline description="All About Android delivers everything you want to know about Android each week--the biggest news, freshest hardware, best apps and geekiest how-tos--with Android enthusiasts Jason Howell, Ron Richards, Huyen Tue Dao, and a variety of special guests along the way. Records live every Tuesday at 8:00pm Eastern / 5:00pm Pacific / 01:00 (Wed) UTC." htmlUrl="https://twit.tv/shows/all-about-android" text="All About Android (Audio)" title="All About Android (Audio)" xmlUrl="http://feeds.twit.tv/aaa.xml" />
|
||||||
<outline description="Join us as we talk about everything related to Information Technology, and some other random stuff as well." htmlUrl="http://aiit.se/radio/" text="All In IT Radio (ogg)" title="All In IT Radio (ogg)" xmlUrl="http://feeds.aiit.se/allinit-radio-ogg" />
|
<outline description="Join us as we talk about everything related to Information Technology, and some other random stuff as well." htmlUrl="http://aiit.se/radio/" text="All In IT Radio (ogg)" title="All In IT Radio (ogg)" xmlUrl="http://feeds.aiit.se/allinit-radio-ogg" />
|
||||||
@ -59,6 +60,7 @@
|
|||||||
<outline description="New media, new rules" htmlUrl="http://sixgun.org" text="Linux Outlaws" title="Linux Outlaws" xmlUrl="http://feeds.feedburner.com/linuxoutlaws" />
|
<outline description="New media, new rules" htmlUrl="http://sixgun.org" text="Linux Outlaws" title="Linux Outlaws" xmlUrl="http://feeds.feedburner.com/linuxoutlaws" />
|
||||||
<outline description="A podcast for the new Linux user" htmlUrl="http://www.linuxreality.com" text="Linux Reality Podcast (MP3 Feed)" title="Linux Reality Podcast (MP3 Feed)" xmlUrl="http://feeds.feedburner.com/linuxreality" />
|
<outline description="A podcast for the new Linux user" htmlUrl="http://www.linuxreality.com" text="Linux Reality Podcast (MP3 Feed)" title="Linux Reality Podcast (MP3 Feed)" xmlUrl="http://feeds.feedburner.com/linuxreality" />
|
||||||
<outline description="Verbal's Linux Trivia Podcast" htmlUrl="http://setbit.org/lt.html" text="Linux Trivia Podcast" title="Linux Trivia Podcast" xmlUrl="http://setbit.org/lt-ogg.xml" />
|
<outline description="Verbal's Linux Trivia Podcast" htmlUrl="http://setbit.org/lt.html" text="Linux Trivia Podcast" title="Linux Trivia Podcast" xmlUrl="http://setbit.org/lt-ogg.xml" />
|
||||||
|
<outline description="How did your favorite Linux distribution get its start? Join us and find out! Linux User Space is hosted by Leo and Dan, and every two weeks we deep dive into the history of Linux distributions and the things that matter to us. Episodes drop every other Monday." htmlUrl="https://www.linuxuserspace.show" text="Linux User Space" title="Linux User Space" xmlUrl="https://www.linuxuserspace.show/rss" />
|
||||||
<outline description="The Linux at Work podcast provides info and tips for people interested in using Linux in a professional environment. Featuring @chetwisniewski, @john_shier and @0xbennyv" htmlUrl="https://www.linuxatwork.org" text="Linux at Work" title="Linux at Work" xmlUrl="http://feeds.podtrac.com/mBdfP0QTX0iY" />
|
<outline description="The Linux at Work podcast provides info and tips for people interested in using Linux in a professional environment. Featuring @chetwisniewski, @john_shier and @0xbennyv" htmlUrl="https://www.linuxatwork.org" text="Linux at Work" title="Linux at Work" xmlUrl="http://feeds.podtrac.com/mBdfP0QTX0iY" />
|
||||||
<outline description="Linux in the Ham Shack Podcast in MP3 Format" htmlUrl="https://lhspodcast.info/category/podcast-mp3/" text="Linux in the Ham Shack" title="Linux in the Ham Shack" xmlUrl="http://lhspodcast.info/category/podcast-mp3/feed/" />
|
<outline description="Linux in the Ham Shack Podcast in MP3 Format" htmlUrl="https://lhspodcast.info/category/podcast-mp3/" text="Linux in the Ham Shack" title="Linux in the Ham Shack" xmlUrl="http://lhspodcast.info/category/podcast-mp3/feed/" />
|
||||||
<outline description="Linux in the Ham Shack Podcast in OGG Format" htmlUrl="https://lhspodcast.info/category/podcast-ogg/" text="Linux in the Ham Shack (OGG Feed)" title="Linux in the Ham Shack (OGG Feed)" xmlUrl="https://lhspodcast.info/category/podcast-ogg/feed/" />
|
<outline description="Linux in the Ham Shack Podcast in OGG Format" htmlUrl="https://lhspodcast.info/category/podcast-ogg/" text="Linux in the Ham Shack (OGG Feed)" title="Linux in the Ham Shack (OGG Feed)" xmlUrl="https://lhspodcast.info/category/podcast-ogg/feed/" />
|
||||||
@ -77,6 +79,7 @@
|
|||||||
<outline description="The Sound of Horror" htmlUrl="https://pseudopod.org" text="PseudoPod" title="PseudoPod" xmlUrl="http://pseudopod.org/feed/" />
|
<outline description="The Sound of Horror" htmlUrl="https://pseudopod.org" text="PseudoPod" title="PseudoPod" xmlUrl="http://pseudopod.org/feed/" />
|
||||||
<outline description="Linux, Open Source und Netzkultur" htmlUrl="https://www.radiotux.de/" text="RadioTux" title="RadioTux" xmlUrl="http://radiotux.de/podcast/rss/radiotux-all.xml" />
|
<outline description="Linux, Open Source und Netzkultur" htmlUrl="https://www.radiotux.de/" text="RadioTux" title="RadioTux" xmlUrl="http://radiotux.de/podcast/rss/radiotux-all.xml" />
|
||||||
<outline description="Music, Waffling, Live Performances & Laughs" htmlUrl="https://ratholeradio.org" text="RatholeRadio.org (Ogg Version)" title="RatholeRadio.org (Ogg Version)" xmlUrl="http://feeds.feedburner.com/RatholeRadio-ogg" />
|
<outline description="Music, Waffling, Live Performances & Laughs" htmlUrl="https://ratholeradio.org" text="RatholeRadio.org (Ogg Version)" title="RatholeRadio.org (Ogg Version)" xmlUrl="http://feeds.feedburner.com/RatholeRadio-ogg" />
|
||||||
|
<outline description="Science for the People is a long-format interview podcast that explores the connections between science, popular culture, history, and public policy, to help listeners understand the evidence and arguments behind what's in the news and on the shelves. Our hosts sit down with science researchers, writers, authors, journalists, and experts to discuss science from the past, the science that affects our lives today, and how science might change our future." htmlUrl="http://www.scienceforthepeople.ca/" text="Science for the People" title="Science for the People" xmlUrl="http://feeds.feedburner.com/SkepticallySpeaking" />
|
||||||
<outline description="Steve Gibson, the man who coined the term spyware and created the first anti-spyware program, creator of SpinRite and ShieldsUP, discusses the hot topics in security today with Leo Laporte. Records live every Tuesday at 4:30pm Eastern / 1:30pm Pacific / 21:30 UTC." htmlUrl="https://twit.tv/shows/security-now" text="Security Now (Audio)" title="Security Now (Audio)" xmlUrl="http://feeds.twit.tv/sn.xml" />
|
<outline description="Steve Gibson, the man who coined the term spyware and created the first anti-spyware program, creator of SpinRite and ShieldsUP, discusses the hot topics in security today with Leo Laporte. Records live every Tuesday at 4:30pm Eastern / 1:30pm Pacific / 21:30 UTC." htmlUrl="https://twit.tv/shows/security-now" text="Security Now (Audio)" title="Security Now (Audio)" xmlUrl="http://feeds.twit.tv/sn.xml" />
|
||||||
<outline description="Spanking the bottom of ignorance since 2009" htmlUrl="http://www.skepticule.co.uk/" text="Skepticule" title="Skepticule" xmlUrl="http://www.skepticule.co.uk/feeds/posts/default?alt=rss" />
|
<outline description="Spanking the bottom of ignorance since 2009" htmlUrl="http://www.skepticule.co.uk/" text="Skepticule" title="Skepticule" xmlUrl="http://www.skepticule.co.uk/feeds/posts/default?alt=rss" />
|
||||||
<outline description="The regular podcast about Free Software and ongoing activities hosted by the FSFE" htmlUrl="https://fsfe.org/news/podcast" text="Software Freedom Podcast" title="Software Freedom Podcast" xmlUrl="http://fsfe.org/news/podcast.en.rss" />
|
<outline description="The regular podcast about Free Software and ongoing activities hosted by the FSFE" htmlUrl="https://fsfe.org/news/podcast" text="Software Freedom Podcast" title="Software Freedom Podcast" xmlUrl="http://fsfe.org/news/podcast.en.rss" />
|
||||||
|
BIN
feedWatcher.pdf
BIN
feedWatcher.pdf
Binary file not shown.
@ -10,7 +10,7 @@
|
|||||||
- **[% feeds.$i.urls_title %]**
|
- **[% feeds.$i.urls_title %]**
|
||||||
- Website: [% feeds.$i.urls_link %]
|
- Website: [% feeds.$i.urls_link %]
|
||||||
- Feed: [% feeds.$i.urls_url %]
|
- Feed: [% feeds.$i.urls_url %]
|
||||||
- Licence: [% feeds.$i.urls_copyright %]
|
- Copyright: [% feeds.$i.urls_copyright %]
|
||||||
|
|
||||||
[% i = i + 1 -%]
|
[% i = i + 1 -%]
|
||||||
[% END -%]
|
[% END -%]
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[%# feedWatcher_5.tpl 2022-11-21 -%]
|
[%# feedWatcher_5.tpl 2022-11-21 -%]
|
||||||
|
[%# Lists all the URLs in the system, useful for dumping everything -%]
|
||||||
[% IF feeds.size > 0 -%]
|
[% IF feeds.size > 0 -%]
|
||||||
[% i = 0 -%]
|
[% i = 0 -%]
|
||||||
[% WHILE i < feeds.size -%]
|
[% WHILE i < feeds.size -%]
|
||||||
|
@ -29,6 +29,8 @@ CREATE TABLE urls (
|
|||||||
link varchar(1024),
|
link varchar(1024),
|
||||||
image varchar(1024),
|
image varchar(1024),
|
||||||
copyright varchar(80),
|
copyright varchar(80),
|
||||||
|
check_type varchar(10) DEFAULT 'none',
|
||||||
|
reason_accepted text,
|
||||||
generator varchar(80),
|
generator varchar(80),
|
||||||
language varchar(40),
|
language varchar(40),
|
||||||
parent_id integer
|
parent_id integer
|
||||||
@ -131,6 +133,8 @@ CREATE VIEW all_episodes AS
|
|||||||
urls.link as urls_link,
|
urls.link as urls_link,
|
||||||
urls.image as urls_image,
|
urls.image as urls_image,
|
||||||
urls.copyright as urls_copyright,
|
urls.copyright as urls_copyright,
|
||||||
|
urls.check_type as urls_check_type,
|
||||||
|
urls.reason_accepted as urls_reason_accepted,
|
||||||
urls.generator as urls_generator,
|
urls.generator as urls_generator,
|
||||||
urls.language as urls_language,
|
urls.language as urls_language,
|
||||||
urls.parent_id as urls_parent_id,
|
urls.parent_id as urls_parent_id,
|
||||||
|
Loading…
Reference in New Issue
Block a user