diff --git a/scripts/antifuck.pl b/scripts/antifuck.pl index 67f5915..f83e853 100644 --- a/scripts/antifuck.pl +++ b/scripts/antifuck.pl @@ -7,7 +7,7 @@ no strict 'subs'; my $SCRIPT_NAME = 'antifuck'; my $SCRIPT_AUTHOR = 'The Krusty Krab '; -my $SCRIPT_VERSION = '1.0'; +my $SCRIPT_VERSION = '1.1'; my $SCRIPT_LICENCE = 'Public domain'; my $SCRIPT_DESC = 'Defend against forcejoins (e.g. from fuckyou.pl) and '. 'forceparts (e.g. from /remove)'; @@ -18,9 +18,18 @@ my %OPTIONS = ( delay => ['Delay in milliseconds to wait before autoparting', '5000'], forward => ['Whether to allow channel forwards (+f on freenode)', '1'], ignore => ['Servers to ignore (e.g. for bouncers), separated by comma', ''], + nobufs => ['If 1, do not create buffers for forcejoined channels', '0'], + timeout => + ['Delay in milliseconds to wait for server to send JOIN after join', + '60000'], ); -my (%channels, %part, %partbuf, $fuckbuf, $timeout_cb); +# %channels: channels we joined and received JOIN / NAMES for +# %zombie: channels we joined but aren't yet in +# %part: channels we were forced into and will part soon +# %partbuf: buffers belonging to parted channels, we'll close these on +# /antifuck part +our (%channels, %zombie, %part, %partbuf, $fuckbuf, $timeout_cb, $gc_cb); if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION, $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) { @@ -44,6 +53,7 @@ HELP weechat::hook_signal('*,irc_raw_in_001', 'irc_001', ''); weechat::hook_signal('*,irc_raw_in_470', 'irc_470', ''); weechat::hook_modifier('irc_in_366', 'irc_366', ''); + weechat::hook_modifier('irc_in_join', 'irc_join', ''); weechat::hook_modifier('irc_in_part', 'irc_part', ''); for my $option (keys %OPTIONS) { @@ -79,6 +89,12 @@ sub ignored return $ignore_conf =~ /(^|,)$server($|,)/; } +sub nobufs { weechat::config_get_plugin('nobufs') } + +sub ircbuf { weechat::buffer_search('irc', "(?i)".(join '.', @_)) } +sub ircparse { weechat::info_get_hashtable(irc_message_parse => + { message => shift }) } + sub servchan { my $buf = shift; @@ -87,6 +103,13 @@ sub servchan lc weechat::buffer_get_string($buf, 'localvar_channel')); } +sub reset_gc +{ + weechat::unhook($gc_cb) if $gc_cb; + $gc_cb = weechat::hook_timer(weechat::config_get_plugin('nobufs'), 0, 1, + 'run_gc', ''); +} + sub cmd_antifuck { my (undef, $buffer, $args) = @_; @@ -100,10 +123,7 @@ sub cmd_antifuck return weechat::WEECHAT_RC_OK; } -sub fuckbuf_input -{ - return weechat::WEECHAT_RC_OK; -} +sub fuckbuf_input { return weechat::WEECHAT_RC_OK; } sub fuckbuf_close { @@ -120,7 +140,7 @@ sub irc_connect my ($autojoin) = (weechat::config_string(weechat::config_get( "irc.server.$server.autojoin")) =~ /^([^ ]*)/); - $channels{$server}{$_} = 1 for (split ',', lc($autojoin)); + $zombie{$server}{$_} = 1 for (split ',', lc($autojoin)); return weechat::WEECHAT_RC_OK; } @@ -131,6 +151,7 @@ sub irc_disconnect $server = lc $server; delete $channels{$server}; + delete $zombie{$server}; delete $part{$server}; return weechat::WEECHAT_RC_OK; @@ -139,7 +160,6 @@ sub irc_disconnect sub buffer_opened { my $buffer = pop; my ($server, $channel) = servchan($buffer); - return weechat::WEECHAT_RC_OK if exists $channels{$server}{$channel}; return weechat::WEECHAT_RC_OK if ignored($server); @@ -172,7 +192,9 @@ sub client_join shift =~ /^join :?([^ ]*)/i); ($server, $channel) = (lc $server, lc $channel); - ($_ eq '0' ? %{$channels{$server}} = () : $channels{$server}{$_} = 1) + reset_gc(); + + ($_ eq '0' ? %{$channels{$server}} = () : $zombie{$server}{$_} = 1) for (split ',', $channel); return weechat::WEECHAT_RC_OK; } @@ -188,6 +210,7 @@ sub client_part return weechat::WEECHAT_RC_OK; } +# RPL_WELCOME sub irc_001 { my (undef, $server, $message) = (shift, @@ -204,30 +227,61 @@ sub irc_001 return weechat::WEECHAT_RC_OK; } -sub irc_366 +sub irc_join { - my ($server, $message) = ($_[2], $_[3]); - my ($nick, $channel) = $message =~ /^:[^ ]* 366 ([^ ]*) ([^ ]*)/i; - my $buffer = weechat::buffer_search('irc', "$server.$channel"); - ($server, $channel) = (lc $server, lc $channel); + my ($server, $message, $msghash) = (lc $_[2], $_[3], ircparse($_[3])); + my ($nick, $channel) = ($msghash->{nick}, $msghash->{channel}); + my $buffer = ircbuf("$server.$channel"); - return $message unless mynick($buffer, $nick); + if (exists $zombie{$server}{$channel} || ignored($server)) { + delete $zombie{$server}{$channel}; + $channels{$server}{$channel} = 1; + return $message; + } + # XXX return $message unless mynick($buffer, $nick); return $message if exists $channels{$server}{$channel}; - return $message if ignored($server); - - weechat::print($buffer, weechat::prefix('network'). - 'Forcejoined, not syncing modes'); - return '' unless weechat::config_get_plugin('autopart'); $part{$server}{$channel} = 1; - $timeout_cb = weechat::hook_timer( weechat::config_get_plugin('delay'), 0, 1, 'irc_join_delay', $buffer) - unless $timeout_cb; + unless $timeout_cb || !weechat::config_get_plugin('autopart'); + + return $message unless nobufs(); + + $fuckbuf = weechat::buffer_new( + 'antifuck', + 'fuckbuf_input', + '', + 'fuckbuf_close', + '' + ) unless $fuckbuf; + weechat::print($fuckbuf, weechat::prefix('join'). + weechat::color('irc.color.message_join'). + 'You were forced to join '.weechat::color('chat_channel').$channel. + weechat::color('reset').weechat::color('irc.color.message_join'). + ', leaving'); return ''; } +# RPL_ENDOFNAMES +sub irc_366 +{ + my ($server, $message) = ($_[2], $_[3]); + my ($nick, $channel) = $message =~ /^:[^ ]* 366 ([^ ]*) ([^ ]*)/i; + my $buffer = ircbuf("$server.$channel"); + ($server, $channel) = (lc $server, lc $channel); + + return $message if exists $channels{$server}{$channel}; + return '' if nobufs(); + + weechat::print($buffer, weechat::prefix('network'). + 'Forcejoined, not syncing modes'); + + return ''; +} + +# ERR_LINKCHANNEL sub irc_470 { my (undef, $server, $oldchan, $newchan) = (shift, @@ -267,6 +321,12 @@ sub irc_join_delay return weechat::WEECHAT_RC_OK; } +sub run_gc +{ + %zombie = (); + return weechat::WEECHAT_RC_OK; +} + sub irc_part { my ($server, $message) = ($_[2], $_[3]); @@ -283,7 +343,7 @@ sub irc_part ); my ($nick, $channel) = ($message =~ /^:([^!]*)[^ ]* part ([^ ]*)/i); - my $buffer = weechat::buffer_search('irc', "$server.$channel"); + my $buffer = ircbuf("$server.$channel"); my ($lserver, $lchannel) = (lc $server, lc $channel); return $message unless mynick($buffer, $nick);