Customizable kickban command with unban timer and mask resolver.
Author: ArZa
— Version: 0.3
— License: GPL-3.0-or-later
For WeeChat ≥ 0.3.0.
Tags: irc, kick, ban
Added: 2011-07-08
— Updated: 2014-03-24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | # kickban.pl by arza <arza@arza.us>: A new, customizable kickban command # This program is free software: you can modify/redistribute it under the terms of # GNU General Public License by Free Software Foundation, either version 3 or later # which you can get from <http://www.gnu.org/licenses/>. # This program is distributed in the hope that it will be useful, but without any warranty. # This script provides command /kickban2. You probably want to alias it to /kb: /alias kb kickban2 # Changelog: # 24.03.2014 0.3 fix bug with uninitialized variable # 15.10.2011 0.2 fix bug with ban when host isn't found in memory # 08.07.2011 0.1 initial release weechat::register("kickban", "arza <arza\@arza.us>", "0.3", "GPL3", "A new, customizable kickban command", "", ""); weechat::hook_command( "kickban2", "A new, customizable kickban command", "[-nuhsd#] nick[,nick2...] [reason]", "The ban mask can be specified by setting plugins.var.perl.kickban.banmask or by a switch (default: u,h): n: nick u: username h: full host s: subdomain d: domain Timeout for unban in minutes can be set by setting plugins.var.perl.kickban.time or by a number in a switch. (default: 0, don't unban) Multiple nicks is supported. If nick isn't found in the channel, the mask is looked up automatically. (v>=0.3.4) The default kick reason can be set by plugins.var.perl.kickban.kick_reason. Whether kicking will be done before banning can be speficied by plugins.var.perl.kickban.kick_first. There may be a delay of irc.server_default.anti_flood_prio_high between commands. Examples: Kick nick lamer and ban its nick!*\@*.domain: /kickban2 -nd lamer Kick nicks badone and badtwo with reason \"Bye bye\", and ban them by *!user\@*.domain for ten minutes: /kickban2 -10ud badone,badtwo Bye bye", "%(nick)", "kickban", ""); my $version=weechat::info_get("version_number", "") || 0; weechat::hook_hsignal("irc_redirection_sigwhois_whois", "get_whois", "") if $version>=0x00030400; my ($buffer, %banmask, $time, $reason); init_config(); sub init_config { if($version>=0x00030500){ # descriptions for settings weechat::config_set_desc_plugin("banmask", "mask used for banning, default: u,h (*!user\@host)"); weechat::config_set_desc_plugin("time", "time in minutes to unban after banning, 0=never (default)"); weechat::config_set_desc_plugin("kick_first", "kick before ban (default: on)"); weechat::config_set_desc_plugin("kick_reason", "default kick reason"); } my %options = ( # default options "banmask" => "u,h", "time" => "0", "kick_first" => "on", "kick_reason" => "", ); foreach my $option (keys %options){ # sync the defaults weechat::config_set_plugin($option, $options{$option}) unless weechat::config_is_set_plugin($option); } } sub kickban { if(!$_[2]){ weechat::command("", "/help kickban2"); return weechat::WEECHAT_RC_OK; } $buffer=$_[1]; my @args=split(/ /, $_[2]); $time=weechat::config_get_plugin("time"); %banmask=(); my @nicks; for(my $i=0; $i<=$#args+1; $i++){ my $arg=$args[$i] || last; # go through arguments if($arg=~/^\-/){ # begins '-': banmask/time switches foreach("n","u","h","s","d"){ $banmask{$_}=1 if $arg=~/$_/; } # set banmask type if($arg=~/(\d+)/){ $time=$1; } # any number = unban time }else{ # the rest is nicks (and reason) @nicks=split(/,/, $arg); $reason=join(' ', @args[$i+1..$#args]); # the reason last; } } return weechat::WEECHAT_RC_ERROR unless @nicks; # return if didn't get nicks if(!%banmask){ $banmask{$_}=1 foreach (split(/,/, weechat::config_get_plugin("banmask"))); } # get the banmask from the setting if it's not given as an argument if($banmask{"h"}){ $banmask{"s"}=$banmask{"d"}=1; } # host -> subdomain and domain $reason=weechat::config_get_plugin("kick_reason") unless $reason; # get the reason from the setting if it's not given as an argument foreach my $nick (@nicks) { # go through nicks to be kicked my $infolist = weechat::infolist_get( # get the irc_nick infolist "irc_nick", "", weechat::buffer_get_string($buffer, "localvar_server"). ",". weechat::buffer_get_string($buffer, "localvar_channel"). ",". $nick ); next unless $infolist; if(weechat::infolist_next($infolist) && lc(weechat::infolist_string($infolist, "name")) eq lc($nick)){ my $host=weechat::infolist_string($infolist, "host") || next; my $ban=gen_mask($nick, split(/@/, $host)); # split variable host from infolist to user and host, get banmask weechat::command($buffer, "/kick $nick $reason") if weechat::config_get_plugin("kick_first") ne "off"; # kick before ban weechat::command($buffer, "/ban $ban"); # ban weechat::command($buffer, "/kick $nick $reason") if weechat::config_get_plugin("kick_first") eq "off"; # kick after ban weechat::command($buffer, "/wait ".60*$time." /unban $ban") if $time; $nick=''; } weechat::infolist_free($infolist); } if($version>=0x00030400){ # hook_hsignal reguires v>=0.3.4 my $server=weechat::buffer_get_string($buffer, "localvar_server"); # current server foreach my $nick (@nicks) { # the nicks that weren't found in the channel if($nick){ weechat::hook_hsignal_send("irc_redirect_command", { "server" => "$server", "pattern" => "whois", "signal" => "sigwhois" }); # redirection weechat::hook_signal_send("irc_input_send", weechat::WEECHAT_HOOK_SIGNAL_STRING, "$server;;1;;/whois $nick"); # send whois command } } } } sub get_whois { my %hashtable=%{$_[2]}; # get the answer for whois if($hashtable{"output"}=~/^:\S+ 311 \S+ (\S+) (\S+) (\S+)/){ my $ban=gen_mask($1,$2,$3); weechat::command($buffer, "/ban $ban"); # ban weechat::command($buffer, "/wait ".60*$time." /unban $ban") if $time; # unban return weechat::WEECHAT_RC_OK; }elsif($hashtable{"output"}=~/^:\S+ 40[12] \S+ (\S+)/){ weechat::print("", weechat::prefix("error")."Kickban: Didn't find nick $1"); return weechat::WEECHAT_RC_OK; } } sub gen_mask { my ($nick, $user, $fullhost) = @_; # generate banmask my ($ban, $sub, $domain); if($fullhost=~/\w/){ # if there are letters in the host (it's not an ip) my @hostparts=split(/\./, $fullhost); # split host to subdomain and domain if(@hostparts>2){ # if there are at least three parts $sub=join(".", @hostparts[0..$#hostparts-2]); # subdomain is the beginning $domain=$hostparts[$#hostparts-1].".".$hostparts[$#hostparts]; # domain is the last two parts } } if($banmask{"n"}){ # if nick is in banmask $ban=$nick."!"; }else{ $ban="*!"; } if($banmask{"u"}){ # if user is in banmask $ban.=$user."\@"; }else{ $ban.="*\@"; } if($banmask{"s"}){ # if subdomain is in banmask if($banmask{"d"} || !$sub){ # use the full host if also domain is in banmask or anyway if subdomain isn't specified $ban.=$fullhost; }else{ $ban.=$sub.".*"; } }elsif($banmask{"d"}){ # if domain is in banmask but subdomain isn't if($domain){ $ban.="*.$domain"; } else{ $ban.=$fullhost; } # use the full host anyway if domain isn't separated from subdomain }else{ $ban.="*"; } return $ban; } |