Added SILC Thread Queue API
[crypto.git] / apps / irssi / scripts / mlock.pl
1 # /MLOCK <channel> <mode>
2 #
3 # Locks the channel mode to <mode>, if someone else tries to change the mode
4 # Irssi will automatically change it back. +k and +l are a bit special since
5 # they require the parameter. If you omit the parameter, like setting the
6 # mode to "+ntlk", Irssi will allow all +k and +l (or -lk) mode changes.
7 # You can remove the lock with /MODE #channel -
8
9 use Irssi;
10 use Irssi::Irc;
11 use strict;
12 use vars qw($VERSION %IRSSI);
13
14 $VERSION = "1.00";
15 %IRSSI = (
16     authors     => 'Timo Sirainen',
17     name        => 'mlock',
18     description => 'Channel mode locking',
19     license     => 'Public Domain',
20     changed     => 'Sun Mar 10 23:18 EET 2002'
21 );
22
23 my %keep_channels;
24
25 sub cmd_mlock {
26         my ($data, $server) = @_;
27         my ($channel, $mode) = split(/ /, $data, 2);
28
29         if ($mode eq "-") {
30                 # remove checking
31                 delete $keep_channels{$channel};
32         } else {
33                 $keep_channels{$channel} = $mode;
34                 mlock_check_mode($server, $channel);
35         }
36 }
37
38 sub mlock_check_mode {
39         my ($server, $channame) = @_;
40
41         my $channel = $server->channel_find($channame);
42         return if (!$channel || !$channel->{chanop});
43
44         my $keep_mode = $keep_channels{$channame};
45         return if (!$keep_mode);
46
47         # old channel mode
48         my ($oldmode, $oldkey, $oldlimit);
49         $oldmode = $channel->{mode};
50         $oldmode =~ s/^([^ ]*).*/\1/;
51         $oldkey = $channel->{key};
52         $oldlimit = $channel->{limit};
53
54         # get the new channel key/limit
55         my (@newmodes, $newkey, $limit);
56         @newmodes = split(/ /, $keep_mode); $keep_mode = $newmodes[0];
57         if ($keep_mode =~ /k/) {
58                 if ($keep_mode =~ /k.*l/) {
59                         $newkey = $newmodes[1];
60                         $limit = $newmodes[2];
61                 } elsif ($keep_mode =~ /l.*k/) {
62                         $limit = $newmodes[1];
63                         $newkey = $newmodes[2];
64                 } else {
65                         $newkey = $newmodes[1];
66                 }
67         } elsif ($keep_mode =~ /l/) {
68                 $limit = $newmodes[1];
69         }
70
71         # check the differences
72         my %allmodes;
73         $keep_mode =~ s/^\+//;
74         for (my $n = 0; $n < length($keep_mode); $n++) {
75                 my $modechar = substr($keep_mode, $n, 1);
76                 $allmodes{$modechar} = '+';
77         }
78
79         for (my $n = 0; $n < length($oldmode); $n++) {
80                 my $modechar = substr($oldmode, $n, 1);
81
82                 if ($allmodes{$modechar} eq '+') {
83                         next if (($modechar eq "k" && $newkey ne $oldkey) ||
84                                  ($modechar eq "l" && $limit != $oldlimit));
85                         delete $allmodes{$modechar};
86                 } else {
87                         $allmodes{$modechar} = '-';
88                 }
89         }
90
91         # create the mode change string
92         my ($modecmd, $extracmd);
93         foreach my $mode (keys %allmodes) {
94                 Irssi::print("key = '$mode':".$allmodes{$mode});
95                 if ($mode eq "k") {
96                         if ($allmodes{$mode} eq '+') {
97                                 next if ($newkey eq "");
98                                 if ($oldkey ne "") {
99                                         # we need to get rid of old key too
100                                         $modecmd .= "-k";
101                                         $extracmd .= " $oldkey";
102                                 }
103                                 $extracmd .= " $newkey";
104                         } else {
105                                 $extracmd .= " $oldkey";
106                         }
107                 }
108                 if ($mode eq "l" && $allmodes{$mode} eq '+') {
109                         next if ($limit <= 0);
110                         $extracmd .= " $limit";
111                 }
112                 $modecmd .= $allmodes{$mode}.$mode;
113         }
114
115         if ($modecmd ne "") {
116                 $channel->{server}->command("mode $channame $modecmd$extracmd");
117         }
118 }
119
120 sub mlock_mode_changed {
121         my ($server, $data) = @_;
122         my ($channel, $mode) = split(/ /, $data, 2);
123
124         mlock_check_mode($server, $channel);
125 }
126
127 sub mlock_synced {
128         my $channel = $_[0];
129
130         mlock_check_mode($channel->{server}, $channel->{name});
131 }
132
133 Irssi::command_bind('mlock', 'cmd_mlock');
134 Irssi::signal_add_last("event mode", "mlock_mode_changed");
135 Irssi::signal_add("channel synced", "mlock_synced");