Merged 0.7.99 irssi.
[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
8 use Irssi;
9 use Irssi::Irc;
10 use strict;
11
12 my %keep_channels;
13
14 sub cmd_mlock {
15         my ($data, $server) = @_;
16         my ($channel, $mode) = split(/ /, $data, 2);
17
18         $keep_channels{$channel} = $mode;
19         mlock_check_mode($server, $channel);
20 }
21
22 sub mlock_check_mode {
23         my ($server, $channame) = @_;
24
25         my $channel = $server->channel_find($channame);
26         return if (!$channel || !$channel->{chanop});
27
28         my $keep_mode = $keep_channels{$channame};
29         return if (!$keep_mode);
30
31         # old channel mode
32         my ($oldmode, $oldkey, $oldlimit);
33         $oldmode = $channel->{mode};
34         $oldmode =~ s/^([^ ]*).*/\1/;
35         $oldkey = $channel->{key};
36         $oldlimit = $channel->{limit};
37
38         # get the new channel key/limit
39         my (@newmodes, $newkey, $limit);
40         @newmodes = split(/ /, $keep_mode); $keep_mode = $newmodes[0];
41         if ($keep_mode =~ /k/) {
42                 if ($keep_mode =~ /k.*l/) {
43                         $newkey = $newmodes[1];
44                         $limit = $newmodes[2];
45                 } elsif ($keep_mode =~ /l.*k/) {
46                         $limit = $newmodes[1];
47                         $newkey = $newmodes[2];
48                 } else {
49                         $newkey = $newmodes[1];
50                 }
51         } elsif ($keep_mode =~ /l/) {
52                 $limit = $newmodes[1];
53         }
54
55         # check the differences
56         my %allmodes;
57         $keep_mode =~ s/^\+//;
58         for (my $n = 0; $n < length($keep_mode); $n++) {
59                 my $modechar = substr($keep_mode, $n, 1);
60                 $allmodes{$modechar} = '+';
61         }
62
63         for (my $n = 0; $n < length($oldmode); $n++) {
64                 my $modechar = substr($oldmode, $n, 1);
65
66                 if ($allmodes{$modechar} eq '+') {
67                         next if (($modechar eq "k" && $newkey ne $oldkey) ||
68                                  ($modechar eq "l" && $limit != $oldlimit));
69                         delete $allmodes{$modechar};
70                 } else {
71                         $allmodes{$modechar} = '-';
72                 }
73         }
74
75         # create the mode change string
76         my ($modecmd, $extracmd);
77         foreach my $mode (keys %allmodes) {
78                 Irssi::print("key = '$mode':".$allmodes{$mode});
79                 if ($mode eq "k") {
80                         if ($allmodes{$mode} eq '+') {
81                                 next if ($newkey eq "");
82                                 if ($oldkey ne "") {
83                                         # we need to get rid of old key too
84                                         $modecmd .= "-k";
85                                         $extracmd .= " $oldkey";
86                                 }
87                                 $extracmd .= " $newkey";
88                         } else {
89                                 $extracmd .= " $oldkey";
90                         }
91                 }
92                 if ($mode eq "l" && $allmodes{$mode} eq '+') {
93                         next if ($limit <= 0);
94                         $extracmd .= " $limit";
95                 }
96                 $modecmd .= $allmodes{$mode}.$mode;
97         }
98
99         if ($modecmd ne "") {
100                 $channel->{server}->command("/mode $channame $modecmd$extracmd");
101         }
102 }
103
104 sub mlock_mode_changed {
105         my ($server, $data) = @_;
106         my ($channel, $mode) = split(/ /, $data, 2);
107
108         mlock_check_mode($server, $channel);
109 }
110
111 sub mlock_synced {
112         my $channel = $_[0];
113
114         mlock_check_mode($channel->{server}, $channel->{name});
115 }
116
117 Irssi::command_bind('mlock', 'cmd_mlock');
118 Irssi::signal_add_last("event mode", "mlock_mode_changed");
119 Irssi::signal_add("channel synced", "mlock_synced");