##
# Xautorejoinpunish - 	Like Paul Raade's script, but for using with Undernet's X.
##
# Explanations for the settings, with defaults shown:
# /set xautorejoinpunish_X_username <nick> (no default value)
# /set xautorejoinpunish_time_limit 3
# 	- The time limit in seconds for measuring what is an
#	  autorejoin, and what is not.
# /set xautorejoinpunish_kickban_message Kickban for autorejoining.
# 	- Kick reason, if kickban was selected.
# /set xautorejoinpunish_knockout ON
# 	- Whether kick or knockout. As default, knockout is
#	  selected, so that the bans will be removed automatically.
# /set xautorejoinpunish_knockout_time 60
# 	- Time in seconds how long a ban will be kept if
#	  knockout is selected.
# /set xautorejoinpunish_knockout_message Temporary ban for autorejoining.
# 	- Kick reason, if knockout was selected.
# /set xautorejoinpunish_channels
# 	- Space separated list of channels on which autorejoin punishment 
#	  be used will
# /set xautorejoinpunish_only_own_kicks ON
#	- If set ON, only people kicked by you will be banned.
##
# Changelog:
# - 0.2: Fixed a bug in check_bans sub, which prevented knockout to function properly
# - 0.1: Initial release.
##
# Happy banning! ;)
##

use strict;
use Irssi qw(settings_get_str settings_get_int settings_get_bool
timeout_add settings_add_int settings_add_str settings_add_bool
signal_add_first command server_find_tag);

use vars qw(%IRSSI $VERSION);
$VERSION = '0.1';
%IRSSI = (
	authors		=> 'Clement "nodens" Hermann, based on autorejoinpunish script by Paul \'laaama\' Raade <paul@raade.org>',
	contact 	=> 'clement.hermann@free.fr',
	name		=> 'X Autorejoin punisher',
	description	=> 'Kickbans or knockouts people who use autorejoin on kick, using Undernet X access. Please set at least xautorejoinpunish_X_username and xautorejoinpunish_channels before use',
	license		=> 'GPLv2',
	changes		=> 'brand new!',
	changed		=> 'Thu 10 May 2003'
);

my (%victims, %bans);
my $debug=0;

sub message_kick { # Set a time stamp for people who are kicked.
	#  "message kick", SERVER_REC, char *channel, char *nick, char *kicker, char *address, char *reason
	my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
	my $X_Username = settings_get_str('xautorejoinpunish_X_username');
	if ((settings_get_bool('xautorejoinpunish_only_own_kicks') == 0) || 
		(settings_get_bool('xautorejoinpunish_only_own_kicks') == 1 && 
		(($kicker eq "X") && ($reason =~ /^\($X_Username\).*$/)))) {
		Irssi::print("debug: kick detected: server=$server, channel=$channel, nick=$nick, kicker=$kicker, address=$address, reason=$reason") if $debug;
		foreach my $item (split(' ', lc(settings_get_str('xautorejoinpunish_channels')))) {
			$victims{$channel}{$nick} = time() if ((lc $channel) eq $item);
		}		
	}
}

sub message_join { # Check for recent kicks, 
	# "message join", SERVER_REC, char *channel, char *nick, char *address
	my ($server, $channel, $nick, $address) = @_;
	if ($victims{$channel}{$nick} && ((time()-$victims{$channel}{$nick}) <= settings_get_int('xautorejoinpunish_time_limit'))) {
		Irssi::print("debug: Autorejoin detected: $victims{$channel}{$nick}") if $debug;
		if (settings_get_bool('xautorejoinpunish_knockout') == 1) {
			$server->command('msg X ban' . ' ' . $channel . ' ' . $nick . ' ' . settings_get_str('xautorejoinpunish_knockout_message'));
			$bans{$server->{tag}}{time()} = $channel . '/' . $nick;
		} else {
			$server->command('msg X ban' . ' ' . $channel . ' ' . $nick . ' ' . settings_get_str('xautorejoinpunish_kickban_message'));
		}
	}
	delete $victims{$channel}{$nick};
}

sub clean_list {
	my ($channelkey, $nickkey);
	if (%victims) {
		foreach $channelkey (keys %victims) {
			foreach $nickkey (keys %{$victims{$channelkey}}) {
				if ((time()-$victims{$channelkey}{$nickkey}) > settings_get_int('xautorejoinpunish_time_limit')) {
					delete $victims{$channelkey}{$nickkey};
				}
			}
		}
	}
}

sub check_bans {
	my ($server, $timestamp);
	if (%bans) {
		foreach $server (keys %bans) {
			foreach $timestamp (keys %{$bans{$server}}) {
				if ((time()-$timestamp) > settings_get_int('xautorejoinpunish_knockout_time')) {
					Irssi::print("bans{$server}{$timestamp} $bans{$server}{$timestamp}") if $debug;
					my ($channel, $nick) = split(/\//, $bans{$server}{$timestamp});
					Irssi::print"ban timeout: $channel: $nick" if $debug;
					server_find_tag($server)->command('msg X unban' . ' ' . $channel . ' ' . $nick);
					delete $bans{$server}{$timestamp};
				}
			}
		}
	}
}


settings_add_int  ('misc', 'xautorejoinpunish_time_limit', '3');
settings_add_str  ('misc', 'xautorejoinpunish_kickban_message', 'Kickban for autorejoining.');
settings_add_bool ('misc', 'xautorejoinpunish_knockout', '1');
settings_add_int  ('misc', 'xautorejoinpunish_knockout_time', '60');
settings_add_str  ('misc', 'xautorejoinpunish_knockout_message', 'Temporary ban for autorejoining.');
settings_add_str  ('misc', 'xautorejoinpunish_channels', '');
settings_add_bool ('misc', 'xautorejoinpunish_only_own_kicks', '1');
settings_add_str ('misc', 'xautorejoinpunish_X_username', '');

signal_add_first 'message join' => 'message_join';
signal_add_first 'message kick' => 'message_kick';

timeout_add ('5000', 'check_bans', '');
timeout_add ('3600000', 'clean_list', '');
# 1h = 60min * 60s * 1000ms = 3600000ms
