From badede80903cc0ea8e4a1bdc9c1397e38e70e34d Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Fri, 24 Aug 2018 03:02:22 -0400 Subject: add slacktopic.pl --- slacktopic.pl | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 slacktopic.pl 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(); -- cgit v1.2.3