weechat- me personal weechat setup 🔵🟢 |
git clone git://git.acid.vegas/weechat.git |
Log | Files | Refs | Archive | README |
antifuck.pl (10433B)
1 # Released into the Public Domain 2 3 use strict; 4 use warnings; 5 6 no strict 'subs'; 7 8 my $SCRIPT_NAME = 'antifuck'; 9 my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>'; 10 my $SCRIPT_VERSION = '1.1'; 11 my $SCRIPT_LICENCE = 'Public domain'; 12 my $SCRIPT_DESC = 'Defend against forcejoins (e.g. from fuckyou.pl) and '. 13 'forceparts (e.g. from /remove)'; 14 15 my %OPTIONS = ( 16 autopart => ['Whether to automatically part forcejoined channels. '. 17 'You can always do this manually with /antifuck part', '0'], 18 delay => ['Delay in milliseconds to wait before autoparting', '5000'], 19 forward => ['Whether to allow channel forwards (+f on freenode)', '1'], 20 ignore => ['Servers to ignore (e.g. for bouncers), separated by comma', ''], 21 nobufs => ['If 1, do not create buffers for forcejoined channels', '0'], 22 timeout => 23 ['Delay in milliseconds to wait for server to send JOIN after join', 24 '60000'], 25 ); 26 27 # %channels: channels we joined and received JOIN / NAMES for 28 # %zombie: channels we joined but aren't yet in 29 # %part: channels we were forced into and will part soon 30 # %partbuf: buffers belonging to parted channels, we'll close these on 31 # /antifuck part 32 our (%channels, %zombie, %part, %partbuf, $fuckbuf, $timeout_cb, $gc_cb); 33 34 if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION, 35 $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) { 36 weechat::hook_command('antifuck', $SCRIPT_DESC, 'part', <<'HELP', 37 This script defends against forced joins, such as from irssi's fuckyou.pl or 38 from channel forwards, as well as forced parts, such as from the /remove 39 command. You can configure certain behaviour using the options under 40 "plugins.var.perl.antifuck.*". Configure rejoin-on-/remove with the 41 irc.server_default.autorejoin and .autorejoin_delay commands. 42 43 Running "/antifuck part" will close all forcejoined channels and part them where 44 appropriate. 45 HELP 46 'part', 'cmd_antifuck', ''); 47 weechat::hook_signal('irc_server_connected', 'irc_connect', ''); 48 weechat::hook_signal('irc_server_disconnected', 'irc_disconnect', ''); 49 weechat::hook_signal('irc_channel_opened', 'buffer_opened', ''); 50 weechat::hook_signal('buffer_closed', 'buffer_closed', ''); 51 weechat::hook_signal('*,irc_out1_join', 'client_join', ''); 52 weechat::hook_signal('*,irc_out1_part', 'client_part', ''); 53 weechat::hook_signal('*,irc_raw_in_001', 'irc_001', ''); 54 weechat::hook_signal('*,irc_raw_in_470', 'irc_470', ''); 55 weechat::hook_modifier('irc_in_366', 'irc_366', ''); 56 weechat::hook_modifier('irc_in_join', 'irc_join', ''); 57 weechat::hook_modifier('irc_in_part', 'irc_part', ''); 58 59 for my $option (keys %OPTIONS) { 60 weechat::config_set_plugin($option, $OPTIONS{$option}[1]) 61 unless weechat::config_is_set_plugin($option); 62 weechat::config_set_desc_plugin($option, $OPTIONS{$option}[0]); 63 } 64 65 my $iptr = weechat::infolist_get('buffer', '', ''); 66 67 while (weechat::infolist_next($iptr)) { 68 next unless weechat::infolist_string($iptr, 'plugin_name') eq 'irc'; 69 my $buf = weechat::infolist_pointer($iptr, 'pointer'); 70 $channels{ 71 lc weechat::buffer_get_string($buf, 'localvar_server')}{ 72 lc weechat::buffer_get_string($buf, 'localvar_channel')} = 1; 73 } 74 weechat::infolist_free($iptr); 75 } 76 77 sub mynick 78 { 79 my ($buf, $nick) = ($_[0], $_[1]); 80 81 return lc weechat::buffer_get_string($buf, 'localvar_nick') eq lc $nick; 82 } 83 84 sub ignored 85 { 86 my $server = shift; 87 my $ignore_conf = lc weechat::config_get_plugin('ignore'); 88 89 return $ignore_conf =~ /(^|,)$server($|,)/; 90 } 91 92 sub nobufs { weechat::config_get_plugin('nobufs') } 93 94 sub ircbuf { weechat::buffer_search('irc', "(?i)".(join '.', @_)) } 95 sub ircparse { weechat::info_get_hashtable(irc_message_parse => 96 { message => shift }) } 97 98 sub servchan 99 { 100 my $buf = shift; 101 102 return (lc weechat::buffer_get_string($buf, 'localvar_server'), 103 lc weechat::buffer_get_string($buf, 'localvar_channel')); 104 } 105 106 sub reset_gc 107 { 108 weechat::unhook($gc_cb) if $gc_cb; 109 $gc_cb = weechat::hook_timer(weechat::config_get_plugin('timeout'), 0, 1, 110 'run_gc', ''); 111 } 112 113 sub cmd_antifuck 114 { 115 my (undef, $buffer, $args) = @_; 116 117 if ($args eq 'part') { 118 # TODO: we really need to spend more time here making sure we send the 119 # fewest PARTs possible, a la irc_join_delay 120 weechat::buffer_close($fuckbuf); 121 } 122 123 return weechat::WEECHAT_RC_OK; 124 } 125 126 sub fuckbuf_input { return weechat::WEECHAT_RC_OK; } 127 128 sub fuckbuf_close 129 { 130 weechat::buffer_close($_) for (keys %partbuf); 131 %partbuf = (); 132 $fuckbuf = ''; 133 134 return weechat::WEECHAT_RC_OK; 135 } 136 137 sub irc_connect 138 { 139 my $server = pop; 140 my ($autojoin) = (weechat::config_string(weechat::config_get( 141 "irc.server.$server.autojoin")) =~ /^([^ ]*)/); 142 143 $zombie{$server}{$_} = 1 for (split ',', lc($autojoin)); 144 145 return weechat::WEECHAT_RC_OK; 146 } 147 148 sub irc_disconnect 149 { 150 my $server = pop; 151 152 $server = lc $server; 153 delete $channels{$server}; 154 delete $zombie{$server}; 155 delete $part{$server}; 156 157 return weechat::WEECHAT_RC_OK; 158 } 159 160 sub buffer_opened { 161 my $buffer = pop; 162 my ($server, $channel) = servchan($buffer); 163 return weechat::WEECHAT_RC_OK if exists $channels{$server}{$channel}; 164 return weechat::WEECHAT_RC_OK if ignored($server); 165 166 $fuckbuf = weechat::buffer_new( 167 'antifuck', 168 'fuckbuf_input', 169 '', 170 'fuckbuf_close', 171 '' 172 ) unless $fuckbuf; 173 174 weechat::buffer_merge($buffer, $fuckbuf); 175 #return weechat::WEECHAT_RC_OK unless weechat::config_get_plugin('autopart'); 176 177 $partbuf{$buffer} = 1; 178 return weechat::WEECHAT_RC_OK; 179 } 180 181 sub buffer_closed { 182 my $buffer = pop; 183 184 delete $partbuf{$buffer}; 185 return weechat::WEECHAT_RC_OK; 186 } 187 188 sub client_join 189 { 190 my (undef, $server, $channel) = (shift, 191 shift =~ /(.+),irc_out1_join/i, 192 shift =~ /^join :?([^ ]*)/i); 193 ($server, $channel) = (lc $server, lc $channel); 194 195 reset_gc(); 196 197 ($_ eq '0' ? %{$channels{$server}} = () : $zombie{$server}{$_} = 1) 198 for (split ',', $channel); 199 return weechat::WEECHAT_RC_OK; 200 } 201 202 sub client_part 203 { 204 my (undef, $server, $channel) = (shift, 205 shift =~ /(.+),irc_out1_part/i, 206 shift =~ /^part ([^ ]*)/i); 207 ($server, $channel) = (lc $server, lc $channel); 208 209 delete $channels{$server}{$_} for (split ',', $channel); 210 return weechat::WEECHAT_RC_OK; 211 } 212 213 # RPL_WELCOME 214 sub irc_001 215 { 216 my (undef, $server, $message) = (shift, 217 shift =~ /(.+),irc_raw_in_001/, shift); 218 219 $server = lc $server; 220 return weechat::WEECHAT_RC_OK unless $message =~ / :- Welcome to ZNC -$/; 221 222 my $ignore_conf = lc weechat::config_get_plugin('ignore'); 223 return weechat::WEECHAT_RC_OK if $ignore_conf =~ /(^|,)$server($|,)/; 224 225 weechat::config_set_plugin('ignore', "$ignore_conf,$server"); 226 227 return weechat::WEECHAT_RC_OK; 228 } 229 230 sub irc_join 231 { 232 my ($server, $message, $msghash) = (lc $_[2], $_[3], ircparse($_[3])); 233 my ($nick, $channel) = ($msghash->{nick}, lc $msghash->{channel}); 234 my $buffer = ircbuf("$server.$channel"); 235 236 return $message if exists $channels{$server}{$channel}; 237 if (exists $zombie{$server}{$channel} || ignored($server)) { 238 delete $zombie{$server}{$channel}; 239 $channels{$server}{$channel} = 1; 240 return $message; 241 } 242 # XXX return $message unless mynick($buffer, $nick); 243 244 $part{$server}{$channel} = 1; 245 $timeout_cb = weechat::hook_timer( 246 weechat::config_get_plugin('delay'), 0, 1, 'irc_join_delay', $buffer) 247 unless $timeout_cb || !weechat::config_get_plugin('autopart'); 248 249 return $message unless nobufs(); 250 251 $fuckbuf = weechat::buffer_new( 252 'antifuck', 253 'fuckbuf_input', 254 '', 255 'fuckbuf_close', 256 '' 257 ) unless $fuckbuf; 258 weechat::print($fuckbuf, weechat::prefix('join'). 259 weechat::color('irc.color.message_join'). 260 'You were forced to join '.weechat::color('chat_channel').$channel. 261 weechat::color('irc.color.message_join').', leaving'); 262 263 return ''; 264 } 265 266 # RPL_ENDOFNAMES 267 sub irc_366 268 { 269 my ($server, $message) = ($_[2], $_[3]); 270 my ($nick, $channel) = $message =~ /^:[^ ]* 366 ([^ ]*) ([^ ]*)/i; 271 my $buffer = ircbuf("$server.$channel"); 272 ($server, $channel) = (lc $server, lc $channel); 273 274 return $message if exists $channels{$server}{$channel}; 275 return '' if nobufs(); 276 277 weechat::print($buffer, weechat::prefix('network'). 278 'Forcejoined, not syncing modes'); 279 280 return ''; 281 } 282 283 # ERR_LINKCHANNEL 284 sub irc_470 285 { 286 my (undef, $server, $oldchan, $newchan) = (shift, 287 shift =~ /(.+),irc_raw_in_470/, 288 shift =~ /^:[^ ]* 470 [^ ]+ ([^ ]+) ([^ ]+)/); 289 ($server, $oldchan, $newchan) = (lc $server, lc $oldchan, lc $newchan); 290 291 delete $channels{$server}{$oldchan}; 292 $channels{$server}{$newchan} = 1 if weechat::config_get_plugin('forward'); 293 return weechat::WEECHAT_RC_OK; 294 } 295 296 sub irc_join_delay 297 { 298 my $buffer = shift; 299 300 for my $server (keys %part) { 301 my $chans = ''; 302 303 for my $chan (keys %{$part{$server}}) { 304 if (length($chans) + length($chan) > 500) { 305 weechat::hook_signal_send('irc_input_send', 306 weechat::WEECHAT_HOOK_SIGNAL_STRING, 307 "$server;;priority_low;;/part $chans"); 308 $chans = ''; 309 } 310 311 $chans .= "$chan,"; 312 } 313 314 weechat::hook_signal_send('irc_input_send', 315 weechat::WEECHAT_HOOK_SIGNAL_STRING, 316 "$server;;priority_low;;/part $chans"); 317 } 318 $timeout_cb = ''; 319 %part = (); 320 return weechat::WEECHAT_RC_OK; 321 } 322 323 sub run_gc 324 { 325 %zombie = (); 326 return weechat::WEECHAT_RC_OK; 327 } 328 329 sub irc_part 330 { 331 my ($server, $message, $msghash) = ($_[2], $_[3], ircparse($_[3])); 332 my ($arj, $arj_delay, $arjd, $arjd_delay) = ( 333 weechat::config_get("irc.server.$server.autorejoin"), 334 weechat::config_get("irc.server.$server.autorejoin_delay"), 335 weechat::config_get("irc.server_default.autorejoin"), 336 weechat::config_get("irc.server_default.autorejoin_delay") 337 ); 338 return $message unless ( 339 weechat::config_option_is_null($arj) ? 340 weechat::config_boolean($arjd) : 341 weechat::config_boolean($arj) 342 ); 343 344 my ($nick, $channel, $reason) = ($msghash->{nick}, $msghash->{channel}, 345 $msghash->{text}); 346 347 my $buffer = ircbuf("$server.$channel"); 348 my ($lserver, $lchannel) = (lc $server, lc $channel); 349 350 return $message unless mynick($buffer, $nick); 351 return $message unless exists $channels{$lserver}{$lchannel}; 352 return $message if ignored($lserver); 353 354 weechat::print($buffer, weechat::prefix('quit'). 355 weechat::color('irc.color.message_quit'). 356 'You were forced to part '.weechat::color('chat_channel').$channel. 357 weechat::color('chat_delimiters').' ('.weechat::color('reset'). 358 $reason.weechat::color('chat_delimiters').')'. 359 weechat::color('irc.color.message_quit').', rejoining'); 360 my $delay = ( 361 weechat::config_option_is_null($arj_delay) ? 362 weechat::config_integer($arjd_delay) : 363 weechat::config_integer($arj_delay) 364 ); 365 weechat::command($buffer, ($delay ? "/wait $delay " : ""). 366 "/join $channel"); 367 368 return ''; 369 }