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');