aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slacktopic.pl152
1 files changed, 152 insertions, 0 deletions
diff --git a/slacktopic.pl b/slacktopic.pl
new file mode 100644
index 0000000..22b8c40
--- /dev/null
+++ b/slacktopic.pl
@@ -0,0 +1,152 @@
+#!/usr/bin/perl
+
+# irssi script. updates the ##slackware topic any time there's a security
+# update in Pat's ChangeLog. Depends on an external shell script,
+# slack_last_update.sh.
+
+# Plan of action:
+# - When this script is loaded, it uses an irssi timer to check
+# for updates periodically.
+# - When there's an update, it asks for ops in the channel if not already
+# opped, changes the topic (replacing only the [YYYY-MM-DD] part), then
+# if we weren't already opped, it deops. If we *were* already opped,
+# it doesn't deop (that would be *annoying*).
+
+# Assumptions made:
+# - By the time the first check happens ($update_frequency sec after
+# script is loaded, or whenever it's run manually), we will be logged
+# into services.
+# - We have enough ChanServ access on the channel to set the topic via
+# ChanServ's topic command (flag +t in access list).
+
+# References:
+# https://raw.githubusercontent.com/irssi/irssi/master/docs/perl.txt
+# http://wiki.foonetic.net/wiki/ChanServ_Commands
+
+use warnings;
+use strict;
+
+use Irssi qw/
+ command
+ timeout_add
+ timeout_add_once
+ timeout_remove
+ window_find_name
+ window_find_item
+ windows
+ channel_find
+ command_bind
+/;
+
+our $VERSION = "0.1";
+our %IRSSI = (
+ authors => 'Urchlay',
+ contact => 'Urchlay on FreeNode ##slackware',
+ name => 'slacktopic',
+ description => 'Updates ##slackware /topic whenever there\'s a ' .
+ 'security update in the Slackware ChangeLog.',
+ license => 'WTFPL',
+ url => 'none',
+);
+
+# External script. Assume it's in $PATH. Could hardcode the full
+# path instead.
+our $update_script = "slack_last_update.sh";
+
+# Where the script stores the last update date.
+our $update_file = "$ENV{HOME}/.slack_last_update";
+
+# What channel's /topic are we updating?
+our $update_channel = "##slackware";
+
+# Seconds between update checks. Every check executes $update_script, which
+# talks to ftp.slackware.com, so be polite here.
+# TODO: make this an irssi setting?
+our $update_frequency = 600;
+
+# Print debugging message in local irssi window?
+our $DEBUG = 1;
+
+sub echo {
+ command("/echo $_") for @_;
+}
+
+sub errmsg {
+ my (undef, $file, $line) = caller;
+ echo("$file:$line: $_") for @_;
+}
+
+sub debugmsg {
+ return unless $DEBUG;
+ my (undef, $file, $line) = caller;
+ echo("$file:$line: $_") for @_;
+}
+
+sub init {
+ debugmsg("init() called");
+
+ # Command for manual updates.
+ command_bind("slacktopic", "update_check");
+
+ # Check once at script load.
+ update_check();
+
+ # Also, automatically run it on a timer. 3rd argument unused here.
+ timeout_add($update_frequency * 1000, "update_check", 0);
+}
+
+sub update_check {
+ debugmsg("update_check() called");
+
+ # Don't do anything if we're not joined to the channel already.
+ my $chan = channel_find($update_channel);
+ debugmsg("not joined to $update_channel") unless $chan;;
+ return unless $chan;
+
+ # Get the date of the last update.
+ my $new_date = exec_update();
+ if(not defined $new_date) {
+ errmsg("couldn't get new date, not updating topic");
+ return;
+ }
+
+ # This should never happen, but...
+ if($new_date !~ /^\d\d\d\d-\d\d-\d\d/) {
+ errmsg("$update_script result isn't a valid date: $new_date");
+ return;
+ }
+
+ # Get old topic, replace the date with the new one.
+ debugmsg("\$new_date is: $new_date");
+ my $t = $chan->{topic};
+ $t =~ s,\[\d\d\d\d-\d\d-\d\d\],[$new_date],;
+
+ # Don't do anything if the topic's already correct.
+ if(if $t eq $chan->{topic}) {
+ debugmsg("topic already correct, not doing anything");
+ return;
+ }
+
+ # Ask ChanServ to change the topic for us. We don't need +o in
+ # the channel, so long as we're logged in to services and have +t.
+ debugmsg("asking ChanServ to update the topic");
+ $chan->{server}->send_raw("ChanServ topic $update_channel :$t");
+}
+
+sub exec_update {
+ debugmsg("exec_update() called");
+ open my $fh, "$update_script|" or do {
+ errmsg("couldn't execute '$update_script': $!");
+ return undef;
+ };
+
+ chomp(my $result = <$fh>);
+ close $fh;
+ my $status = $? >> 8;
+
+ debugmsg("$update_script exit status: $status, result '$result'");
+ return $result;
+}
+
+# main()
+init();