diff options
Diffstat (limited to 'scripts/recentdepart.pl')
| -rw-r--r-- | scripts/recentdepart.pl | 332 | 
1 files changed, 332 insertions, 0 deletions
| diff --git a/scripts/recentdepart.pl b/scripts/recentdepart.pl new file mode 100644 index 0000000..f0cc121 --- /dev/null +++ b/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.6"; +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 (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 (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(); | 
