aboutsummaryrefslogtreecommitdiff
path: root/.irssi/scripts/recentdepart.pl
diff options
context:
space:
mode:
Diffstat (limited to '.irssi/scripts/recentdepart.pl')
-rw-r--r--.irssi/scripts/recentdepart.pl332
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();