diff options
Diffstat (limited to 'scripts/getop.pl')
| -rw-r--r-- | scripts/getop.pl | 387 | 
1 files changed, 387 insertions, 0 deletions
| diff --git a/scripts/getop.pl b/scripts/getop.pl new file mode 100644 index 0000000..1dbd75c --- /dev/null +++ b/scripts/getop.pl @@ -0,0 +1,387 @@ +use Irssi 20020300; +use strict; + +use vars qw($VERSION %IRSSI %HELP); +$HELP{getop} = " +GETOP [channel] + +Gets op on current channel or 'channel' from random opped bot added by ADDGETOP. +"; +$HELP{addgetop} = " +ADDGETOP [channel] <mask> <command> + +Adds entry to 'channel' or current channel getop list. +The \$0 in command specifies nick of random found mask +in channel. +"; +$HELP{delgetop} = " +DELGETOP [channel] <mask or index number from LISTGETOP> + +Deletes entry from getoplist on current channel or 'channel'. +"; +$HELP{listgetop} = " +LISTGETOP [channel] + +Lists all entries in getop list or just 'channel's getop list. +"; +$VERSION = "0.9b"; +%IRSSI = ( +	authors         => "Maciek \'fahren\' Freudenheim", +	contact         => "fahren\@bochnia.pl", +	name            => "GetOP", +	description     => "Automatically request op from random opped person with specifed command from list after joining channel", +	license         => "GNU GPLv2 or later", +	changed         => "Fri Jan 10 03:54:07 CET 2003" +); + +Irssi::theme_register([ +	'getop_listline', '[%W$[!-2]0%n]%| $[40]1%_: %_$2', +	'getop_add', 'Added \'%_$2%_\' to getop list on channel %_$1%_ /$0/', +	'getop_del', 'Deleted \'%_$2%_\' from getop list on channel %_$1%_ /$0/', +	'getop_changed', 'Changed command for mask \'%_$2%_\' on channel %_$1%_ /$0/', +	'getop_noone', '"%Y>>%n No one to get op from on $1 /$0/', +	'getop_get', '%Y>>%n Getting op from %_$2%_ on $1 /$0/' +]); + +my %getop = (); +my @userhosts; +my $getopfile = Irssi::get_irssi_dir . "/getoplist"; + +sub sub_getop { +	my ($args, $server, $winit) = @_; + +	my $chan; +	my ($channel) = $args =~ /^([^\s]+)/; + +	if ($server->ischannel($channel)) { +		unless ($chan = $server->channel_find($channel)) { +			Irssi::print("%R>>%n You are not on $channel."); +			return; +		} +		$args =~ s/^[^\s]+\s?//; +	} else { +		unless ($winit && $winit->{type} eq "CHANNEL") { +			Irssi::print("%R>>%n You don't have active channel in that window."); +			return; +		} +		$channel = $winit->{name}; +		$chan = $winit; +	} + +	if ($chan->{chanop}) { +		Irssi::print("%R>>%n You are already opped on $channel."); +		return; +	} + +	$channel = lc($channel); +	my $tag = lc($server->{tag}); + +	unless ($getop{$tag}{$channel}) { +		Irssi::print("%R>>%n Your getop list on channel $channel is empty. Use /ADDGETOP first."); +		return; +	}; + +	unless ($getop{$tag}{$channel}) { +		Irssi::print("%R>>%n Your getop list on channel $channel is empty."); +		return; +	} + +	getop_proc($tag, $chan); +} + +sub sub_addgetop { +	my ($args, $server, $winit) = @_; + +	my ($channel) = $args =~ /^([^\s]+)/; + +	if ($server->ischannel($channel)) { +		$args =~ s/^[^\s]+\s?//; +	} else { +		unless ($winit && $winit->{type} eq "CHANNEL") { +			Irssi::print("%R>>%n You don't have active channel in that window."); +			return; +		} +		$channel = $winit->{name}; +	} + +	my ($mask, $command) = split(/ +/, $args, 2); +	 +	unless ($command) { +		Irssi::print("Usage: /ADDGETOP [channel] <mask or nickname> <command>. If you type '\$0' in command then it will be changed automatically into mask's nick."); +		return; +	} + +	my $cmdchar = Irssi::settings_get_str('cmdchars'); +	$command =~ s/^($cmdchar*)\^?/\1^/g; +	 +	if (index($mask, "@") == -1) { +		my ($c, $n); +		if (($c = $server->channel_find($channel)) && ($n = $c->nick_find($mask))) { +			$mask = $n->{host}; +			$mask =~ s/^[~+\-=^]/*/; +		} else { +			$server->redirect_event('userhost', 1, $mask, 0, undef, { +					'event 302' => 'redir getop userhost', +					'' => 'event empty' } ); +			$server->send_raw("USERHOST $mask"); +			my $uh = lc($mask) . " " . lc($channel) . " $command"; +			push @userhosts,  $uh; +			return; +		} +	} +	 +	$mask = "*!" . $mask if (index($mask, "!") == -1); +	my $tag = lc($server->{tag}); +	my $channel = lc($channel); +	 +	for my $entry (@{$getop{$tag}{$channel}}) { +		if ($entry->{mask} eq $mask) { +			$entry->{command} = $command; +			Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_changed', $tag, $channel, $mask, $command); +			&savegetop; +			return; +		} +	} +	 +	my $gh = { +		mask	=> $mask, +		command	=> $command +	}; +	 +	push @{$getop{$tag}{$channel}}, $gh; + +	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_add', $tag, $channel, $mask, $command); + +	&savegetop; +} + +sub sub_delgetop { +	my ($args, $server, $winit) = @_; + +	my ($channel) = $args =~ /^([^\s]+)/; + +	if ($server->ischannel($channel)) { +		$args =~ s/^[^\s]+\s?//; +	} else { +		unless ($winit && $winit->{type} eq "CHANNEL") { +			Irssi::print("%R>>%n You don't have active channel in that window."); +			return; +		} +		$channel = $winit->{name}; +	} + +	my $tag = lc($server->{tag}); +	my $channel = lc($channel); + +	unless ($getop{$tag}{$channel}) { +		Irssi::print("%R>>%n Your getop list on channel $channel is empty."); +		return; +	} + +	unless ($args) { +		Irssi::print("%W>>%n Usage: /DELGETOP [channel] <mask | index from LISTGETOP>"); +		return; +	} + +	my $num; +	if ($args =~ /^[0-9]+$/) { +		if ($args > scalar(@{$getop{$tag}{$channel}})) { +			Irssi::print("%R>>%n No such entry in $channel getop list."); +			return; +		} +		$num = $args - 1; +	} else { +		my $i = 0; +		for my $entry (@{$getop{$tag}{$channel}}) { +			$args eq $entry->{mask} and $num = $i, last; +			$i++; +		} +	} + +	if (my($gh) = splice(@{$getop{$tag}{$channel}}, $num, 1)) { +		Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_del', $tag, $channel, $gh->{mask}, $gh->{command}); +		unless (scalar(@{$getop{$tag}{$channel}})) { +			Irssi::print("%R>>%n No more entries in $channel getop list left."); +			delete $getop{$tag}{$channel}; +		} +		unless (keys %{$getop{$tag}}) { +			Irssi::print("%R>>%n No more entries in getop list on $tag left.");	 +			delete $getop{$tag}; +		} +	} + +	&savegetop; +} + +sub sub_listgetop { +	my ($args, $server, $winit) = @_; + +	my ($channel) = $args =~ /^([^\s]+)/; + +	if ($server->ischannel($channel)) { +		my $tag = lc($server->{tag}); +		$channel = lc($channel); +		unless ($getop{$tag}{$channel}) { +			Irssi::print("%R>>%n Your getop list on channel $channel is empty."); +			return; +		} +		my $i = 0; +		Irssi::print("Getop list on $channel /$tag/:"); +		for my $entry (@{$getop{$tag}{$channel}}) { +			Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_listline', $i++, $entry->{mask}, $entry->{command}); +		} +	} else { +		unless (keys %getop) { +			Irssi::print("%R>>%n Your getop list is empty. /ADDGETOP first."); +			return; +		} +		for my $ircnet (keys %getop) { +			for my $chan (keys %{$getop{$ircnet}}) { +				Irssi::print("Channel: $chan /$ircnet/"); +				my $i = 1; +				for my $entry (@{$getop{$ircnet}{$chan}}) { +					Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_listline', $i++, $entry->{mask}, $entry->{command}); +				} +			} +		} +	} +} + +sub userhost_red { +	my ($server, $data) = @_; +	$data =~ s/^[^ ]* :?//; + +	my $uh = shift @userhosts; +	my ($nick, $chan, $command) = split(/ /, $uh, 3); + +	unless ($data && $data =~ /^([^=\*]*)\*?=.(.*)@(.*)/ && lc($1) eq $nick) { +		Irssi::print("%R>>%n No such nickname: $nick"); +		return; +	} + +	my ($user, $host) = ($2, $3); +	$user =~ s/^[~+\-=^]/*/; +	my $mask = "*!" . $user . "@" . $host; +	my $tag = lc($server->{tag}); +	 +	for my $entry (@{$getop{$tag}{$chan}}) { +		if ($entry->{mask} eq $mask) { +			$entry->{command} = $command; +			Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_changed', $tag, $chan, $mask, $command); +			&savegetop; +			return; +		} +	} +	 +	my $gh = { +		mask => $mask, +		command => $command +	}; + +	push @{$getop{$tag}{$chan}}, $gh; + +	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_add', $tag, $chan, $mask, $command); + +	&savegetop; +} + +sub getop_proc ($$) { +	my ($tag, $chan) = @_; + +	my $channel = lc($chan->{name}); +	return unless ($getop{$tag}{$channel}); + +	my (@list, $mask); +	for my $nick ($chan->nicks()) { +		next unless ($nick->{op}); +		$mask = $nick->{nick} . "!" . $nick->{host}; +		for my $entry (@{$getop{$tag}{$channel}}) { +			if (mask_match($mask, $entry->{mask})) { +				my $lh = { +					nick	=> $nick->{nick}, +					command	=> $entry->{command} +				}; +				push @list, $lh; +			} +		} +	} +	 +	unless (@list) { +		Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_noone', $tag, $channel); +	} else { +		my $get = $list[int(rand(@list))]; +		$get->{command} =~ s/\$0/$get->{nick}/g; +		Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'getop_get', $tag, $channel, $get->{nick}, $get->{command});	 +		$chan->command($get->{command}); +	} +} + +sub mask_match ($$) { +	my ($what, $match) = @_; + +	$match =~ s/\\/\\\\/g; +	$match =~ s/\./\\\./g; +	$match =~ s/\*/\.\*/g; +	$match =~ s/\!/\\\!/g; +	$match =~ s/\?/\./g; +	$match =~ s/\+/\\\+/g; +	$match =~ s/\^/\\\^/g; + +	return ($what =~ /^$match$/i); +} + +sub got_notopped { +	my ($server, $data) = @_; +	my ($chan) = $data =~ /^[^\s]+\s([^\s]+)\s:/; +	getop_proc(lc($server->{tag}), $server->channel_find($chan)); +} + +sub channel_sync { +	my $chan = shift; +	getop_proc(lc($chan->{server}->{tag}), $chan) unless ($chan->{chanop}); +} + +sub savegetop { +	local *fp; +	open (fp, ">$getopfile") or die "Couldn't open $getopfile for writing"; + +	for my $ircnet (keys %getop) { +		for my $chan (keys %{$getop{$ircnet}}) { +			for my $entry (@{$getop{$ircnet}{$chan}}) { +				print(fp "$ircnet $chan $entry->{mask} $entry->{command}\n"); +			} +		} +	} + +	close fp; +} + +sub loadgetop { +	%getop = (); +	return unless (-e $getopfile); +	local *fp; + +	open (fp, "<$getopfile") or die "Couldn't open $getopfile for reading"; +	local $/ = "\n"; +	 +	while (<fp>) { +		chop; +		my $gh = {}; +		my ($tag, $chan); +		($tag, $chan, $gh->{mask}, $gh->{command}) = split(/ /, $_, 4); +		push @{$getop{$tag}{$chan}}, $gh; +	} +	 +	close fp; +} + +&loadgetop; + +Irssi::command_bind( { +		'getop' => \&sub_getop, +		'addgetop' => \&sub_addgetop, +		'delgetop' => \&sub_delgetop, +		'listgetop' => \&sub_listgetop } ); +Irssi::signal_add({ 'redir getop userhost' => \&userhost_red, +		    'event 482' => \&got_notopped, +	    	    'channel sync' => \&channel_sync}); | 
