#!/usr/bin/perl # gem2atom.pl - convert gemfeed to Atom use 5.36.0; use DateTime::Format::Strptime; use Getopt::Long; use Net::Gemini; use XML::Atom; use XML::Atom::Entry; use XML::Atom::Feed; my $max_posts = ~0; GetOptions( 'b=s' => \my $base_url, 'M=i' => \$max_posts ) or exit 1; die "Usage: $0 -b base_url [gemfeed-file|-]\n" unless defined $base_url; my ( $feed, $feed_title, $header ); $XML::Atom::DefaultVersion = "1.0"; my $entry_count = 1; while ( my $line = readline ) { unless ( defined $feed_title ) { if ( $line =~ m/^#\s*(.+)/ ) { $feed_title = $1; } else { next; } } if ( $line =~ m/^=>\s*(\S+)\s*([0-9-]{10})\s*(.+)/ ) { my ( $entry_path, $entry_date, $entry_title ) = ( $1, $2, $3 ); eval { my $dt = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d', time_zone => 'UTC', on_error => 'croak', ); $dt->parse_datetime($entry_date); 1; } or die "invalid date '$entry_date' at $ARGV:$.\n"; unless ( defined $feed ) { $feed = XML::Atom::Feed->new; $feed->title($feed_title); my $link = XML::Atom::Link->new; $link->rel('alternate'); $link->href($base_url); $feed->add_link($link); $feed->updated( DateTime->now->strftime('%Y-%m-%dT%H:%M:%SZ') ); } my $entry = XML::Atom::Entry->new; $entry->title($entry_title); my $link = XML::Atom::Link->new; $link->rel('alternate'); $link->href( URI->new_abs( $entry_path, $base_url )->canonical ); $entry->add_link($link); $entry->updated( $entry_date . 'T12:00:00Z' ); $feed->add_entry($entry); last if ++$entry_count > $max_posts; } } continue { last if eof; # only the first file given in ARGV } print $feed->as_xml if defined $feed;