weechat-opal/scripts/antifuck.pl

296 lines
8.0 KiB
Perl
Raw Normal View History

2016-09-18 00:00:50 +00:00
# Released into the Public Domain
use strict;
use warnings;
no strict 'subs';
my $SCRIPT_NAME = 'antifuck';
my $SCRIPT_AUTHOR = 'The Krusty Krab <wowaname@volatile.ch>';
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'],
2016-11-27 13:17:30 +00:00
ignore => ['Servers to ignore (e.g. for bouncers), separated by comma', ''],
2016-09-18 00:00:50 +00:00
);
my (%channels, %part, %partbuf, $fuckbuf, $timeout_cb);
2016-09-18 00:00:50 +00:00
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.
2016-09-18 00:01:42 +00:00
Running "/antifuck part" will close all forcejoined channels and part them where
appropriate.
2016-09-18 00:00:50 +00:00
HELP
'part', 'cmd_antifuck', '');
weechat::hook_signal('irc_server_connected', 'irc_connect', '');
weechat::hook_signal('irc_server_disconnected', 'irc_disconnect', '');
2016-09-18 00:01:42 +00:00
weechat::hook_signal('irc_channel_opened', 'buffer_opened', '');
weechat::hook_signal('buffer_closed', 'buffer_closed', '');
2016-09-18 00:00:50 +00:00
weechat::hook_signal('*,irc_out1_join', 'client_join', '');
weechat::hook_signal('*,irc_out1_part', 'client_part', '');
weechat::hook_signal('*,irc_raw_in_001', 'irc_001', '');
2016-09-18 00:00:50 +00:00
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]);
}
my $iptr = weechat::infolist_get('buffer', '', '');
while (weechat::infolist_next($iptr)) {
next unless weechat::infolist_string($iptr, 'plugin_name') eq 'irc';
my $buf = weechat::infolist_pointer($iptr, 'pointer');
$channels{
lc weechat::buffer_get_string($buf, 'localvar_server')}{
lc weechat::buffer_get_string($buf, 'localvar_channel')} = 1;
}
weechat::infolist_free($iptr);
2016-09-18 00:00:50 +00:00
}
2016-11-27 12:15:12 +00:00
sub mynick
{
2016-09-18 00:00:50 +00:00
my ($buf, $nick) = ($_[0], $_[1]);
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
return lc weechat::buffer_get_string($buf, 'localvar_nick') eq lc $nick;
}
sub ignored
{
my $server = shift;
my $ignore_conf = lc weechat::config_get_plugin('ignore');
return $ignore_conf =~ /(^|,)$server($|,)/;
}
2016-11-27 12:15:12 +00:00
sub servchan
{
2016-09-18 00:00:50 +00:00
my $buf = shift;
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
return (lc weechat::buffer_get_string($buf, 'localvar_server'),
lc weechat::buffer_get_string($buf, 'localvar_channel'));
}
2016-11-27 12:15:12 +00:00
sub cmd_antifuck
{
2016-09-18 00:00:50 +00:00
my (undef, $buffer, $args) = @_;
2016-09-18 00:01:42 +00:00
if ($args eq 'part') {
# TODO: we really need to spend more time here making sure we send the
# fewest PARTs possible, a la irc_join_delay
weechat::buffer_close($fuckbuf);
}
return weechat::WEECHAT_RC_OK;
2016-09-18 00:00:50 +00:00
}
2016-11-27 12:15:12 +00:00
sub fuckbuf_input
{
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub fuckbuf_close
{
weechat::buffer_close($_) for (keys %partbuf);
%partbuf = ();
2016-11-27 12:15:12 +00:00
$fuckbuf = '';
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub irc_connect
{
2016-09-18 00:00:50 +00:00
my $server = pop;
my ($autojoin) = (weechat::config_string(weechat::config_get(
2016-09-18 00:00:50 +00:00
"irc.server.$server.autojoin")) =~ /^([^ ]*)/);
2016-11-27 12:15:12 +00:00
$channels{$server}{$_} = 1 for (split ',', lc($autojoin));
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub irc_disconnect
{
2016-09-18 00:00:50 +00:00
my $server = pop;
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
$server = lc $server;
delete $channels{$server};
delete $part{$server};
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
sub buffer_opened {
my $buffer = pop;
my ($server, $channel) = servchan($buffer);
2016-11-27 12:15:12 +00:00
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK if exists $channels{$server}{$channel};
return weechat::WEECHAT_RC_OK if ignored($server);
2016-09-18 00:00:50 +00:00
$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');
$partbuf{$buffer} = 1;
return weechat::WEECHAT_RC_OK;
}
sub buffer_closed {
my $buffer = pop;
2016-09-18 00:00:50 +00:00
delete $partbuf{$buffer};
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub client_join
{
2016-09-18 00:00:50 +00:00
my (undef, $server, $channel) = (shift,
shift =~ /(.+),irc_out1_join/i,
shift =~ /^join :?([^ ]*)/i);
($server, $channel) = (lc $server, lc $channel);
2016-09-30 22:41:09 +00:00
$channels{$server}{$_} = 1 for (split ',', $channel);
2016-09-18 00:00:50 +00:00
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub client_part
{
2016-09-18 00:00:50 +00:00
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_001
{
my (undef, $server, $message) = (shift,
shift =~ /(.+),irc_raw_in_001/, shift);
$server = lc $server;
return weechat::WEECHAT_RC_OK unless $message =~ / :- Welcome to ZNC -$/;
my $ignore_conf = lc weechat::config_get_plugin('ignore');
return weechat::WEECHAT_RC_OK if $ignore_conf =~ /(^|,)$server($|,)/;
weechat::config_set_plugin('ignore', "$ignore_conf,$server");
return weechat::WEECHAT_RC_OK;
}
2016-11-27 12:15:12 +00:00
sub irc_366
{
2016-09-18 00:00:50 +00:00
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};
return $message if ignored($server);
2016-09-18 00:00:50 +00:00
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 '';
}
2016-11-27 12:15:12 +00:00
sub irc_join_delay
{
2016-09-18 00:00:50 +00:00
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;
}
2016-11-27 12:15:12 +00:00
sub irc_part
{
2016-09-18 00:00:50 +00:00
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};
return $message if ignored($lserver);
2016-09-18 00:00:50 +00:00
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 '';
}