Advertisement
Techman

antifuck-1.1.pl

Feb 1st, 2018
498
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 10.55 KB | None | 0 0
  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 <[email protected]>';
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement