aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slacktopic.pl137
1 files changed, 89 insertions, 48 deletions
diff --git a/slacktopic.pl b/slacktopic.pl
index ea450f1..e45d094 100644
--- a/slacktopic.pl
+++ b/slacktopic.pl
@@ -1,16 +1,20 @@
#!/usr/bin/perl
-# irssi script. updates the ##slackware topic any time there's a security
-# update in the Slackware ChangeLog.
+# slacktopic.pl, by B. Watson <yalhcru@gmail.com>.
+# Licensed under the WTFPL. See http://www.wtfpl.net/txt/copying/ for details.
+
+# This is an irssi script that updates the ##slackware topic any time
+# there's a new update in the Slackware ChangeLog. Place the script in
+# your ~/.irssi/scripts/autorun/ dir.
# At script startup, and again every $update_frequency seconds, we
# check for updates like so:
# - Exec a curl process to get the first part of the ChangeLog
-# and extract the date from it.
-# - Extract the date from the current /topic.
-# - If the /topic has a date, and if it's different, update the
-# /topic. Only the date (inside []) is changed, all the other
-# stuff is left as-is.
+# and extract the new date from it.
+# - Extract the old date from the current /topic.
+# - If the /topic has an old date, and if it's different from the new
+# date, update the /topic (really, get ChanServ to do it). Only the date
+# (inside []) is changed, all the other stuff is left as-is.
# Assumptions made:
# - Every new ChangeLog entry is a security fix. This is almost
@@ -26,10 +30,16 @@
# ChanServ's topic command (flag +t in access list). Again, no
# harm done, but no topic updates either.
-# TODO: send debug/error/status messages to window #1, including
-# successful topic updates. Otherwise, I'll never know when this script
-# is working (the topic gets changed by ChanServ, I can't tell if that
-# was my script doing it or another op doing it manually...)
+# Notes:
+# - This script would possibly work for other FreeNode channels that track
+# a ChangeLog and update the /topic when there's a change. You'd want
+# to at least change $update_channel and $update_cmd. If you're not on
+# FreeNode, more surgery will be required (if there's a way to change
+# the /topic by talking to a 'services' bot, it should be possible).
+# - Please don't try to talk me into using LWP and one of the Date::
+# modules in place of executing curl and date. Slackware doesn't ship
+# them, plus they're huge and I don't want to keep them loaded in
+# irssi all the time.
# References:
# https://raw.githubusercontent.com/irssi/irssi/master/docs/perl.txt
@@ -38,34 +48,33 @@
use warnings;
use strict;
+# I really wish I could just say 'use Irssi ":all"' here.
use Irssi qw/
+ channel_find
command
+ command_bind
+ signal_add_last
timeout_add
timeout_add_once
timeout_remove
window_find_name
- window_find_item
- windows
- window_find_refnum
- channel_find
- command_bind
- pidwait_add
- signal_add_last
/;
our $VERSION = "0.1";
our %IRSSI = (
- authors => 'Urchlay',
- contact => 'Urchlay on FreeNode ##slackware',
+ authors => 'B. Watson',
+ contact => 'yalhcru@gmail.com or Urchlay on FreeNode ##slackware',
name => 'slacktopic',
description => 'Updates ##slackware /topic whenever there\'s a ' .
'security update in the Slackware ChangeLog.',
license => 'WTFPL',
- url => 'none',
+ url => 'http://urchlay.naptime.net/repos/misc-scripts/',
);
+### Configurables.
+
# TODO: make some or all of these config variables into irssi
-# settings. Probably overkill, this script is niche-market (probably
+# settings? Probably overkill, this script is niche-market (probably
# nobody but the author will ever run it...)
# Print verbose debugging messages in local irssi window?
@@ -76,7 +85,10 @@ our $DEBUG = 1;
#our $FAKE = '9999-99-99';
our $FAKE = 0;
-# Slackware ChangeLog URL. Version number is hardcoded here.
+# Slackware ChangeLog URL. Version number is hardcoded here. Notice it's
+# the plain http URL, not https (which doesn't even exist). Actually,
+# ftp would also work, but then you got the whole passive vs. active
+# firewall mess.
our $changelog_url =
"http://ftp.slackware.com/pub/slackware/slackware64-14.2/ChangeLog.txt";
@@ -85,12 +97,17 @@ our $changelog_url =
our $cmd_timeout = 60;
# $update_cmd will write its output here. It'll be in YYYY-MM-DD form,
-# which is just what's needed for the /topic.
+# which is just what's needed for the /topic. I prefer to keep this
+# in ~/.irssi, but it might be better in /tmp (especially if /tmp is
+# a tmpfs).
our $cmd_outfile = "$ENV{HOME}/.irssi/slack_update.txt";
# We /exec this to get the first line of the ChangeLog. So long as Pat
# follows his standard conventions, bytes 0-28 are the first line of
-# the ChangeLog.
+# the ChangeLog. If you *really* wanted to, you could use wget instead
+# of curl, but it doesn't have the --range option... All the business
+# with rm and mv is to (try to) avoid ever reading the file when it's
+# only partially written.
our $curl_args = "--silent --range 0-28 --max-time $cmd_timeout";
our $update_cmd = "rm -f $cmd_outfile ; " .
"curl $curl_args $changelog_url |" .
@@ -112,11 +129,14 @@ our $server_regex = qr/\.freenode\.(org|net)$/;
# talks to ftp.slackware.com, so be polite here.
our $update_frequency = 600;
-# Bookkeeping stuffs.
+### End of configurables.
+
+### Bookkeeping stuffs.
our $timeout_tag;
our $child_proc;
our $log_window;
+### Functions.
# Print a message to the status window, if there is one. Otherwise print
# it to whatever the active window happens to be. Use this or one of
# (err|debug|log)msg for all output, don't use regular print or warn.
@@ -134,9 +154,7 @@ sub errmsg {
}
sub debugmsg {
- return unless $DEBUG;
- my (undef, $file, $line) = caller;
- echo("$file:$line: $_") for @_;
+ goto &errmsg if $DEBUG;
}
sub logmsg {
@@ -161,17 +179,22 @@ sub init {
command_bind("slacktopic", "start_update");
# Check once at script load.
- start_update();
+ initial_update();
- # Also, automatically run it on a timer. 3rd argument unused here.
- timeout_add($update_frequency * 1000, "start_update", 0);
+ if($update_frequency < 60) {
+ # Typo protection. Ugh.
+ errmsg("You didn't really mean to set \$update_frequency to " .
+ "$update_frequency seconds, did you? Not starting timer. " .
+ "Fix the script and reload it.");
+ } else {
+ # Also, automatically run it on a timer. 3rd argument unused here.
+ timeout_add($update_frequency * 1000, "start_update", 0);
+ }
}
-# Start the update process.
-sub start_update {
- debugmsg("start_update() called");
-
- # Don't do anything if we're not joined to the channel already.
+# Return a Channel (always true) if we're joined to the correct channel,
+# otherwise return undef (false).
+sub get_channel {
my $chan = channel_find($update_channel);
if(!$chan) {
errmsg("not joined to $update_channel");
@@ -185,7 +208,28 @@ sub start_update {
return;
}
- exec_update();
+ return $chan;
+}
+
+# First update might need to be delayed. Usually we're being autoloaded at
+# irssi startup, and we might get called before autojoining the channel,
+# and/or before being logged in to services. Hard-coded 10 sec here. If
+# FreeNode or your ISP is being slow, the first update still might
+# fail. Oh well.
+sub initial_update {
+ if(get_channel()) {
+ start_update();
+ } else {
+ timeout_add_once(10 * 1000, "start_update", 0);
+ }
+}
+
+# Start the update process.
+sub start_update {
+ debugmsg("start_update() called");
+
+ # Don't do anything if we're not joined to the channel already.
+ exec_update() if get_channel();
}
# Called when an /exec finishes.
@@ -205,11 +249,12 @@ sub finish_update {
undef $child_proc;
}
- my $chan = channel_find($update_channel);
- if(!$chan) {
- debugmsg("not joined to $update_channel");
- return;
- }
+ # ChanServ would let us change the topic even if we weren't in
+ # the channel, but let's not do that. For one thing, it's a PITA
+ # to retrieve the old topic, if we're not in the channel.
+ # No debugmsg here, get_channel() already did it.
+ my $chan = get_channel();
+ return unless $chan;
# Get the date of the last update.
my $new_date;
@@ -217,7 +262,6 @@ sub finish_update {
errmsg("$cmd_outfile not found, update command failed");
return;
};
-
chomp($new_date = <$fh>);
close $fh;
$new_date ||= "";
@@ -273,10 +317,7 @@ sub exec_update {
1000 * ($cmd_timeout + 2),
'update_timed_out',
0); # last arg is unused
-
- # is this really necessary? seems it isn't.
- #pidwait_add($child_proc->{pid});
}
-# main()
+### main()
init();