💾 Archived View for gmn.clttr.info › sources › orrg.git › tree › orrg.pl.txt captured on 2024-05-10 at 10:56:54.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

#!/usr/bin/perl
# Copyright René Wagner 2020
# licenced under BSD 3-Clause licence
# https://src.clttr.info/rwa/orrg

use strict;
use URI::Escape;
use XML::FeedPP;
use HTML::Strip;
use DateTime;
use DateTime::Format::ISO8601;
use POSIX qw(strftime);
use lib 'lib/';
use orrg;

# enable UTF-8 mode for everything	
use utf8;
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';

if (!defined($ENV{'SERVER_PROTOCOL'}) || $ENV{'SERVER_PROTOCOL'} ne 'GEMINI')
{
	write_response('CGI_ERROR', '', undef);
}

my $query = lc(uri_unescape($ENV{'QUERY_STRING'}));

if ($query eq '' || $query !~ /^(https|gemini)\:\/\//) {
	write_response('INPUT', 'Paste the URI of the rss feed you want to read', undef);
}

write_response('SUCCESS', 'text/gemini', create_response($query));

exit;

sub create_response
{
	my ( $qs ) = @_;
	my @body = ();

	my $content = feed_get($qs);
	if ( !defined($content) || $content eq '' ) {
		push @body, ('# orrg error', '', 'The requested feed could not be loaded. :(', '', '=> '. $qs .' open feed in browser');
	} else {
		my $feed = feed_parse($content);

		if (defined($feed)) {
			recent_add($qs, trim_ws($feed->title));
			popular_add($qs, trim_ws($feed->title));

			push @body, '# '. trim_ws($feed->title);
			push @body, 'fetched '. strftime('%Y-%m-%dT%H:%M:%SZ', gmtime());
			push @body, '';
			$feed->description eq '' or push @body, trim_ws($feed->description);
			$feed->image eq '' or push @body, '=> '. $feed->image .' feed image';
			$feed->link eq '' or push @body, ('=> '.$feed->link.' open website', '');

			foreach my $it ($feed->get_item()) { push @body, @{item($it)};	}
		} else {
			push @body, ('# orrg error', '', 'The requested feed could be loaded but not parsed. :(', '', '=> '. $qs .' open feed in native client');
		}
	}
	push @body, ('', '', '=> ./index.pl [home]');
	return @body;
}

sub item
{
	my ($it) = @_;

	my $hs = HTML::Strip->new(emit_spaces => 0, auto_reset => 1);
	my @item = ();
	my $title = trim_ws($it->title);
	my $link = trim_ws($it->link);
	my $desc = $it->description;
	if ($desc ne '') {
		$desc =~ s/\<li\>/* /igm;
		$desc =~ s/\<h[1-2][^\>]+\>/### /igm;
		$desc =~ s/\<br \/\>/\r\n/igm;
		$desc =~ s/\<pre.*\>/\r\n```\r\n/igm;
		$desc =~ s/\<\/pre\>/\r\n```\r\n/igm;
		$desc = $hs->parse($desc);
	}
	push @item, (($desc ne '' && $desc ne $title) || $it->pubDate ne '')? '## '. $title : $title;
	if ($it->pubDate ne '') {
		my $dt = DateTime::Format::ISO8601->parse_datetime($it->pubDate);
		push @item, 'published '. strftime('%Y-%m-%dT%H:%M:%SZ', gmtime($dt->epoch));
		push @item, '';
	}
	if ($desc ne '' && $desc ne $title) {
		push @item, $desc;
	}
	$link eq '' or push @item, ('=> '.$link.' open entry in browser', '');

	return \@item;
}

sub trim_ws
{
	my ( $string ) = @_;
	$string =~ s/^\s+\*/*/igm;
	$string =~ s/\s+$//igm;
	$string =~ s/^\s+//igm;
	$string =~ s/^\r\n$//igm;
	return $string;
}

sub feed_get
{
	my ( $query ) = @_;

	my $content;
	if ( $query =~ /^https\:\/\// ) { $content = `wget -qO - $query`; }
	if ( $query =~ /^gemini\:\/\// ) {
		$content = `gmni -L -j once -i -N  $query`;
		$content =~ /20\W/ or return undef;
		$content =~ s/^[0-9]{0,2}\W.+\r\n//;
	}

	return $content;
}

sub feed_parse
{
	my ($content) = @_;

	my $feed = XML::FeedPP->new($content, -type => 'string', utf8_flag => 1);
	if (defined($feed)) { $feed->sort_item(); }
	return $feed;
}