You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.2 KiB

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Getopt::Std;
use IO::File;
use Date::Parse;
use DBIx::Simple;
use SQL::Abstract;
use Term::Prompt;
use YAML;
my $opts = { f => undef, F => undef };
getopts('f:F:', $opts)
or die "Usage: $0 [-f <qrss.db>] [-F <filter-by-url>]\n";
die "Usage: $0 [-f <qrss.db>]\n"
unless $opts->{f} and -f $opts->{f};
my $dbopts = { sqlite_unicode => 1, AutoCommit => 1, RaiseError => 1 };
my $dsn = sprintf 'dbi:SQLite:dbname=%s', $opts->{f};
my $db = DBIx::Simple->new($dsn, undef, undef, $dbopts);
sub list_feeds {
my $filter = $opts->{F}
? { xmlUrl => {-like => "%$opts->{F}%"} }
: { xmlUrl => {'!=' => ''} };
my @feeds = $db->select('feeds', [qw(id title text xmlUrl)], $filter, 'title')->hashes;
print " ID | Feed name (URL)\n";
print "-----+-----------------------------------------------------------\n";
foreach my $f (@feeds) {
printf " %3d | %s (%s)\n", $f->{id}, $f->{title} || $f->{text}, $f->{xmlurl};
}
print "\n";
}
sub export_feed {
my $fid = shift;
my $feed = $db->select('feeds', '*', {id => $fid})->hash
or return warn "no such feed: $fid\n";
my $fname = sprintf "%d - %s", $fid, substr($feed->{title} || $feed->{text}, 0, 128);
$fname =~ tr[/][]d;
$fname .= '.yml';
my $file = IO::File->new($fname, 'w');
my $yml = YAML::Dump({
type => 'feed',
url => $feed->{xmlurl} || $feed->{htmlurl},
name => $feed->{title} || $feed->{text},
note => $feed->{description},
});
if (utf8::is_utf8($yml)) { utf8::encode($yml); }
$file->print($yml);
my @news = $db->select('news', '*', {feedId => $fid})->hashes;
my $exported = 0;
print "exporting: ";
while (my $n = shift @news) {
$n->{flags} = '';
$n->{flags} .= ($n->{read}) ? 'u' : 'U';
$n->{flags} .= ($n->{starred}) ? 'S' : 's';
$n->{ctime} = str2time($n->{published} || $n->{modified});
if ($n->{description} and not $n->{content}) {
$n->{content} = $n->{description};
undef $n->{description};
}
foreach my $attr (qw(guid link_href)) {
next unless $n->{$attr} and index($n->{$attr}, '://') >= 0;
$n->{url} = $n->{$attr};
last;
}
$yml = YAML::Dump({
type => 'entry',
url => $n->{url},
ctime => $n->{ctime},
flags => $n->{flags},
author => $n->{author_name},
category => $n->{category},
title => $n->{title},
summary => $n->{description},
content => $n->{content},
});
if (utf8::is_utf8($yml)) { utf8::encode($yml); }
$file->print($yml);
$exported++;
if ($exported % 100 == 0) { print '.'; }
} # foreach @news
$file->close;
print "\n";
printf "exported: %s (%d entries)\n", $fname, $exported;
}
sub show_help {
print <<"HELP";
l\tList feeds
f\tSet list filter
e\tExport
h\tHelp
q\tQuit
HELP
}
binmode STDOUT => ':utf8';
$| = 1;
while (1) {
my $a = prompt('c', 'command', 'h for help', '', qw(l f e h q));
if ($a eq 'l') {
list_feeds();
} elsif ($a eq 'f') {
$opts->{F} = prompt('x', 'Filter by URL', '', 'example.com', '');
} elsif ($a eq 'e') {
my $fid = prompt('n', 'feed id:', '', '');
export_feed($fid);
} elsif ($a eq 'q') {
print "exiting...\n";
exit 0;
} else {
show_help();
}
}
exit 0;