All pastes #24420 Raw Edit

Untitled

public text v1 · immutable
#24420 ·published 2005-10-02 02:29 UTC
rendered paste body
#!/usr/bin/perl -w
# Petr Baudis (c) 2004, public domain
# Slightly inspired by Stefan "tommie" Tomanek's newsline.pl.
# RSS->IRC gateway

use strict;

### Configuration section.
# In our example setup, we are going to deliver Slashdot headlines.
use vars qw ($nick $server $port $channel $rss_url $refresh);

$nick = 'slashrss';
$server = 'irc.freenode.net';
$port = 6667;
$channel = '#irchacks';
$rss_url = 'http://www.slashdot.org/slashdot.rss';
$refresh = 30*60; # in seconds; Slashdot allows refresh max. once per 30 minutes

### Preamble.
use POSIX;
use Net::IRC;
use LWP::UserAgent;
use XML::RSS;

### Connection initialization.
use vars qw ($irc $conn);
$irc = new Net::IRC;
print "Connecting to server ".$server.":".$port." with nick ".$nick."...\n";
$conn = $irc->newconn (Nick => $nick, Server => $server, Port => $port,
                       Ircname => 'RSS->IRC gateway IRC hack');

# Connect event handler - we immediately try to join our channel.
sub on_connect {
  my ($self, $event) = @_;
  print "Joining channel ".$channel."...\n";
  $self->join ($channel);
}
$conn->add_handler ('welcome', \&on_connect);

# Joined the channel, so log that.
sub on_joined {
  my ($self, $event) = @_;
  print "Joined channel ".$channel."...\n";
}
$conn->add_handler ('endofnames', \&on_joined);

# It is a good custom to reply to the CTCP VERSION request.
sub on_cversion {
  my ($self, $event) = @_;
  $self->ctcp_reply ($event->nick, 'VERSION RSS->IRS gateway IRC hack');
}
$conn->add_handler ('cversion', \&on_cversion);

### The RSS feed
use vars qw (@items);
# Fetches the RSS from server and returns a list of RSS items.
sub fetch_rss {
  my $ua = LWP::UserAgent->new (env_proxy => 1, keep_alive => 1, timeout => 30);
  my $request = HTTP::Request->new('GET', $rss_url);
  my $response = $ua->request ($request);
  return unless ($response->is_success);
  my $data = $response->content;
  my $rss = new XML::RSS ( );
  $rss->parse($data);
  foreach my $item (@{$rss->{items}}) {
    # Make sure to strip any possible newlines and similiar stuff.
    $item->Feed Syndicated RSS News =~ s/\s/ /g;
  }
  return @{$rss->{items}};
}

# Attempts to find some newly appeared RSS items.
sub delta_rss {
  my ($old, $new) = @_;

  # If @$old is empty, it means this is the first run and 
    we will therefore not do anything.
  return ( ) unless ($old and @$old);

  # We take the first item of @$old and find it in @$new. 
    Then anything before its position in @$new are the 
    newly appeared items which we return.
  my $sync = $old->[0];

  # If it is at the start of @$new, nothing has changed.
  return ( ) if ($sync->Feed Syndicated RSS News eq $new->[0]->Feed Syndicated RSS News);

  my $item;
  for ($item = 1; $item < @$new; $item++) {
    # We are comparing the titles which might not be 100% reliable but RSS
    # streams really should not contain multiple items with same title.
    last if ($sync->Feed Syndicated RSS News eq $new->[$item]->Feed Syndicated RSS News);
  }
  return @$new[0 .. $item - 1];
}

# Check RSS feed periodically.
sub check_rss {
  my (@new_items);
  print "Checking RSS feed [".$rss_url."]...\n";
  @new_items = fetch_rss ( );
  if (@new_items) {
    my @delta = delta_rss (\@items, \@new_items);
    foreach my $item (reverse @delta) {
      $conn->privmsg ($channel, '"'.$item->Feed Syndicated RSS News.'" :: '.$item->{link});
    }
    @items = @new_items;
  }
  alarm $refresh;
}

$SIG{ALRM} = \&check_rss;
check_rss( );

# Fire up the IRC loop.
$irc->start;