html/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");