#!/usr/bin/perl
#######################################################################
# snowlistOutput - RSS Output
#
# $Id: snowlistOutput 185 2004-10-20 16:38:41Z kiza $
#
# Generate RSS feed
#
# Copyright Oliver Feiler 2004 <kiza@gmx.net>
# http://kiza.kcore.de/software/snowlist/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#######################################################################

use FindBin qw($Bin);
use lib "$Bin";

use Encode qw/encode/;
use strict;
use DBI;
use XML::LibXML;
use Digest::MD5 qw(md5_hex);
use SnowlistConfig;

#######################################################################

my($listid) = $ARGV[0];
my($config) = SnowlistConfig::LoadConfig($listid);

my($nsrss) = "http://purl.org/rss/1.0/";
my($nsrdf) = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";

my($dboutput) = LoadDB();

#######################################################################
# Build XML document
my($doc) = XML::LibXML::Document->new();
my($text);

my($root) = $doc->createElement("RDF");
$root->setNamespace($nsrss, "", 0);
$root->setNamespace($nsrdf, "rdf", 1);
$doc->setDocumentElement($root);

my($channel) = $doc->createElement("channel");
$channel->setAttribute("rdf:about", $config->{'feedlink'});
$root->appendChild($channel);

$channel->appendTextChild("title", $config->{'feedtitle'}); 
$channel->appendTextChild("link", $config->{'feedlink'});
$channel->appendTextChild("description", $config->{'feeddescription'});

my($channelitems) = $doc->createElement("items");
$channel->appendChild($channelitems);
my($seqitems) = $doc->createElement("rdf:Seq");
$channelitems->appendChild($seqitems);

foreach(@$dboutput) {
	my($rssitemlink) = $config->{'feedlink'}."/#".md5_hex(encode('UTF-8', $_->{'msg_thread'}));

	# rdf sequence item
	my($li) = $doc->createElement("rdf:li");
	$li->setAttribute("rdf:resource", $rssitemlink);
	$seqitems->appendChild($li);
	
	# news item
	my($rssitem) = $doc->createElement("item");
	$rssitem->setAttribute("rdf:about", $rssitemlink);
	$root->appendChild($rssitem);
	
	my($rssitemcount) = 0;
	my($rssitemdescription) = "<pre>";
	foreach(@{$_->{'items'}}) {
		$rssitemdescription .= MakeThatSingleItemThing($_);
		$rssitemcount++;
	}
	$rssitemdescription .= "</pre>";
	my($rssitemtitle) = $_->{'msg_thread'}." ($rssitemcount ";
	if ($rssitemcount == 1) {
		$rssitemtitle .= "item)";
	} else {
		$rssitemtitle .= "items)";
	}
	$rssitem->appendTextChild("title", $rssitemtitle);
	$rssitem->appendTextChild("link", $rssitemlink);
	$rssitem->appendTextChild("description", $rssitemdescription);
}

if ($config->{'outputfile'} eq "-") {
	print $doc->serialize(1);
} else {
	if ($config->{'compressoutput'} eq "yes") {
		$doc->setCompression($config->{'compressionlevel'});
	}
	$doc->toFile($config->{'outputfile'}, 1);
}

#######################################################################
# Author:     Foo Author
# Date:       Wannauchimmer
#
# Der Text.
# =====================================================================
#
sub MakeThatSingleItemThing {
	my($dbhash) = shift;
	my($newitem) = "";
	
	$newitem .= "From:    ".$dbhash->{'msg_from'}."\n".
	            "Date:    ".$dbhash->{'msg_date'}."\n\n".
	            $dbhash->{'msg_body'};
	$newitem .= "="x 72;
	$newitem .= "\n\n";
	return $newitem;
}

#######################################################################
# Load $maxthreads with $maxitemsperthread from the database
sub LoadDB {
	my $dbh = db_connect($config);
	my $threads_sth = $dbh->prepare(q{
		SELECT msg_thread, MAX(msg_received) 
		FROM messages
		WHERE msg_listid = ?
		GROUP BY msg_thread 
		ORDER BY max(msg_received) DESC
		LIMIT ?
	});
	$threads_sth->execute($listid, $config->{'maxthreads'});
	
	my $items_sth = $dbh->prepare(q{
		SELECT msg_from, msg_subject, msg_date, msg_body
		FROM messages
		WHERE msg_thread = ?
		AND msg_listid = ?
		ORDER BY msg_received
		LIMIT ?
	});
	
	my($dbthreads) = FetchAllRowsHashArrayRef($threads_sth);
	
	foreach(@$dbthreads) {
		$items_sth->execute($_->{'msg_thread'}, $listid, $config->{'maxitemsperthread'});
		$_->{'items'} = FetchAllRowsHashArrayRef($items_sth);
	}
	
	$dbh->disconnect;
	
	return $dbthreads;
}

#######################################################################
# I haven't written these and I don't question the code
sub FetchSingleRowHashRef ($) {
        my($sth) = shift;
        my(%row);
        
        $sth->bind_columns(\(@row{@{$sth->{NAME_lc}}})); # scary!
        return undef if (!$sth->fetch());
        
        return \%row;
}

sub FetchAllRowsHashArrayRef ($) {
        my($sth) = shift;
        my(%cur_row);
        my(@rows);

        $sth->bind_columns(\(@cur_row{@{$sth->{NAME_lc}}}));
        while ($sth->fetch()) {
                my(%row) = %cur_row;
                push(@rows, \%row);
        }
        
        return \@rows;
}
