fix double announcements
[raumzeitinfo.git] / feed_ircbot.pl
blobc19116afe2aeb3c4b9cfd6ead6634e0aa296da17
1 #!/usr/bin/perl
3 use strict;
4 use warnings;
6 use EV;
7 use DateTime;
8 use Digest::SHA qw(sha256_hex);
9 use Getopt::Long;
10 use AnyEvent;
11 use AnyEvent::Feed;
12 use AnyEvent::IRC::Client;
14 use Log::Log4perl qw/:easy/;
15 Log::Log4perl->easy_init($INFO);
17 $|++;
19 my %opt = (
20 channel => '#raumzeitlabor',
21 nick => 'RaumZeitInfo',
22 port => 6667,
23 ssl => 0,
24 server => 'irc.hackint.eu',
25 rejoin => 3600, # in seconds
26 refresh => 300, # in seconds
29 my @feeds = (
30 'http://raumzeitlabor.de/feed',
31 'http://raumzeitlabor.de/w/index.php5?title=Spezial:Letzte_%C3%84nderungen&feed=atom',
32 'https://twitter.com/statuses/user_timeline/114430885.rss',
35 GetOptions(\%opt, 'channel=s', 'nick=s', 'port=i', 'server=s', 'rejoin=i', 'ssl=i');
37 INFO 'starting up';
39 my @feed_reader;
40 my $irc = new AnyEvent::IRC::Client;
41 $irc->enable_ssl() if $opt{ssl};
42 $irc->connect($opt{server}, $opt{port}, { nick => $opt{nick} });
44 $irc->reg_cb(registered => sub { INFO "connected to ".$opt{server}; });
46 $irc->reg_cb(join => sub {
47 my ($nick, $channel, $is_myself) = @_;
48 INFO "joined channel ".$opt{channel} if $is_myself;
49 });
51 # if we get kicked, we either rejoin after some time or leave the network
52 $irc->reg_cb(kick => sub {
53 my ($kicked_nick, $channel, $is_myself, $msg, $kicker_nick) = @_;
54 return unless $is_myself;
56 INFO "got kicked";
57 if ($opt{rejoin}) {
58 INFO "rejoining channel in ".$opt{rejoin}."s";
59 my $timer; $timer = AnyEvent->timer(
60 after => $opt{rejoin},
61 cb => sub {
62 undef $timer;
63 $irc->send_srv(JOIN => ($opt{channel}));
64 });
65 } else {
66 INFO "disconnecting";
67 $irc->disconnect;
69 });
71 $irc->reg_cb(disconnect => sub {
72 INFO "disconnected";
73 undef @feed_reader;
74 exit 1;
75 });
77 $irc->send_srv(join => ($opt{channel}));
79 my @old_entries;
81 foreach my $f (@feeds) {
82 my $init = 1;
83 my $reader = AnyEvent::Feed->new (
84 url => $f,
85 interval => $opt{refresh},
86 on_fetch => sub {
87 my ($feed_reader, $new_entries, $feed, $error) = @_;
89 if (defined $error) {
90 ERROR $error;
91 return;
94 # only post updates noticed after first refresh to prevent spam
95 if ($init) { $init--; return; };
97 for (@$new_entries) {
98 my ($hash, $entry) = @$_;
100 if (sha256_hex($entry->content) ~~ @old_entries) {
101 WARN "tried to send old item...";
102 } else {
103 while (scalar(@old_entries) > 100) {
104 shift(@old_entries);
107 push(@old_entries, sha256_hex($entry->content));
108 my $msg = "Update: \"".$entry->title."\" von ".$entry->author." um ".
109 $entry->issued->set_time_zone('local')->strftime("%H:%I")
110 ." Uhr (".$entry->id.")";
111 INFO $msg;
112 $irc->send_chan($opt{channel}, PRIVMSG => ($opt{channel}, $msg));
118 push @feed_reader, $reader;
121 # if SIGINT is received, leave the network
122 my $w = AnyEvent->signal (signal => 'INT', cb => sub {
123 WARN "SIGINT received, disconnecting...";
124 $irc->disconnect("shutting down...");
127 EV::loop;