html/nocollide.pl


   1 #
   2 # This script will change your nickname if in given time (/SET collision_time [seconds])
   3 # there are more than specific number of collisions (/SET collision_count [number]) on
   4 # single channel. After change next nick collisions are ignored for given time
   5 # (/SET collsion_ignore [seconds]).
   6 # Settings:
   7 #		/SET collision_avoid [On/Off] (default is on, if off - action disabled)
   8 #		/SET collision_count [number]
   9 #		/SET collision_time [seconds]
  10 #		/SET collision_ignore [seconds]
  11 #		/SET collision_baselen [0-6]
  12 
  13 use strict;
  14 use Irssi;
  15 use Irssi::Irc;
  16 
  17 use vars qw($VERSION %IRSSI);
  18 $VERSION = "0.2.3";
  19 %IRSSI = (
  20 	'authors'		=> 'Marcin Rozycki',
  21 	'contact'		=> 'derwan@irssi.pl',
  22 	'name'			=> 'nocollide',
  23 	'description'		=> 'Automatically changes nick (to randnick or uid on ircd 2.11) when certain amount of nick colissions'.
  24 	                           'takes place on channel',
  25 	'url'			=> 'http://derwan.irssi.pl',
  26 	'license'		=> 'GNU GPL v2',
  27 	'changed'		=> 'Mon Feb 16 10:08:59 CET 2004',
  28 );
  29 
  30 my $default_time = 5;
  31 my $default_count = 2;
  32 my $default_ignore = 10;
  33 my $default_baselen = 5;
  34 
  35 Irssi::settings_add_bool('misc', 'collision_avoid', 1);
  36 Irssi::settings_add_int('misc', 'collision_time', $default_time);
  37 Irssi::settings_add_int('misc', 'collision_count', $default_count);
  38 Irssi::settings_add_int('misc', 'collision_ignore', $default_ignore);
  39 Irssi::settings_add_int('misc', 'collision_baselen', $default_baselen);
  40 
  41 my %collision = ();
  42 my %collision_changed = ();
  43 
  44 sub sig_message_quit {
  45 	my ($server, $nick, $null, $quit_msg) = @_;
  46 
  47 	# based on cras'es kills.pl
  48 	return if ($quit_msg !~ /^Killed \(([^ ]*) \((.*)\)\)$/ or !$server or !$server->{connected} or
  49 			!$nick or !Irssi::settings_get_bool('collision_avoid'));
  50 
  51 	my $time = time(); my $tag = lc($server->{tag}); my $change = 0;
  52 
  53 	my $check_time = Irssi::settings_get_int('collision_time');
  54 	$check_time = $default_time if (!$check_time or $check_time !~ /^\d+$/);
  55 
  56 	my $check_count = Irssi::settings_get_int('collision_count');
  57 	$check_count = $default_count if (!$check_count or $check_count !~ /^\d+$/);
  58 	$check_count = 10 if (--$check_count > 10);
  59 
  60 	my $ignore = Irssi::settings_get_int('collision_ignore');
  61 	$ignore = $default_ignore if (!$ignore or $ignore !~ /^\d+$/);
  62 
  63 	my $version = $server->{version};
  64 	$version = 0 unless ( defined $version );
  65 	
  66 	my @list = $server->nicks_get_same($nick);
  67 	while (my $channel = shift(@list)) {
  68 		shift(@list);
  69 
  70 		my $chan = lc($channel->{name});
  71 		unshift @{$collision{$tag}{$chan}}, $time; $#{$collision{$tag}{$chan}} = 10;
  72 		next if ( $server->{nick} =~ m/^\d/ );
  73 		
  74 		next unless ($check_count > 0 and $check_time > 0);
  75 
  76 		my $test = $collision{$tag}{$chan}[$check_count];
  77 		if ($test and $test >= ($time - $check_time)) {
  78 			my $last = $collision_changed{$tag};
  79 			next if ($last and ($time - $last) < $ignore);
  80 			
  81 			$collision_changed{$tag} = $time;
  82 			delete $collision{$tag}{$chan};
  83 			next if ($change++);
  84 
  85 			if ( $version =~ m/^2.11/ ) {
  86 				$channel->print("%RNick collision alert%n in %_".$channel->{name}."%_ \(rate ".($check_count + 1)."\:$check_time\). Changing nick to %_uid%_!", MSGLEVEL_CLIENTCRAP);
  87 				$server->send_raw('NICK 0');
  88 				next;
  89 			}
  90 			
  91 			my $len = Irssi::settings_get_int('collision_baselen');
  92 			$len = 6 if ($len > 6);
  93 			my $nick = randnick(substr($server->{nick}, 0, $len));
  94 			$channel->print("%RNick collision alert%n in %_".$channel->{name}."%_ \(rate ".($check_count + 1)."\:$check_time\). Changing nick to \'%_$nick%_\'", MSGLEVEL_CLIENTCRAP);
  95 			$server->command("NICK $nick");
  96 		}
  97 	}
  98 }
  99 
 100 # str randnick($prefix, $nicklen);
 101 # returns random nickname
 102 sub randnick {
 103 	my ($base, $length) = @_;
 104 	$length = 9 if (!$length or $length !~ /^\d+$/);
 105 
 106 	# based on fahren's void.scr for LiCe
 107 	my $chars = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ_-0123456789';
 108 	my $cchars = (length($base)) ? 64 : 53;
 109 
 110 	while (length($base) < $length)
 111 	{
 112 		$base .= substr($chars, int(rand($cchars)), 1);
 113 		$cchars = 64 if ($cchars == 53);
 114 	}
 115 	return $base;
 116 }
 117 
 118 Irssi::signal_add_first('message quit', 'sig_message_quit');