commit - 3af4a1f76a207c8113cce7539b513a3af26dff8d
commit + 16d0d03f980f192b1d5fbb3efbce9ed1aaf2f1ed
blob - 9579989b001f202a240eeb511659dd4d28608520
blob + 7ae4d09317a961dd6028db9384ccd6f4abd07b84
--- mata_bot.pl
+++ mata_bot.pl
CONNECT_TIMEOUT => 60,
CRLF => 2, # RFC 2812
DEFAULT_PORT => 6667,
+ DEFAULT_RSS => 0,
DEFAULT_TLS => 0,
HOSTMAX => 63, # RFC 2812
IRCMAX => 512,
NBIBLE => 31102,
NQURAN => 6348,
RECONN_SLEEP => 60,
+ RSS_CHECK_TIME => 3600,
SOCK_TIMEOUT => 10,
};
my $DEFAULT_CHAN = '#testmatabot';
my $MYREAL = 'death to technomage!!';
my $MYUSER = 'mata_bot_beta4';
my $NICKRE = qr/mata_?bo[ity]+/i;
+my $RSSLINK = 'https://analognowhere.com/feed/rss.xml';
+my $RSSMEM_PATH = 'rss';
sub randint {
my($min, $max) = @_;
}
}
+sub sendnews {
+ state $lastlink;
+ my $rssmem = shift;
+ my ($homepage, $r);
+ my (@matches, @replies);
+
+ $r = HTTP::Tiny->new->get($RSSLINK);
+ unless ($r->{success}) {
+ logger(LOG_WARN, 'GET ${RSSLINK}: $r->{status} $r->{reason}');
+ return ();
+ }
+ unless (length $r->{content}) {
+ logger(LOG_WARN, 'GET ${RSSLINK}: empty HTTP response');
+ return ();
+ }
+ unless (defined($lastlink)) {
+ seek($rssmem, 0, 0);
+ chomp($lastlink = <$rssmem>);
+ }
+ $homepage = ($r->{content} =~ m,<channel>.*?<link>([^<]+)</link>,s) ? $1 : 'website';
+ while ($r->{content} =~ m,\G.*?<item>.*?<title>([^<]+)</title>.*?<link>([^<]+)</link>.*?</item>,gs) {
+ push @matches, {title => $1, link => $2};
+ }
+ if (@matches) {
+ my $i;
+
+ if (defined($lastlink)) {
+ for ($i = 0; $i < @matches; $i++) {
+ last if $matches[$i]->{'link'} eq $lastlink;
+ }
+ } else {
+ $i = @matches;
+ }
+ for ($i--; $i >= 0; $i--) {
+ push @replies, "RSS: $matches[$i]->{'link'} | $matches[$i]->{'title'}";
+ if ($i > 2) {
+ push @replies, "RSS: found " . ($i-1) . " new items in between. Visit ${homepage} for more...";
+ $i = 1;
+ }
+ }
+ truncate($rssmem, 0);
+ seek($rssmem, 0, 0);
+ say $rssmem ($lastlink = $matches[0]->{'link'});
+ $rssmem->flush;
+ }
+ return @replies;
+}
+
sub evasdrop {
- my ($s, $host, $chan, $lists) = @_;
- my ($msgtime, $msgmax, $pingsent, $pingtime, $prefixlen, $priv);
+ my ($s, $rssmem, $lists, ($chan, $host, $rss)) = @_;
+ my ($firstrss, $msgmax, $msgtime, $pingsent, $pingtime, $priv, $rsstime);
+ $firstrss = 1;
$pingsent = 0;
$priv = "PRIVMSG ${chan} :";
$msgmax = IRCMAX - length(":${MYNICK}!~${MYUSER}\@ ${priv}")
- HOSTMAX - CRLF; # conservative max message length heuristic
- $msgtime = $pingtime = time;
+ $rsstime = $msgtime = $pingtime = time;
while (1) {
if ($pingsent) {
if (time - $pingtime > MAX_LAG) {
$pingsent = 1;
$pingtime = time;
}
+ if ($rss and ($firstrss || time - $rsstime > RSS_CHECK_TIME)) {
+ foreach (sendnews($rssmem)) {
+ sendmsg($s, $priv . substr($_,0,$msgmax));
+ }
+ $rsstime = time;
+ $firstrss = 0 if $firstrss;
+ }
defined($_ = recvmsg($s)) or return;
next if not length;
$msgtime = time;
}
sub usage {
- say STDERR "usage: ${0} [-d|-v] [-t] [-b path] [-e path] [-h host] [-j join] [-p port] [-q path]";
+ say STDERR "usage: ${0} [-d|-v] [-r] [-t] [-b path] [-e path] [-h host] [-j join] [-p port] [-q path]";
exit 1;
}
sub init {
my ($path_ball, $path_helo, $path_quot);
+ my $rssmem;
my %opts;
@_ = @ARGV;
while (@_) {
$_ = shift;
if (/^-d$/) { logger(LOG_DEBUG) }
+ elsif (/^-r$/) { $opts{'rss'} = 1 }
elsif (/^-t$/) { $opts{'tls'} = 1 }
elsif (/^-v$/) { logger(LOG_WARN) }
elsif (@_ < 1) { usage() }
$opts{'chan'} //= $DEFAULT_CHAN;
$opts{'host'} //= $DEFAULT_HOST;
$opts{'port'} //= DEFAULT_PORT;
+ $opts{'rss'} //= DEFAULT_RSS;
$opts{'tls'} //= DEFAULT_TLS;
open(my $ball_file, '<', $path_ball // $DEFAULT_PATH_BALL)
or die "couldn't open ${path_ball}: $!";
or die "couldn't open ${path_quot}: $!";
chomp(my @quot = <$quot_file>);
close $quot_file or die "${quot_file}: $!";
- return \%opts, [
+ if ($opts{'rss'}) {
+ open($rssmem, '+>>', $RSSMEM_PATH)
+ || die "couldn't open ${RSSMEM_PATH}: $!";
+ }
+ return $rssmem, \%opts, [
\@ball,
\@helo,
\@quot,
];
}
-my ($opts, $lists) = init();
+my ($rssmem, $opts, $lists) = init();
while (1) {
my ($sock, $addr);
sendmsg($s, "NICK ${MYNICK}");
sendmsg($s, "WHO ${MYNICK}");
sendmsg($s, "JOIN $opts->{'chan'}");
- evasdrop($s, $opts->{'host'}, $opts->{'chan'}, $lists);
+ evasdrop($s, $rssmem, $lists, @$opts{'chan', 'host', 'rss'});
sendmsg($s, 'QUIT');
$sock->close();
} else {