[[!template id=plugin name=irker author="[[anarcat]]"]]
[[!tag type/special-purpose]]

This plugin will configure your wiki to send IRC notifications using the [irker](http://www.catb.org/esr/irker/) notification bot.

It is fairly simple and requires no configuration but installation of the irker package. For template configuration, patches from [Debian bug #824512](https://bugs.debian.org/824512) are necessary. Note that they have been factored into irker 2.18.

[[!format perl """
package IkiWiki::Plugin::irker;

use warnings;
use strict;
use IkiWiki 3.00;

sub import {
    hook(type => "getsetup", id => "irker", call => \&getsetup);
    hook(type => "checkconfig", id => "branchable", call => \&checkconfig,
         first => 1);
    hook(type => "genwrapper", id => "irker", call => \&genwrapper,
         last => 1);
}

sub getsetup() {
	return
		plugin => {
			safe => 0,
			rebuild => undef,
			section => "core",
		},
		irker_channels => {
			type => "string",
			example => ['ircs://irc.example.com/example'],
			description => "IRC channels to send notifications to",
			safe => 1,
			rebuild => 0,
		},
		irker_template => {
			type => "string",
			example => "'%(bold)s%(project)s:%(reset)s %(green)s%(author)s%(reset)s %(repo)s:%(yellow)s%(branch)s%(reset)s * %(bold)s%(rev)s%(reset)s / %(bold)s%(files)s%(reset)s: %(logmsg)s %(brown)s%(url)s%(reset)s",
			description => "Template to use for messages. Only supported with patch from https://bugs.debian.org/824512",
			safe => 1,
			rebuild => 0,
		},
		irker_hook => {
			type => "string",
			example => "irkerhook-git",
			description => 'Hook to setup for notifications, will look in $PATH if File::Which is available, otherwise use absolute path.',
			safe => 1,
			rebuild => 0,
		},
}

sub checkconfig {
    use URI; # ikiwiki Depends on it
    foreach my $channel (@{$config{'irker_channels'}}) {
        my $uri = URI->new( $channel );
        # inspired by http://stackoverflow.com/a/2599378/1174784
        # and http://stackoverflow.com/a/4953329/1174784
        if (!$uri->scheme || $uri->path =~ m/^([#&]?[^\x07\x2C\s]{,200})/) {
            error("$channel is not a valid IRC channel URI");
        }
    }
    # check if hook exists
    if (-x $config{irker_hook}) {
        # shortcut: already configured
        return;
    }
    eval q{use File::Which};
    # check with which, i available
    if (!$@) {
        my $hook;
        if (!defined $config{'irker_hook'}) {
            $config{'irker_hook'} = 'irkerhook-git';
        }
        $hook = which($config{'irker_hook'});
        if (defined $hook) {
            $config{'irker_hook'} = $hook;
        }
        else {
            error("irker hook '$config{irker_hook}' not found in PATH");
        }
    }
    if (!-x $config{irker_hook}) {
        error("irker hook '$config{irker_hook}' not executable");
    }
}

# Parses git_wrapper to find out where the git repository is.
# cargo-culted from branchable.pm
sub find_git_repository {
	if ($config{rcs} eq 'git' &&
	    $config{git_wrapper}=~m!^(.*)/hooks/post-update$!) {
		return $1;
	}
	else {
		return undef;
	}
}

# setup the hook symlink and git configuration
sub genwrapper() {
    my $repo=find_git_repository();
    if (defined $repo && defined $config{'irker_channels'}) {
        if (!-l $repo . '/hooks/post-receive') {
            if (-e $repo . '/hooks/post-receive') {
                error('post-receive hook exists and is not a symlink, failed to setup hook');
            }
            symlink($config{'irker_hook'}, $repo . '/hooks/post-receive') || error('failed to symlink: $!');
        }
        my $channels = join(",", @{$config{'irker_channels'}});
        system { 'git' } ('config', '-C', $repo, 'config', 'irker.channels', $channels);
        system { 'git' } ('config', '-C', $repo, 'config', 'irker.channels', $config{'wikiname'});
        if ($config{'irker_template'}) {
            exec { 'git' } ('config', '-C', $repo, 'config', 'irker.channels', $config{'irker_template'});
        }
    }
    else {
        system { 'git' } ('config', '-C', $repo, 'config', '--remove-section', 'irker');
        if (-l $repo . '/hooks/post-receive' && 
            readlink($repo . '/hooks/post-receive') =~ m/irkerhook/) {
            unlink($repo . '/hooks/post-receive');
        }
    }
    return "";
}

1
"""]]
