22use Irssi;
33use vars qw( $VERSION %IRSSI) ;
44
5- $VERSION = " 1.01 " ;
5+ $VERSION = " 1.02 " ;
66%IRSSI = (
77 name => " zmartfilter" ,
88 description => " smartfilter.pl reimagined, optimized for unusually flakey networks such as IRC over I2P" ,
2626
2727
2828Irssi::theme_register([
29- squelched => " {line_start} { channick_hilight \$ 0} {chanhost_hilight \$ 1} squelched" ,
29+ squelched => " {channick_hilight \$ 0} {chanhost_hilight \$ 1} squelched" ,
3030]);
3131
3232
@@ -135,13 +135,29 @@ sub message_kick {
135135 activity($server , $channel , undef , $nick );
136136}
137137
138+ sub message_nick {
139+ my ($server , $newnick , $oldnick ) = @_ ;
140+ # if this user recently joined any channels then entries relating to
141+ # $oldnick in the tjoined table need to be copied with $newnick; no
142+ # reason to bother deleting the $oldnick entries now, they will get
143+ # collected after $join_time elapses
144+ for my $oldkey (keys %tjoined ) {
145+ my ($s , $t , $n ) = split (/ $; / , $oldkey );
146+ if ($s eq $server -> {tag } && $n eq $oldnick ) {
147+ my $newkey = join ($; , $s , $t , $newnick );
148+ $tjoined {$newkey } = $tjoined {$oldkey };
149+ }
150+ }
151+ }
152+
138153sub message_server_channel_nick_address { activity(@_ [0, 1, 3, 2]); }
139154
140155Irssi::signal_add({
141156 " message public" => \&message_server_x_x_address_target,
142157 " message own_public" => \&message_own_public,
143158 " message join" => \&message_join,
144159 " message kick" => \&message_kick,
160+ " message nick" => \&message_nick,
145161 " message invite" => \&message_server_channel_nick_address,
146162 " message topic" => sub { activity(@_ [0, 1, 4]); },
147163 " message irc op_public" => \&message_server_x_x_address_target,
@@ -158,20 +174,45 @@ sub message_kick {
158174sub print_text {
159175 my ($dest , $text , $stripped ) = @_ ;
160176
161- # only filter text bound for channel windows
162- my ($now , $server , $target ) = ( time (), $dest -> {server }, $dest -> { target } );
163- if (!$server || !$server -> {connected } || ! $server -> ischannel( $target ) ) {
177+ # only filter text bound for a dest with a connected server
178+ my ($now , $server ) = ( time (), $dest -> {server } );
179+ if (!$server || !$server -> {connected }) {
164180 return ;
165181 }
166182
167- # don't filter text bound for channels in the whitelist
168- if (grep { $_ eq $target } @whitelist_channels ) {
183+ my ($level , @targets ) = $dest -> {level };
184+ if ($level & (MSGLEVEL_NICKS | MSGLEVEL_QUITS)) {
185+ # nick changes and quits are printed only once per window, so
186+ # $dest could reference a channel where this user is considered
187+ # inactive when there is another channel in the same window
188+ # (e.g., /JOIN -window or /QUERY -window) where the user is
189+ # considered active, in which case the text would be
190+ # erroneously suppressed; so all further processing must
191+ # consider every windowitem associated with this window and
192+ # server
193+ @targets = grep { $_ -> {server } && $_ -> {server }-> {tag } eq $server -> {tag } } $dest -> {window }-> items();
194+ } else {
195+ # other messages are printed for each windowitem, even if
196+ # they're in the same window, so @targets includes only the
197+ # single relevant windowitem
198+ @targets = ( $dest -> {window }-> item_find($server , $dest -> {target }) );
199+ }
200+
201+ # only filter text bound only for channels
202+ if (grep { !$server -> ischannel($_ -> {name }) } @targets ) {
169203 return ;
170204 }
171205
172- my ($level , @nicks , %addresses ) = $dest -> {level };
206+ # don't filter text bound for channels in the whitelist
207+ for my $target (@targets ) {
208+ if (grep { $_ eq $target -> {name } } @whitelist_channels ) {
209+ return ;
210+ }
211+ }
212+
213+ my (@nicks , %addresses );
173214 if ($level & (MSGLEVEL_JOINS | MSGLEVEL_PARTS | MSGLEVEL_QUITS)) {
174- if ($stripped =~ / ([^ ]+) \[ ([^]]+)\] has (joined|left|quit)/ ) {
215+ if ($stripped =~ / ([^ ]+) \[ ([^]]+)\] has (changed| joined|left|quit)/ ) {
175216 @nicks = ($1 );
176217 # this nick may have just parted or quit, in which case
177218 # we can't rely on the channel->nick->address lookup,
@@ -197,48 +238,48 @@ sub print_text {
197238 my $slevel = MSGLEVEL_JOINS | MSGLEVEL_PARTS | MSGLEVEL_QUITS |
198239 MSGLEVEL_NICKS | MSGLEVEL_MODES;
199240 my ($athreshold , $jthreshold ) = ( $now - $allow_time , $now - $join_time );
200- for my $nick (@nicks ) {
241+ for my $target ( @targets ) { for my $ nick (@nicks ) {
201242 if ($nick eq $server -> {nick }) {
202243 # it's text that relates to me
203244 return ;
204245 }
205246 my $address = $addresses {$nick };
206247 if (!$address ) {
207- $address = $server -> channel_find($target );
208- $address = $address -> nick_find($nick );
248+ $address = $target -> nick_find($nick );
209249 $address = $address -> {host };
210250 if (!$address ) {
211251 next ;
212252 }
253+ $addresses {$nick } = $address ; # for future iterations
213254 }
214255 if ($server -> mask_match_address(' *!*@services.*' , " " , $address )) {
215256 # relates to network services
216257 return ;
217258 }
218- my $key = join ($; , $server -> {tag }, $target , $address );
259+ my $key = join ($; , $server -> {tag }, $target -> { name } , $address );
219260 my $tstamp = $tactive {$key };
220261 if ($tstamp && $athreshold < $tstamp ) {
221262 if (0 < $allow_max && ++$nallowed {$key } <= $allow_max ) {
222263 # relates to an active user who hasn't been
223264 # squelched by $allow_max yet
224265 return ;
225266 }
226- $server -> printformat($target , $slevel , " squelched" ,
267+ $server -> printformat($target -> { name } , $slevel , " squelched" ,
227268 $nick , $address );
228269 delete $tactive {$key };
229270 delete $nallowed {$key };
230271 }
231272 if ($level & MSGLEVEL_MODES) {
232- # also check whether any nicks affected a mode change
233- # were NOT recently joined, in which case this was a
234- # spontaneous mode change (perhaps a new operator
273+ # also check whether any nicks affected by a mode
274+ # change were NOT recently joined, in which case this
275+ # was a spontaneous mode change (perhaps a new operator
235276 # elevation) and I want to see it
236- $tstamp = $tjoined {$server -> {tag }, $target , $nick };
277+ $tstamp = $tjoined {$server -> {tag }, $target -> { name } , $nick };
237278 if (!$tstamp || $tstamp <= $jthreshold ) {
238279 return ;
239280 }
240281 }
241- }
282+ } }
242283
243284 # if I made it this far it means this text is to be suppressed
244285 Irssi::signal_stop();
0 commit comments