#!/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 ] [-F ]\n"; die "Usage: $0 [-f ]\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;