diff --git a/index.cgi b/index.cgi index 064b4bf..6c0abbd 100755 --- a/index.cgi +++ b/index.cgi @@ -29,10 +29,10 @@ use strict; use warnings; -use v5.14; +use v5.24; use utf8; use experimental 'smartmatch'; # for given/when -use experimental 'autoderef'; +use experimental 'postderef'; use CGI; use Cache::Memcached; @@ -43,6 +43,7 @@ use POSIX qw(strftime); use Rss2Html::Scrubber; use Time::HiRes qw(time); +my $db_conn = "dbi:Pg:dbname=rss2html"; $| = 1; my $start = time(); @@ -60,18 +61,14 @@ if ($q->param('mark')) { } sub redirect { - my $dbh = DBI->connect("dbi:SQLite:dbname=rss2html.sqlite", "", "", - { - sqlite_use_immediate_transaction => 1, - }); - $dbh->{sqlite_unicode} = 1; + my $dbh = DBI->connect($db_conn); my $item_id = $q->param('redir'); my $item = $dbh->selectrow_hashref("select * from items where id=?", {}, $item_id); if ($item) { print "Status: 302\n"; print "Location: $item->{link}\n"; print "\n"; - $dbh->do("insert into read(user, item_id) values(?, ?)", {}, $q->remote_user, $item_id); + $dbh->do("insert into read(username, item_id) values(?, ?)", {}, $q->remote_user, $item_id); $mcd->delete(item_info_key($q->remote_user, $item->{feed_id})); exit(0); } @@ -84,7 +81,7 @@ sub redirect { sub mark { print_log("mark start"); - my $dbh = DBI->connect("dbi:SQLite:dbname=rss2html.sqlite", "", ""); + my $dbh = DBI->connect($db_conn, "", ""); $dbh->{sqlite_unicode} = 1; my $item_id = $q->param('mark'); my $item = $dbh->selectrow_hashref("select * from items where id=?", {}, $item_id); @@ -94,7 +91,7 @@ sub mark { print "Status: 302\n"; print "Location: ", $q1->self_url, "\n"; print "\n"; - $dbh->do("insert into read(user, item_id) values(?, ?)", {}, $q->remote_user, $item_id); + $dbh->do("insert into read(username, item_id) values(?, ?)", {}, $q->remote_user, $item_id); $mcd->delete(item_info_key($q->remote_user, $item->{feed_id})); print_log("mark done"); exit(0); @@ -126,7 +123,7 @@ sub list { print "

RSS 2 HTML

