diff options
Diffstat (limited to '.irssi/scripts/recentdepart.pl')
-rw-r--r-- | .irssi/scripts/recentdepart.pl | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/.irssi/scripts/recentdepart.pl b/.irssi/scripts/recentdepart.pl new file mode 100644 index 0000000..efb8b95 --- /dev/null +++ b/.irssi/scripts/recentdepart.pl @@ -0,0 +1,332 @@ +#!/usr/bin/perl -w +# +# recentdepart.pl +# +# irssi script +# +# This script, when loaded into irssi, will filter quit and parted messages +# for channels listed in recdep_channels for any nick whos last message was +# more then a specified time ago. +# +# It also filters join messages showing only join messages for nicks who recently +# parted. +# +# [settings] +# recdep_channels +# - Should contain a list of chatnet and channel names that recentdepart +# should monitor. Its format is a spcae delimited list of chatnet/#channel +# pairs. Either chatnet or channel are optional but adding a / makes it +# explicitly recognized as a chatnet or a channel name. A special case is just a +# "*" which turns it on globally. +# +# "#irrsi #perl" - enables filtering on the #irssi and #perl +# channels on all chatnets. +# +# "freenode IRCNet/#irssi" - enables filtering for all channels on frenode +# and only the #irssi channel on IRCNet. +# +# "freenode/" - force "freenode" to be interpreted as the chatnet +# name by adding a / to the end. +# +# "/freenode" - forces "freenode" to be interpreted as the channel +# by prefixing it with the / delimiter. +# +# "*" - globally enables filtering. +# +# recdep_period +# - specifies the window of time, after a nick last spoke, for which quit/part +# notices will be let through the filter. +# +# recdep_rejoin +# - specifies a time period durring which a join notice for someone rejoining will +# be shown. Join messages are filtered if the nicks part/quit message was filtered +# or if the nick is gone longer then the rejoin period. +# Set to 0 to turn off filtering of join notices. +# +# recdep_nickperiod +# - specifies a window of time like recdep_period that is used to filter nick change +# notices. Set to 0 to turn off filtering of nick changes. +# +# recdep_use_hideshow +# - whether to use hideshow script instead of ignoring +# + +use strict; +use warnings; +use Irssi; +use Irssi::Irc; + +our $VERSION = "0.7"; +our %IRSSI = ( + authors => 'Matthew Sytsma', + contact => 'spiderpigy@yahoo.com', + name => 'Recently Departed', + description => 'Filters quit/part/join/nick notices based on time since last message. (Similar to weechat\'s smartfilter).', + license => 'GNU GPLv2 or later', + url => '', +); + +# store a hash of configure selected servers/channels +my %chanlist; +# Track recent times by server/nick/channel +# (it is more optimal to go nick/channel then channel/nick because some quit signals are by server not by channel. +# We will only have to loop through open channels that a nick has spoken in which should be less then looping +# through all the monitored channels looking for the nick. +my %nickhash=(); +# Track recent times for parted nicks by server/channel/nick +my %joinwatch=(); +my $use_hide; + +sub on_setup_changed { + my %old_chanlist = %chanlist; + %chanlist = (); + my @pairs = split(/ /, Irssi::settings_get_str("recdep_channels")); + + $use_hide = Irssi::settings_get_bool("recdep_use_hideshow"); + foreach (@pairs) + { + my ($net, $chan, $more) = split(/\//); + if ($more) + { + /\/(.+)/; + $chan = $1; + } +# Irssi::active_win()->print("Initial Net: $net Chan: $chan"); + if (!$net) + { + $net = '*'; + } + + if ($net =~ /^[#!@&]/ && !$chan) + { + $chan = $net; + $net = "*"; + } + + if (!$chan) + { + $chan = "*"; + } + + $chanlist{$net}{$chan} = 1; + } + + # empty the storage in case theres a channel or server we are no longer filtering + %nickhash=(); + %joinwatch=(); +} + +sub check_channel +{ + my ($server, $channel) = @_; + + # quits dont have a channel so we need to see if this server possibly contains this channel + if (!$channel || $channel eq '*') + { + # see if any non chatnet channel listings are open on this server + if (keys %{ $chanlist{'*'} }) + { + foreach my $chan (keys %{ $chanlist{'*'} }) + { + if ($chan eq '*' || $server->channel_find($chan)) + { + return 1; + } + } + } + + # see if there were any channels listed for this chatnet + if (keys %{ $chanlist{$server->{'chatnet'}} }) + { return 1; } + else + { return 0; } + } + + # check for global channel matches and pair matches + return (($chanlist{'*'}{'*'}) || + ($chanlist{'*'}{$channel}) || + ($chanlist{$server->{'chatnet'}}{'*'}) || + ($chanlist{$server->{'chatnet'}}{$channel})); +} + +# Hook for quitting +sub on_quit +{ + my ($server, $nick, $address, $reason) = @_; + + if ($server->{'nick'} eq $nick) + { return; } + + if (check_channel($server, '*')) + { + my $recent = 0; + foreach my $chan (keys %{ $nickhash{$server->{'tag'}}{lc($nick)} }) + { + if (time() - $nickhash{$server->{'tag'}}{lc($nick)}{$chan} < Irssi::settings_get_int("recdep_period")) + { + $recent = 1; + + if (Irssi::settings_get_int("recdep_rejoin") > 0) + { + $joinwatch{$server->{'tag'}}{$chan}{lc($nick)} = time(); + } + } + } + + delete $nickhash{$server->{'tag'}}{lc($nick)}; + + if (!$recent) + { + $use_hide ? $Irssi::scripts::hideshow::hide_next = 1 + : Irssi::signal_stop(); + } + } +} + +# Hook for parting +sub on_part +{ + my ($server, $channel, $nick, $address, $reason) = @_; + + # cleanup if its you who left a channel + if ($server->{'nick'} eq $nick) + { + # slightly painfull cleanup but we shouldn't hit this as often + foreach my $nickd (keys %{ $nickhash{$server->{'tag'}} }) + { + delete $nickhash{$server->{'tag'}}{$nickd}{$channel}; + if (!keys(%{ $nickhash{$server->{'tag'}}{$nickd} })) + { + delete $nickhash{$server->{'tag'}}{$nickd}; + } + } + delete $joinwatch{$server->{'tag'}}{$channel}; + } + elsif (check_channel($server, $channel)) + { + if (!defined $nickhash{$server->{'tag'}}{lc($nick)}{$channel} || time() - $nickhash{$server->{'tag'}}{lc($nick)}{$channel} > Irssi::settings_get_int("recdep_period")) + { + $use_hide ? $Irssi::scripts::hideshow::hide_next = 1 + : Irssi::signal_stop(); + } + elsif (Irssi::settings_get_int("recdep_rejoin") > 0) + { + $joinwatch{$server->{'tag'}}{$channel}{lc($nick)} = time(); + } + + delete $nickhash{$server->{'tag'}}{lc($nick)}{$channel}; + if (!keys(%{ $nickhash{$server->{'tag'}}{lc($nick)} })) + { + delete $nickhash{$server->{'tag'}}{lc($nick)}; + } + } +} + +# Hook for public messages. +sub on_public +{ + my ($server, $msg, $nick, $addr, $target) = @_; + + if (!$target) { return; } + if ($nick =~ /^#/) { return; } + + if ($server->{'nick'} eq $nick) { return; } + + if (check_channel($server, $target)) + { + $nickhash{$server->{'tag'}}{lc($nick)}{$target} = time(); + } +} + +# Hook for people joining +sub on_join +{ + my ($server, $channel, $nick, $address) = @_; + + if ($server->{'nick'} eq $nick) + { return; } + + if (Irssi::settings_get_int("recdep_rejoin") == 0) + { return; } + + if (check_channel($server, $channel)) + { + if (!defined $joinwatch{$server->{'tag'}}{$channel}{lc($nick)} || time() - $joinwatch{$server->{'tag'}}{$channel}{lc($nick)} > Irssi::settings_get_int("recdep_rejoin")) + { + $use_hide ? $Irssi::scripts::hideshow::hide_next = 1 + : Irssi::signal_stop(); + } + } + + # loop through and delete all old nicks from the rejoin hash + # this should be a small loop because it will only inlude nicks who recently left channel and who + # passed the part message filter + foreach my $nickd (keys %{ $joinwatch{$server->{'tag'}}{$channel} }) + { + if (time() - $joinwatch{$server->{'tag'}}{$channel}{lc($nickd)} < Irssi::settings_get_int("recdep_rejoin")) + { next; } + + delete $joinwatch{$server->{'tag'}}{$channel}{lc($nickd)}; + } + if (!keys(%{ $joinwatch{$server->{'tag'}}{$channel} })) + { + delete $joinwatch{$server->{'tag'}}{$channel}; + } +} + +# Hook for nick changes +sub on_nick +{ + my ($server, $new, $old, $address) = @_; + + if ($server->{'nick'} eq $old || $server->{'nick'} eq $new) + { return; } + + if (check_channel($server, '*')) + { + my $recent = 0; + foreach my $chan (keys %{ $nickhash{$server->{'tag'}}{lc($old)} }) + { + if (time() - $nickhash{$server->{'tag'}}{lc($old)}{$chan} < Irssi::settings_get_int("recdep_nickperiod")) + { + $recent = 1; + } + } + + if (!$recent && Irssi::settings_get_int("recdep_nickperiod") > 0) + { + $use_hide ? $Irssi::scripts::hideshow::hide_next = 1 + : Irssi::signal_stop(); + } + + delete $nickhash{$server->{'tag'}}{lc($old)}; + } +} + + +# Hook for cleanup on server quit +sub on_serverquit +{ + my ($server, $msg) = @_; + + delete $nickhash{$server->{'tag'}}; + delete $joinwatch{$server->{'tag'}}; +} + +# Setup hooks on events +Irssi::signal_add_last("message public", "on_public"); +Irssi::signal_add_last("message part", "on_part"); +Irssi::signal_add_last("message quit", "on_quit"); +Irssi::signal_add_last("message nick", "on_nick"); +Irssi::signal_add_last("message join", "on_join"); +Irssi::signal_add_last("server disconnected", "on_serverquit"); +Irssi::signal_add_last("server quit", "on_serverquit"); +Irssi::signal_add('setup changed', "on_setup_changed"); + +# Add settings +Irssi::settings_add_str("recdentpepart", "recdep_channels", '*'); +Irssi::settings_add_int("recdentpepart", "recdep_period", 600); +Irssi::settings_add_int("recdentpepart", "recdep_rejoin", 120); +Irssi::settings_add_int("recdentpepart", "recdep_nickperiod", 600); +Irssi::settings_add_bool("recdentpepart", "recdep_use_hideshow", 0); +on_setup_changed(); |