From 00df59df39e9685765c7b59a6fd30832adda3495 Mon Sep 17 00:00:00 2001 From: wowaname Date: Sun, 18 Sep 2016 00:00:50 +0000 Subject: [PATCH] add scripts/antifuck.pl --- scripts/antifuck.pl | 227 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 scripts/antifuck.pl diff --git a/scripts/antifuck.pl b/scripts/antifuck.pl new file mode 100644 index 0000000..8683091 --- /dev/null +++ b/scripts/antifuck.pl @@ -0,0 +1,227 @@ +# Released into the Public Domain + +use strict; +use warnings; + +no strict 'subs'; + +my $SCRIPT_NAME = 'antifuck'; +my $SCRIPT_AUTHOR = 'The Krusty Krab '; +my $SCRIPT_VERSION = '0.1'; +my $SCRIPT_LICENCE = 'Public domain'; +my $SCRIPT_DESC = 'Defend against forcejoins (e.g. from fuckyou.pl) and '. + 'forceparts (e.g. from /remove)'; + +my %OPTIONS = ( + autopart => ['Whether to automatically part forcejoined channels. '. + 'You can always do this manually with /antifuck part', '0'], + delay => ['Delay in milliseconds to wait before autoparting', '5000'], + forward => ['Whether to allow channel forwards (+f on freenode)', '1'], + ); + +my (%channels, %part, @partbuf, $fuckbuf, $timeout_cb); + +if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION, + $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) { + weechat::hook_command('antifuck', $SCRIPT_DESC, 'part', <<'HELP', +This script defends against forced joins, such as from irssi's fuckyou.pl or +from channel forwards, as well as forced parts, such as from the /remove +command. You can configure certain behaviour using the options under +"plugins.var.perl.antifuck.*". Configure rejoin-on-/remove with the +irc.server_default.autorejoin and .autorejoin_delay commands. +HELP + 'part', 'cmd_antifuck', ''); + weechat::hook_signal('irc_server_connected', 'irc_connect', ''); + weechat::hook_signal('irc_server_disconnected', 'irc_disconnect', ''); + #weechat::hook_signal('irc_channel_opened', 'buffer_opened', ''); + weechat::hook_signal('*,irc_out1_join', 'client_join', ''); + weechat::hook_signal('*,irc_out1_part', 'client_part', ''); + weechat::hook_modifier('irc_in_366', 'irc_366', ''); + weechat::hook_modifier('irc_in_part', 'irc_part', ''); + + for my $option (keys %OPTIONS) { + weechat::config_set_plugin($option, $OPTIONS{$option}[1]) + unless weechat::config_is_set_plugin($option); + weechat::config_set_desc_plugin($option, $OPTIONS{$option}[0]); + } +} + +sub mynick { + my ($buf, $nick) = ($_[0], $_[1]); + return lc weechat::buffer_get_string($buf, 'localvar_nick') eq lc $nick; +# my $hd_serv = weechat::hdata_get('irc_server'); +# my $hd_servs = weechat::hdata_get_list($hd_serv, 'irc_servers'); +# +# $hd_serv = weechat::hdata_search( +# $hd_serv, $hd_servs, '${irc_server.name} == '. +# weechat::buffer_get_string($buf, 'localvar_server'), 1); +# +# return lc weechat::hdata_string($hd_serv, $buf, 'nick') eq lc $nick; +} + +sub servchan { + my $buf = shift; + return (lc weechat::buffer_get_string($buf, 'localvar_server'), + lc weechat::buffer_get_string($buf, 'localvar_channel')); +} + +sub cmd_antifuck { + my (undef, $buffer, $args) = @_; + weechat::print('',"$_: ".join(' ', keys %{ $part{$_} })) for (keys %part); +} + +sub fuckbuf_input { + return weechat::WEECHAT_RC_OK; +} + +sub fuckbuf_close { + $fuckbuf = ''; + return weechat::WEECHAT_RC_OK; +} + +sub irc_connect { + my $server = pop; + my ($autojoin) = lc (weechat::config_string(weechat::config_get( + "irc.server.$server.autojoin")) =~ /^([^ ]*)/); + $channels{$server}{$_} = 1 for (split ',', $autojoin); + return weechat::WEECHAT_RC_OK; +} + +sub irc_disconnect { + my $server = pop; + $server = lc $server; + delete $channels{$server}; + delete $part{$server}; + return weechat::WEECHAT_RC_OK; +} + +sub buffer_opened { + my $buffer = pop; + weechat::print('',$buffer); + return weechat::WEECHAT_RC_OK + if weechat::buffer_get_string($buffer, 'localvar_plugin') ne 'irc'; + + my ($server, $channel) = servchan($buffer); + return weechat::WEECHAT_RC_OK if exists $channels{$server}{$channel}; + + $fuckbuf = weechat::buffer_new( + 'antifuck', + 'fuckbuf_input', + '', + 'fuckbuf_close', + '' + ) unless $fuckbuf; + + weechat::buffer_merge($buffer, $fuckbuf); + return weechat::WEECHAT_RC_OK unless weechat::config_get_plugin('autopart'); + + #push @partbuf, $buffer; + return weechat::WEECHAT_RC_OK; +} + +sub client_join { + my (undef, $server, $channel) = (shift, + shift =~ /(.+),irc_out1_join/i, + shift =~ /^join :?([^ ]*)/i); + ($server, $channel) = (lc $server, lc $channel); + + $channels{$server}{$channel} = 1; + return weechat::WEECHAT_RC_OK; +} + +sub client_part { + my (undef, $server, $channel) = (shift, + shift =~ /(.+),irc_out1_part/i, + shift =~ /^part ([^ ]*)/i); + ($server, $channel) = (lc $server, lc $channel); + + delete $channels{$server}{$channel}; + return weechat::WEECHAT_RC_OK; +} + +sub irc_366 { + 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); + + return $message unless mynick($buffer, $nick); + return $message if exists $channels{$server}{$channel}; + + 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; + + return ''; +} + +sub irc_join_delay { + my $buffer = shift; + + for my $server (values %part) { + my $chans = ''; + + for my $chan (keys %$server) { + if (length($chans) + length($chan) > 500) { + weechat::command($buffer, "/part $chans"); + #weechat::hook_signal_send('irc_input_send', + # weechat::WEECHAT_HOOK_SIGNAL_STRING, + # "$server;;priority_low;;/part $chans"); + $chans = ''; + } + + $chans .= "$chan,"; + } + + weechat::command($buffer, "/part $chans"); + #weechat::hook_signal_send('irc_input_send', + # weechat::WEECHAT_HOOK_SIGNAL_STRING, + # "$server;;priority_low;;/part $chans"); + } + $timeout_cb = ''; + %part = (); + return weechat::WEECHAT_RC_OK; +} + +sub irc_part { + my ($server, $message) = ($_[2], $_[3]); + my ($arj, $arj_delay, $arjd, $arjd_delay) = ( + weechat::config_get("irc.server.$server.autorejoin"), + weechat::config_get("irc.server.$server.autorejoin_delay"), + weechat::config_get("irc.server_default.autorejoin"), + weechat::config_get("irc.server_default.autorejoin_delay") + ); + return $message unless ( + weechat::config_option_is_null($arj) ? + weechat::config_boolean($arjd) : + weechat::config_boolean($arj) + ); + + my ($nick, $channel) = ($message =~ /^:([^!]*)[^ ]* part ([^ ]*)/i); + my $buffer = weechat::buffer_search('irc', "$server.$channel"); + my ($lserver, $lchannel) = (lc $server, lc $channel); + + return $message unless mynick($buffer, $nick); + return $message unless exists $channels{$lserver}{$lchannel}; + + weechat::print($buffer, weechat::prefix('quit'). + weechat::color('irc.color.message_quit'). + 'You were forced to part '.weechat::color('chat_channel').$channel. + weechat::color('reset').weechat::color('irc.color.message_quit'). + ', rejoining'); + my $delay = ( + weechat::config_option_is_null($arj_delay) ? + weechat::config_integer($arjd_delay) : + weechat::config_integer($arj_delay) + ); + weechat::command($buffer, ($delay ? "/wait $delay " : ""). + "/join $channel"); + + return ''; +}