\n"; print "
", strftime("%Y-%m-%d %H:%M:%S%z", localtime()), "
\n"; - my $dbh = DBI->connect("dbi:SQLite:dbname=rss2html.sqlite", "", ""); + my $dbh = DBI->connect($db_conn, "", ""); $dbh->{sqlite_unicode} = 1; print_log("list_feeds start"); @@ -135,16 +132,17 @@ sub list { my $items; if ($show_read) { - my $fields = "feeds.id as feed_id, feeds.title as feed_title, allow_img, link, items.title as item_title, content, items.id as item_id, issued, user, lang"; + my $fields = "feeds.id as feed_id, feeds.title as feed_title, allow_img, link, items.title as item_title, content, " + . "items.id as item_id, issued, username, lang"; my $tables = "items join feeds on items.feed_id=feeds.id - left outer join read on (items.id=read.item_id and user=?)"; + left outer join read on (items.id=read.item_id and username=?)"; my @where; if (%feed_item_show) { push @where, "feeds.id in (" . join(',', keys %feed_item_show) . ")"; } if (!$show_old) { - push @where, "(items.old is null or items.old == 0)" + push @where, "(items.old is null or items.old = 0)" } my $where = "where " . join(" and ", @where); @@ -157,9 +155,9 @@ sub list { my $item = pop @$items1; { no warnings 'uninitialized'; - print_log("id=$item->{item_id}, user=$item->{user}"); + print_log("id=$item->{item_id}, username=$item->{username}"); } - if (!$item->{user}) { + if (!$item->{username}) { print_log("id=$item->{item_id}: unread"); unshift @$items, $item; } elsif ($nrd < $show_read) { @@ -170,10 +168,10 @@ sub list { } } else { - my @where = ("user is null"); + my @where = ("username is null"); if (!$show_old) { - push @where, "(items.old is null or items.old == 0)" + push @where, "(items.old is null or items.old = 0)" } my $where = "where " . join(" and ", @where); @@ -183,13 +181,13 @@ sub list { "select feeds.id as feed_id, feeds.title as feed_title, allow_img, link, items.title as item_title, content, items.id as item_id, issued, lang from items join feeds on items.feed_id=feeds.id - left outer join read on (items.id=read.item_id and user=?) + left outer join read on (items.id=read.item_id and username=?) $where order by issued", { Slice => {} }, $q->remote_user); } my $feeds = $dbh->selectall_arrayref( - "select id, title from feeds where update_frequency is not null order by id", + "select id, title from feeds where active order by id", { Slice => {} } ); for my $f (@$feeds) { @@ -226,7 +224,7 @@ sub print_itemlist { print_log(scalar @$items . " after remix"); for my $item (@$items) { $n_items++; - my $is_read = defined($item->{user}); + my $is_read = defined($item->{username}); my $scrubbed_content = $mcd->get(scrubbed_content_key($item->{item_id})); if ($scrubbed_content) { $scrubbed_content = decode_utf8($scrubbed_content); @@ -273,17 +271,17 @@ sub remix { print_log("item w/o feed_id: " . Dumper($item)); } $queues->{$item->{feed_id}} //= []; - push $queues->{$item->{feed_id}}, $item; + push $queues->{$item->{feed_id}}->@*, $item; } - my @ordered_feeds = sort { $queues->{$a}[0]{issued} <=> $queues->{$b}[0]{issued} } keys $queues; + my @ordered_feeds = sort { $queues->{$a}[0]{issued} <=> $queues->{$b}[0]{issued} } keys $queues->%*; my $new_items = []; my $found; do { $found = 0; for my $feed (@ordered_feeds) { - my $item = shift $queues->{$feed}; + my $item = shift $queues->{$feed}->@*; if ($item) { - push $new_items, $item; + push $new_items->@*, $item; $found++; print_log("found an item in feed $feed. " . scalar(@{$queues->{$feed}}) . " items left") } @@ -305,7 +303,7 @@ sub list_feeds { print "
\n"; $dbh->begin_work; - my $feeds = $dbh->selectall_arrayref("select * from feeds where update_frequency is not null", { Slice => {} }); + my $feeds = $dbh->selectall_arrayref("select * from feeds where active", { Slice => {} }); my $seconds_per_week = 86400 * 7; for my $feed (@$feeds) { $feed->{title} //= "-"; @@ -325,7 +323,7 @@ sub print_item_info { my $item_info = $mcd->get($item_info_key); my $cmd = "select count(i.id) as nr_items, max(i.issued) as last_issued, max(i.seen) as last_seen, count(r.item_id) as nr_read - from items i left outer join (select item_id from read where user=?) r on i.id=r.item_id + from items i left outer join (select item_id from read where username=?) r on i.id=r.item_id where i.feed_id=?"; unless ($show_old) { $cmd .= " and (old is null or old = 0)"; @@ -408,6 +406,7 @@ sub delta_t { sub item_info_key { my ($user, $feed_id) = @_; + $user //= "anonymous"; return "rss2html/item_info/$user/$feed_id"; } diff --git a/lib/Rss2Html/Feed.pm b/lib/Rss2Html/Feed.pm index 55fc43c..fec5aa6 100644 --- a/lib/Rss2Html/Feed.pm +++ b/lib/Rss2Html/Feed.pm @@ -32,7 +32,7 @@ has 'id' => ( has 'url' => ( is => 'rw', ); -has 'update_frequency' => ( +has 'active' => ( is => 'rw', ); has 'last_update' => ( @@ -124,7 +124,7 @@ sub update { } } } else { - print STDERR "error getting $self->{url}: $@\n"; + $self->log->error("error getting $self->{url}: $@"); } } elsif ($self->{type} eq 'atom') { my $api = XML::Atom::Client->new(); @@ -175,7 +175,7 @@ sub update { $dbh->do("update items set old=1 where id in (select id from items where feed_id=? and (old is null or old != 1) - order by issued desc limit -1 offset 100)", + order by issued desc offset 100)", {}, $self->{id}); @@ -205,7 +205,7 @@ sub invalidate_item_info { my ($self) = @_; my $dbh = $self->dbh; - my $users = $dbh->selectcol_arrayref("select distinct user from read"); + my $users = $dbh->selectcol_arrayref("select distinct username from read"); for my $user (@$users) { $mcd->delete($self->item_info_key($user)); } diff --git a/lib/Rss2Html/FeedList.pm b/lib/Rss2Html/FeedList.pm index 7e6acd4..3a209cf 100644 --- a/lib/Rss2Html/FeedList.pm +++ b/lib/Rss2Html/FeedList.pm @@ -17,11 +17,7 @@ has 'dbh' => ( sub BUILD { my ($self, $args) = @_; - my $dbh = DBI->connect("dbi:SQLite:dbname=rss2html.sqlite", "", "", - { - sqlite_use_immediate_transaction => 1, - }); - $dbh->{sqlite_unicode} = 1; + my $dbh = DBI->connect("dbi:Pg:dbname=rss2html", "", ""); $self->_set_dbh($dbh); } @@ -31,7 +27,7 @@ sub feeds { no autovivification qw(fetch); - my $feeds_sql = $dbh->selectall_arrayref("select * from feeds where update_frequency is not null", { Slice => {} }); + my $feeds_sql = $dbh->selectall_arrayref("select * from feeds where active", { Slice => {} }); my @feeds; for (@$feeds_sql) { push @feeds, Rss2Html::Feed->new(%$_, dbh => $dbh); @@ -129,3 +125,4 @@ sub cleanup { #--- __PACKAGE__->meta->make_immutable; 1; +# vim: tw=132 diff --git a/rss2html.postgresql b/rss2html.postgresql index 3a5be2a..732d809 100644 --- a/rss2html.postgresql +++ b/rss2html.postgresql @@ -1,7 +1,7 @@ -CREATE TABLE feeds (id integer primary key autoincrement, url varchar, update_frequency int, last_update int, title varchar, type varchar, allow_img boolean, expire int, lang varchar); -CREATE TABLE items (id integer primary key autoincrement, title varchar, link varchar, content varchar, issued int, seen int, feed_id integer, old int); -CREATE TABLE read(item_id integer, user varchar, foreign key (item_id) references items(id)); -CREATE INDEX items_link_idx on items(link); +CREATE TABLE feeds (id serial primary key, url varchar, active boolean, last_update int, title varchar, type varchar, allow_img boolean, expire int, lang varchar); +CREATE TABLE items (id serial primary key, title varchar, link varchar, content varchar, issued int, seen int, feed_id integer, old int); +CREATE TABLE read(item_id integer, username varchar, foreign key (item_id) references items(id)); +CREATE INDEX on items(link); CREATE INDEX read_item_id_idx on read(item_id); -CREATE TABLE later (item_id integer, user varchar, foreign key (item_id) references items(id)); -CREATE INDEX later_item_id_idx on later(item_id); +CREATE TABLE later (item_id integer, username varchar, foreign key (item_id) references items(id)); +CREATE INDEX on later(item_id);