fix double announcements
[raumzeitinfo.git] / wikibot.pl
blob66f792f882cd1f420548d438afc582dccc6faac3
1 #!/usr/bin/perl
3 use strict;
4 use warnings;
6 use 5.10.0;
8 use EV;
9 use POSIX;
10 use Getopt::Long;
11 use JSON::XS;
12 use Time::Piece;
13 use Time::Seconds;
14 use AnyEvent;
15 use AnyEvent::HTTP;
16 use AnyEvent::IRC::Client;
18 use Log::Log4perl qw/:easy/;
19 Log::Log4perl->easy_init($INFO);
21 $|++;
23 my %opt = (
24 channel => '#raumzeitlabor',
25 nick => 'RaumZeitInfo',
26 port => 6667,
27 ssl => 0,
28 server => 'irc.hackint.eu',
29 rejoin => 3600, # in seconds
32 my $api_url = 'http://rzl.so/w/api.php?action=query&list=recentchanges&rcprop=title|sizes|user|ids|timestamp&rclimit=10&rcshow=!minor&rctoponly&format=json';
34 my $irc = AnyEvent::IRC::Client->new;
35 $irc->enable_ssl() if $opt{ssl};
36 $irc->connect($opt{server}, $opt{port}, { nick => $opt{nick} });
38 $irc->reg_cb(registered => sub { INFO "connected to ".$opt{server}; });
40 $irc->reg_cb(join => sub {
41 my ($nick, $channel, $is_myself) = @_;
42 INFO "joined channel ".$opt{channel} if $is_myself;
43 });
45 # if we get kicked, we either rejoin after some time or leave the network
46 $irc->reg_cb(kick => sub {
47 my ($kicked_nick, $channel, $is_myself, $msg, $kicker_nick) = @_;
48 return unless $is_myself;
50 INFO "got kicked";
51 if ($opt{rejoin}) {
52 INFO "rejoining channel in ".$opt{rejoin}."s";
53 my $timer; $timer = AnyEvent->timer(
54 after => $opt{rejoin},
55 cb => sub {
56 undef $timer;
57 $irc->send_srv(JOIN => ($opt{channel}));
58 });
59 } else {
60 INFO "disconnecting";
61 $irc->disconnect;
63 });
65 $irc->reg_cb(disconnect => sub {
66 INFO "disconnected";
67 exit 1;
68 });
70 $irc->send_srv(join => ($opt{channel}));
72 my $lastupdate = gmtime;
73 $lastupdate -= 1 * ONE_MINUTE;
74 $lastupdate = $lastupdate->datetime."Z";
76 my $nextupdate = gmtime->datetime."Z";
78 my $w = AnyEvent->timer(
79 interval => 60,
80 cb => sub {
81 my $paged_api_url = $api_url;
82 $paged_api_url .= "&rcend=".$lastupdate."&rcstart=".$nextupdate;
83 INFO "fetching…";
84 http_get $paged_api_url, sub {
85 my ($body, $hdr) = @_;
86 if ($hdr->{Status} !~ /^2/) {
87 WARN "HTTP error: ".$hdr->{Status}.", reason: ".$hdr->{Reason};
90 my $json = decode_json($body);
91 INFO "fetched ".@{$json->{query}->{recentchanges}}." results";
92 foreach my $page (@{$json->{query}->{recentchanges}}) {
93 my $type = uc substr $page->{type}, 0, 1;
94 my $diff = $page->{newlen} - $page->{oldlen};
95 $diff = ($diff < 0 ? "" : $diff == 0 ? "+-" : "+").$diff;
96 my $title = $page->{title};
97 my $pageid = $page->{pageid};
98 my $oldid = $page->{old_revid};
99 my $revid = $page->{revid};
100 my $user = $page->{user};
102 # mediawiki timestamps are UTC, see https://www.mediawiki.org/wiki/Manual:Timestamp
103 my $time = Time::Piece->strptime($page->{timestamp}, "%Y-%m-%dT%H:%M:%SZ");
104 $time += $time->localtime->tzoffset;
105 $time = $time->strftime("%H:%M");
107 my $msg = "Wiki: [$type] \"$title\" ($diff) von $user um $time Uhr http://rzl.so/w/index.php?pageid=$pageid&diff=$revid&oldid=$oldid";
108 INFO $msg;
109 $irc->send_chan($opt{channel}, PRIVMSG => ($opt{channel}, $msg));
112 INFO "last update: $lastupdate";
113 $lastupdate = gmtime;
114 $lastupdate -= 1 * ONE_MINUTE;
115 $lastupdate = $lastupdate->datetime."Z";
116 $nextupdate = gmtime->datetime."Z";
117 INFO "next update: $lastupdate";
122 # if SIGINT is received, leave the network
123 my $s = AnyEvent->signal (signal => 'INT', cb => sub {
124 WARN "SIGINT received, disconnecting...";
125 $irc->disconnect("shutting down...");
128 EV::loop;