Sports Headlines From Stuff.co.nz
#!/usr/bin/perl
use cPanelUserConfig;
#### Copyright 2003 and beyond by Kurt Melvin. You may not distibute this script in
#### any way, Thanks.
BEGIN {
unshift @INC, "libwww";
unshift @INC, "xmlparser/lib";
};
require "data/config.pl";
$::SSI_TEMPLATE = q(
{title}
{description}
) unless $::SSI_TEMPLATE;
package Gamma::Parser;
use XML::Parser;
sub new {
my ($class) = @_;
bless {}, $class;
};
sub get_items {
my ($self, $data) = @_;
$data =~ s/‘/`/g;
$data =~ s/’/'/g;
$data =~ s/̶[01];/"/g;
$data =~ s/̳[45];/ /g;
$data =~ s/̵[12];/-/g;
my $items = [];
my $parser = new XML::Parser(Handlers => {
Start => sub { $self->handle_start($items, @_) },
End => sub { $self->handle_end($items, @_) },
Char => sub { $self->handle_char($items, @_) },
});
$parser->parse($data);
return $items;
};
sub handle_start {
my ($self, $items, $parser, $element) = @_;
if ($element eq "channel") {
$self->{channel_name} = "";
$self->{ctitle} = 1;
};
if ($element eq "item") {
$self->{item} = {
title => "",
description => "",
url => "",
channel_name => $self->{channel_name},
};
};
$self->{field} = $element;
};
sub handle_end {
my ($self, $items, $parser, $element) = @_;
if ($element eq "item") {
push @$items, $self->{item};
$self->{item} = {
title => "",
description => "",
url => "",
channel_name => $self->{channel_name},
};
};
$self->{ctitle} = undef if ($self->{ctitle} and $element eq "title");
$self->{field} = "";
};
sub handle_char {
my ($self, $items, $parser, $data) = @_;
$self->{item}->{title} .= $data if $self->{field} eq "title";
$self->{channel_name} .= $data if $self->{field} eq "title" and $self->{ctitle};
$self->{item}->{description} .= $data if $self->{field} eq "description";
$self->{item}->{url} .= $data if $self->{field} eq "link";
}
package Gamma::App;
use CGI;
use XIT::XIT;
use LWP::Simple;
sub new {
my ($class) = @_;
my $cgi = new CGI;
bless { cgi => $cgi }, $class;
};
sub main {
my ($self) = @_;
$self->fetch_channels_and_categories;
my $random = $self->{cgi}->param("random");
$random = $self->{cgi}->param("shuffle") unless $random;
my $channel = $self->{cgi}->param("channel");
if ($channel =~ /^user-(\d+)\.xml$/) {
$channel = $1;
}
my $category = $self->{cgi}->param("cat");
$category = 0 unless $category;
$category = $self->{channels}->{$channel}->{category_id}
if $channel;
my $start = $self->{cgi}->param("start");
$start = 0 if $start < 0;
my $results = $self->{cgi}->param("results") || $::DEFAULT_RESULTS;
$results = $::MIN_RESULTS if $results < $::MIN_RESULTS;
$results = $::MAX_RESULTS if $results > $::MAX_RESULTS;
my $keywords = $self->{cgi}->param("keywords");
my $search_mode = $self->{cgi}->param("mode");
$search_mode = "all" unless $search_mode =~ /^all|any|exact$/;
my $items = $self->fetch_items($channel, $category);
$items = $self->filter_items($items, $keywords, $search_mode);
$items = $self->shuffle_items($items, $random);
$items = $self->limit_items($items, $start, $results);
$self->output($items, $self->{categories}->{$category}->{template});
}
sub fetch_channels_and_categories {
my ($self) = @_;
$self->{channels} = {};
$self->{categories} = {
0 => {
id => 0,
title => 'default',
description => '',
template => $::SSI_TEMPLATE,
expire => $::CACHE_EXPIRE,
channels => [],
}
};
open(CATEGORIES, ") {
chomp($line);
my @values = split(/\|/, $line);
my ($id, $title, $description, $template, $expire) = @values;
$self->{categories}->{$id} = {
id => $id,
title => $title,
description => $description,
template => $template,
expire => $expire,
channels => [],
};
}
open(CHANNELS, ") {
chomp($line);
my @values = split(/\|/, $line);
my ($id, $title, $description, $rss_url, $html_url, $category_id) = @values;
$category_id = 0 unless $category_id;
$self->{channels}->{$id} = {
id => $id,
title => $title,
description => $description,
rss_url => $rss_url,
html_url => $html_url,
category_id => $category_id,
};
push @{$self->{categories}->{$category_id}->{channels}}, $id;
}
close(CHANNELS);
}
sub fetch_items {
my ($self, $channel, $category) = @_;
my @channels;
if ($channel) {
@channels = ($channel);
}
elsif ($category ne '') {
@channels = @{$self->{categories}->{$category}->{channels}};
}
else {
@channels = keys %{$self->{channels}};
}
my $items = [];
for my $channel (@channels) {
push @$items, @{$self->fetch_channel($channel)};
}
return $items;
}
sub filter_items {
my ($self, $items, $keywords, $mode) = @_;
return $items if $keywords eq "";
my @expr;
@expr = ('\W'.quotemeta($keywords).'\W') if $mode eq 'exact';
@expr = (map { '\W'.quotemeta($_).'\W' } split(/\s+/, $keywords)) if $mode eq 'all';
@expr = (join('|', (map { '\W'.quotemeta($_).'\W' } split(/\s+/, $keywords))))
if $mode eq 'any';
for my $expr (@expr) {
my $new_items = [];
for my $item (@$items) {
my $text = " ".$item->{title}." ".$item->{description}." ";
$text =~ s/\s+/ /g;
push @$new_items, $item if $text =~ /$expr/is;
}
$items = $new_items;
}
return $items;
}
sub shuffle_items {
my ($self, $items, $random) = @_;
return $items unless $random and scalar(@$items);
for my $index (0 .. scalar(@$items)-1) {
my $new_index = int(rand(scalar(@$items)));
my $item = $items->[$index];
my $new_item = $items->[$new_index];
$items->[$index] = $new_item;
$items->[$new_index] = $item;
}
return $items;
}
sub limit_items {
my ($self, $items, $start, $results) = @_;
return [splice @$items, $start, $results];
}
sub fetch_channel {
my ($self, $id) = @_;
my $channel_data = $self->get_channel_data($id);
return [] unless $channel_data;
my $parser = new Gamma::Parser;
return eval { $parser->get_items($channel_data) };
};
sub get_channel_data {
my ($self, $id) = @_;
my $channel = "user-$id.xml";
$channel =~ s/\\\/\|//g;
my $expire = $self->{categories}->{$self->{channels}->{$id}->{category_id}}->{expire};
my $xml_url = $self->{channels}->{$id}->{rss_url};
my $data;
my $filename = "data/cache/" . $channel;
if (-f $filename) {
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
if (time() - $mtime < $expire) {
open(XML, "<$filename");
my $first_line = ;
$data = do { local $/; };
close(XML);
}
}
if ($data eq "") {
$data = get($xml_url);
open(XML, ">$filename");
print XML "$xml_url\n";
print XML $data;
close(XML);
};
return $data;
};
sub output {
my ($self, $items, $template) = @_;
$template =~ s/\\n/\n/g;
my $results = [];
for $item (@$items) {
my $text = $template;
$text =~ s/{url}/$item->{url}/gi;
$text =~ s/{title}/$item->{title}/gi;
$text =~ s/{description}/$item->{description}/gi;
push @$results, $text;
}
my $template = new XIT::Template;
my $body = $template->substitute("templates/ssi.html", results => $results);
print "Content-Type: text/html\n\n";
print $body;
};
package Gamma::Run;
my $app = new Gamma::App;
$app->main;
1;
|