Merge branch 'adaptive-filter'
[softsnow_xchat2_filter.git] / SoftSnow_filter.pl
blobc1e694c40ff38295df7271ddaf996b9c42ca6683
1 #!/usr/bin/perl
3 # SoftSnow XChat2 filter script
5 ## Summary:
6 ##
7 # Filter out fileserver announcements and SPAM on IRC
9 ## Description:
11 # This script started as an upgrade to the SoftSnow filter script
12 # from http://dukelupus.pri.ee/softsnow/ircscripts/scripts.shtml
13 # or http://softsnow.griffin3.com/ircscripts/scripts.shtml
14 # (originally http://www.softsnow.biz/softsnow_filter/filter.shtml)
15 # It borrows some ideas from filter-ebooks (#ebooks Xchat2 filter
16 # script) by KiBo, and its older version by RJVJR, mainly moving
17 # from the old IRC:: interface to the new Xchat2 API.
19 # Tested on #ebooks channel on IRCHighWay (irc.irchighway.net)
21 # Use '/FILTER HELP' (or '/HELP FILTER') to list all commands.
22 # By default filter is turned off: use '/FILTER ON' to start
23 # filtering contents, use '/FILTERWINDOW ON' to log filtered
24 # lines to '(filtered)' window.
27 ## Install:
29 # Place SoftSnow_filter.pl in your ~/.xchat directory
31 ## URL (repositories):
32 # * http://github.com/jnareb/softsnow-xchat2-filter
33 # * http://gitorious.org/projects/softsnow-xchat2-filter
34 # * http://repo.or.cz/w/softsnow_xchat2_filter.git
36 ## ChangeLog (main points only):
38 # Version 1.2:
39 # * Original version of SoftSnow filter this one is based on
40 # Version 1.2.2:
41 # * Add /FILTER command, to turn filter off and on, and to limit
42 # filtering to current IRC server only
43 # Version 1.2.3:
44 # * Allow to save and load filter rules from file (UNIX only)
45 # * Add ALLOW rules, for example to show '@search' while filtering '@'
46 # Version 2.0.1:
47 # * Use new XChat2 API (Xchat:: instead of IRC::)
48 # Version 2.0.5:
49 # * More secure saving rules to a file (always save whole file)
50 # Version 2.1.0:
51 # * Allow printing (logging) filtered content to '(filtered)' window
52 # via 'Channel Message' text event, with nick of sender
53 # Version 2.1.3:
54 # * /FILTERWINDOW command to control and query of logging filtered
55 # contents to separate '(filtered)' window
57 ## TODO:
59 # * Add GUI and MENU (would require XChat >= 2.4.5)
60 # * Change format of saved rules to 'm/.../' or 'qr{...}';
61 # see YAML (YAML::Types) and Data::Dumper code and output
62 # * Save and read config together with filter rules
63 # * Autosave (and autoread) configuration, if turned on
64 # * Read default config and rules from __DATA__, add reset
65 # * Save filter rules usage statistics
66 # * Import filter rules from filter-ebooks3.3FINAL script
67 # * Limit filter to specified channels (or all channels)
68 # * Filter private SPAM (SPAM sent to you, but not other)
69 # * ? Don't accept DCC from users not on common channel
70 # * ? Do not accept files, or dangerous files, from regular users
71 # * Color nicks in '(filtered)' window according to matched rule
72 # * Add command to clear '(filtered)' window
73 # * Add option to strip codes from logged filtered lines
74 # * Limit number of lines in '(filtered)' window
75 # * ? Perhaps something about '@find' and '!find' results?
76 # * Triggers, for example automatic /dccallow + resubmit,
77 # if request fails (due to double '.' in filename, etc.)
79 use strict;
80 use warnings;
82 use File::Temp qw(tempfile);
83 use File::Copy qw(move);
86 my $scriptName = "SoftSnow XChat2 Filter";
87 my $scriptVersion = "2.2.1";
88 my $scriptDescr = "Filter out file server announcements and IRC SPAM";
90 my $B = chr 2; # bold
91 my $U = chr 31; # underline
92 my $C = chr 3; # start of color sequence
93 my $R = chr 22; # reverse
94 my $O = chr 15; # reset
96 ### config ###
97 my $filter_file = Xchat::get_info("xchatdir") . "/SoftSnow_filter.conf";
99 my $filter_turned_on = 0; # is filter is turned on
100 my $limit_to_server = ''; # if true limit to given server (host)
101 my $use_filter_allow = 0; # use overrides (ALLOW before DENY)
103 my $filtered_to_window = 0;
104 my $filter_window = "(filtered)";
105 ### end config ###
107 my $filter_commands = 'ON|OFF|STATUS|SERVER|SERVERON|ALL|HELP|DEBUG|CLEARSTATS|SORT|PRINT|ALLOW|ADD|DELETE|SAVE|LOAD';
109 my $filter_help = <<"EOF";
110 ${B}/FILTER $filter_commands${B}
111 /FILTER ON|OFF - turns filtering on/off
112 /FILTER HELP - prints this help message
113 /FILTER STATUS - prints if filter is turned on, and with what limits
114 /FILTER DEBUG - shows some info; used in debuggin the filter
115 /FILTER CLEARSTATS - reset filter statistics
116 /FILTER SORT - sort deny rules to have more often matched rules first
117 /FILTER PRINT - prints all the rules
118 /FILTER ALLOW - toggle use of ALLOW rules (before DENY).
119 /FILTER SERVER - limits filtering to current server (host)
120 /FILTER SERVERON - limits to server and turns filter on
121 /FILTER ALL - resumes filtering everywhere i.e. removes limits
122 /FILTER SAVE - saves the rules to the file $filter_file
123 /FILTER LOAD - loads the rules from the file, replacing existing rules
124 /FILTER ADD <rule> - add rule at the end of the DENY rules
125 /FILTER DELETE [<num>] - delete rule number <num>, or last rule
126 /FILTER SHOW [<num>] - show rule number <num>, or last rule
127 /FILTER VERSION - prints the name and version of this script
128 /FILTER WINDOW <arg>... - same as /FILTERWINDOW <arg>...
129 /FILTER without parameter is equivalent to /FILTER STATUS
132 my $filterwindow_commands = 'ON|OFF|CLOSE|HELP|STATUS|DEBUG';
134 my $filterwindow_help = <<"EOF";
135 ${B}/FILTERWINDOW $filterwindow_commands${B}
136 /FILTERWINDOW ON|OFF - turns saving filtered content to ${U}$filter_window${U}
137 /FILTERWINDOW CLOSE - close ${U}$filter_window${U} (and turn off logging)
138 /FILTERWINDOW STATUS - prints if saving to ${U}$filter_window${U} is turned on
139 /FILTERWINDOW HELP - prints this help message
140 /FILTERWINDOW DEBUG - shows some info; used in debugging this part of filter
141 /FILTERWINDOW without parameter is equivalent to /FILTERWINDOW STATUS
144 Xchat::register($scriptName, $scriptVersion, $scriptDescr);
146 Xchat::hook_command("FILTER", \&filter_command_handler,
147 { help_text => $filter_help });
148 Xchat::hook_command("FILTERWINDOW", \&filterwindow_command_handler,
149 { help_text => $filterwindow_help });
150 Xchat::hook_server("PRIVMSG", \&privmsg_handler);
152 Xchat::print("Loading ${B}$scriptName $scriptVersion${B}...\n");
155 # GUI, windows, etc.
156 if ($filtered_to_window) {
157 Xchat::command("QUERY $filter_window");
160 # information about (default) options used
161 if ($filter_turned_on) {
162 Xchat::print("Filter turned ${B}ON${B}\n");
163 } else {
164 Xchat::print("Filter turned ${B}OFF${B}\n");
166 if ($limit_to_server) {
167 Xchat::print("Filter limited to server $limit_to_server\n")
169 if ($use_filter_allow) {
170 Xchat::print("Filter uses ALLOW rules\n");
173 # ------------------------------------------------------------
175 my @filter_allow = (
176 q/^\@search\s/,
179 my @filter_deny = (
180 q/\@/,
181 q/^\s*\!/,
182 q/slot\(s\)/,
183 #q/~&~&~/,
185 #xdcc
186 q/^\#\d+/,
188 #fserves
189 q/(?i)fserve.*trigger/,
190 q/(?i)trigger.*\!/,
191 q/(?i)trigger.*\/ctcp/,
192 q/(?i)type\:\s*\!/,
193 q/(?i)file server online/,
195 #ftps
196 q/(?i)ftp.*l\/p/,
198 #CTCPs
199 q/SLOTS/,
200 q/MP3 /,
202 #messages for when a file is received/failed to receive
203 q/(?i)DEFINITELY had the right stuff to get/,
204 q/(?i)has just received/,
205 q/(?i)I have just received/,
207 #mp3 play messages
208 q/is listening to/,
209 q/\]\-MP3INFO\-\[/,
211 #spammy scripts
212 q/\]\-SpR\-\[/,
213 q/We are BORG/,
215 #general messages
216 q/brave soldier in the war/,
219 my $nlines = 0; # how many lines we passed through filter
220 my $nfiltered = 0; # how many lines were filtered
221 my $checklensum = 0; # how many rules to check to catch filtered
222 my $nallow = 0; # how many lines matched ALLOW rule
223 my %stats = (); # histogram: how many times given rule was used
225 # return 1 (true) if text given as argument is to be filtered out
226 sub isFiltered {
227 my $text = shift;
228 my $regexp = '';
230 #strip colour, underline, bold codes, etc.
231 $text = Xchat::strip_code($text);
233 # count all filtered lines;
234 $nlines++;
236 if ($use_filter_allow) {
237 foreach $regexp (@filter_allow) {
238 if ($text =~ /$regexp/) {
239 $nallow++;
240 return 0;
245 my $nrules_checked = 0;
246 foreach $regexp (@filter_deny) {
247 $nrules_checked++;
249 if ($text =~ /$regexp/) {
250 # filter statistic
251 $nfiltered++;
252 $checklensum += $nrules_checked;
253 if (exists $stats{$regexp}) {
254 $stats{$regexp}++;
255 } else {
256 $stats{$regexp} = 1;
259 return 1;
263 return 0;
266 #called when someone says something in the channel
267 #1: address of speaker
268 #2: PRIVMSG constant
269 #3: channel
270 #4: text said (prefixed with :)
271 sub privmsg_handler {
272 # $_[0] - array reference containing the IRC message or command
273 # and arguments broken into words
274 # $_[1] - array reference containing the Nth word to the last word
275 my ($address, $msgtype, $channel) = @{$_[0]};
276 my ($nick, $user, $host) = ($address =~ /^:([^!]*)!([^@]+)@(.*)$/);
278 my $text = $_[1][3]; # Get server message
280 my $server = Xchat::get_info("host");
282 #-- EXAMPLE RAW COMMANDS: --
283 #chanmsg: [':epitaph!~epitaph@CPE00a0241892b7-CM014480119187.cpe.net.cable.rogers.com', 'PRIVMSG', '#werd', ':mah', 'script', 'is', 'doing', 'stuff.']
284 #action: [':rlz!railz@bzq-199-176.red.bezeqint.net', 'PRIVMSG', '#werd', ':\x01ACTION', 'hugs', 'elhaym', '\x01']
285 #private: [':olene!oqd@girli.sh', 'PRIVMSG', 'epinoodle', ':hey']
288 return Xchat::EAT_NONE unless $filter_turned_on;
289 if ($limit_to_server) {
290 return Xchat::EAT_NONE unless $server eq $limit_to_server;
292 # do not filter out private messages
293 return Xchat::EAT_NONE unless ($channel =~ /^#/);
295 $text =~ s/^://;
297 if (isFiltered($text)) {
298 if (defined $nick && $filtered_to_window) {
299 #Xchat::print($text, $filter_window)
301 my $ctx = Xchat::get_context();
302 Xchat::set_context($filter_window);
303 Xchat::emit_print('Channel Message', $nick, $text);
304 Xchat::set_context($ctx);
306 #return Xchat::EAT_XCHAT;
307 return Xchat::EAT_ALL;
309 return Xchat::EAT_NONE;
313 # ------------------------------------------------------------
315 sub save_filter {
316 my ($fh, $tmpfile) = tempfile($filter_file.'.XXXXXX', UNLINK=>1);
318 unless ($fh) {
319 Xchat::print("${B}FILTER:${B} ".
320 "Couldn't open temporary file $tmpfile to save filter: $!\n");
321 return;
324 Xchat::print("${B}FILTER SAVE >$filter_file${B}\n");
325 foreach my $regexp (@filter_deny) {
326 Xchat::print("/".$regexp."/ saved\n");
327 print $fh $regexp."\n";
330 unless (close $fh) {
331 Xchat::print("${B}FILTER:${B} Couldn't close file to save filter: $!\n");
332 return;
334 #move($tmpfile, $filter_file);
335 rename($tmpfile, $filter_file);
336 Xchat::print("${B}FILTER SAVED ----------${B}\n");
338 return 1;
341 sub load_filter {
342 my $fh;
344 Xchat::print("${B}FILTER:${B} ...loading filter patterns\n");
345 unless (open $fh, '<', $filter_file) {
346 Xchat::print("${B}FILTER:${B} Couldn't open file to load filter: $!\n");
347 return;
350 @filter_deny = <$fh>;
351 map (chomp, @filter_deny);
353 unless (close $fh) {
354 Xchat::print("${B}FILTER:${B} Couldn't close file to load filter: $!\n");
355 return;
358 Xchat::print("${B}FILTER DENY START ----------${B}\n");
359 for (my $i = 0; $i <= $#filter_deny; $i++) {
360 Xchat::print(" [$i]: /".$filter_deny[$i]."/\n");
362 Xchat::print("${B}FILTER DENY END ------------${B}\n");
365 sub add_rule ( $ ) {
366 my $rule = shift;
368 # always ading rules at the end
369 push @filter_deny, $rule;
372 sub delete_rule ( $ ) {
373 my $num = shift || $#filter_deny;
375 splice @filter_deny, $num, 1;
378 sub slquote {
379 my $text = shift;
381 $text =~ s!([\/])!\$1!g;
383 return $text;
386 # ============================================================
387 # ------------------------------------------------------------
388 # ............................................................
390 sub cmd_version {
391 Xchat::print("${B}$scriptName $scriptVersion${B}\n");
392 Xchat::print(" * URL: http://github.com/jnareb/softsnow-xchat2-filter\n");
393 Xchat::print(" * URL: http://gitorious.org/projects/softsnow-xchat2-filter\n");
394 Xchat::print(" * URL: http://repo.or.cz/w/softsnow_xchat2_filter.git\n");
397 sub cmd_status {
398 my $server = shift;
400 if ($filter_turned_on) {
401 Xchat::print("Filter is turned ${B}ON${B}\n");
402 } else {
403 Xchat::print("Filter is turned ${B}OFF${B}\n");
405 if ($limit_to_server) {
406 if ($server eq $limit_to_server) {
407 Xchat::print("Filter is limited to ${B}current${B} ".
408 "server $limit_to_server\n");
409 } else {
410 Xchat::print("Filter is limited to server ".
411 "$limit_to_server != $server\n");
414 if ($use_filter_allow) {
415 Xchat::print("Filter is using ALLOW rules (before DENY)\n");
419 sub cmd_debug {
420 Xchat::print("${B}FILTER DEBUG START ----------${B}\n");
421 Xchat::print("Channel: ".Xchat::get_info("channel")."\n");
422 Xchat::print("Host: ".Xchat::get_info("host")."\n");
423 Xchat::print("Server: ".Xchat::get_info("server")."\n");
424 Xchat::print("Server Id: ".Xchat::get_info("id")."\n");
425 Xchat::print("Network: ".Xchat::get_info("network")."\n");
427 Xchat::print("\n");
428 Xchat::printf("%3u %s rules\n", scalar(@filter_allow), "allow");
429 Xchat::printf("%3u %s rules\n", scalar(@filter_deny), "deny");
431 my %deny_idx = ();
432 # %deny_idx = map { $filter_deny[$_] => $_ } 0..$#filter_deny;
433 @deny_idx{ @filter_deny } = (0..$#filter_deny);
434 Xchat::print("\n");
435 Xchat::print("filtered lines = $nfiltered out of $nlines\n");
436 if ($nlines > 0) {
437 Xchat::printf("filtered ratio = %f (%5.1f%%)\n",
438 $nfiltered/$nlines, 100.0*$nfiltered/$nlines);
440 if ($nfiltered > 0) {
441 Xchat::print("average to match = ".$checklensum/$nfiltered."\n");
442 foreach my $rule (sort { $stats{$b} <=> $stats{$a} } keys %stats) {
443 Xchat::printf("%5u: %5.1f%% [%2u] /%s/\n",
444 $stats{$rule}, 100.0*$stats{$rule}/$nfiltered,
445 $deny_idx{$rule}, slquote($rule));
448 if ($use_filter_allow || $nallow > 0) {
449 Xchat::print("allow matches = $nallow\n");
451 Xchat::print("${B}FILTER DEBUG END ------------${B}\n");
454 sub cmd_clear_stats {
455 $nlines = 0;
456 $nfiltered = 0;
457 $checklensum = 0;
458 $nallow = 0;
459 %stats = ();
461 Xchat::print("${B}FILTER:${B} stats cleared\n");
464 sub cmd_sort_by_stats {
465 use sort 'stable';
467 @filter_deny =
468 sort { ($stats{$b} || 0) <=> ($stats{$a} || 0) }
469 @filter_deny;
471 Xchat::print("${B}FILTER:${B} DENY rules sorted by their use descending\n");
474 sub cmd_server_limit {
475 my $server = shift;
477 if ($server) {
478 # adding limiting to given (single) server
479 if ($limit_to_server) {
480 Xchat::print("${B}FILTER:${B} Changing server from $limit_to_server to $server\n");
481 Xchat::print("[FILTER LIMITED TO SERVER ${B}$server${B} (WAS TO $limit_to_server)]",
482 $filter_window);
483 } else {
484 Xchat::print("${B}FILTER:${B} Limiting filtering to server $server\n");
485 Xchat::print("[FILTER LIMITED TO SERVER ${B}$server${B} (WAS UNLIMITED)]",
486 $filter_window);
488 $limit_to_server = $server;
490 } else {
491 # removing limiting to server
492 if ($limit_to_server) {
493 Xchat::print("${B}FILTER:${B} Removing limit to server $limit_to_server\n");
494 Xchat::print("[FILTER ${B}NOT LIMITED${B} TO SERVER (WAS TO $limit_to_server)]",
495 $filter_window);
497 $limit_to_server = '';
502 sub cmd_print_rules {
503 Xchat::print("${B}FILTER PRINT START ----------${B}\n");
504 Xchat::print("${B}ALLOW${B}".($use_filter_allow ? ' (on)' : ' (off)')."\n");
506 for (my $i = 0; $i <= $#filter_allow; $i++) {
507 Xchat::print("[$i]: /".$filter_allow[$i]."/\n");
509 Xchat::print("${B}DENY${B}\n");
510 for (my $i = 0; $i <= $#filter_deny; $i++) {
511 Xchat::print("[$i]: /".$filter_deny[$i]."/\n");
513 Xchat::print("${B}FILTER PRINT END ------------${B}\n");
516 sub cmd_add_rule {
517 my $rule = shift;
519 if ($rule) {
520 add_rule($rule);
521 Xchat::print("${B}FILTER RULE [$#filter_deny]:${B} /$rule/\n");
522 } else {
523 Xchat::print("Syntax: ${B}/FILTER ADD ${U}rule${U}${B} to add\n")
527 sub cmd_delete_rule {
528 my $num = shift;
530 # strip whitespace
531 $num =~ s/^\s*(.*?)\s*$/$1/g if $num;
532 SWITCH: {
533 unless ($num) {
534 Xchat::print("${B}FILTER:${B} deleting /".$filter_deny[-1]."/\n");
535 $#filter_deny--;
536 Xchat::print("${B}FILTER:${B} deleted successfully last rule\n");
537 last SWITCH;
539 if ($num !~ /^\d+$/) {
540 Xchat::print("${B}FILTER:${B} $num is not a number\n");
541 last SWITCH;
543 if ($num < 0 || $num > $#filter_deny) {
544 Xchat::print("${B}FILTER:${B} $num outside range [0,$#filter_deny]\n");
545 last SWITCH;
547 # default
549 Xchat::print("${B}FILTER:${B} deleting /".$filter_deny[$num]."/\n");
550 delete_rule($num);
551 Xchat::print("${B}FILTER:${B} deleted successfully rule $num\n");
556 sub cmd_show_rule {
557 my $num = shift;
559 $num =~ s/^\s*(.*?)\s*$/$1/g if $num;
561 if (defined $num && $num !~ /^\d+$/) {
562 Xchat::print("${B}FILTER:${B} $num is not a number\n");
563 } elsif (defined $num && !defined $filter_deny[$num]) {
564 Xchat::print("${B}FILTER:${B} rule $num does not exist\n");
565 } else {
566 Xchat::print("${B}FILTER:${B} ".(defined $num ? "[$num]" : "last").
567 " rule /".$filter_deny[defined $num ? $num : -1]."/\n");
571 # ============================================================
572 # ============================================================
573 # ============================================================
575 sub filter_command_handler {
576 my $cmd = $_[0][1]; # 1st parameter (after FILTER)
577 my $arg = $_[1][2]; # 2nd word to the last word
578 my $server = Xchat::get_info("host");
581 if (!$cmd || $cmd =~ /^STATUS$/i) {
582 cmd_status($server);
584 } elsif ($cmd =~ /^ON$/i) {
585 $filter_turned_on = 1;
586 Xchat::print("Filter turned ${B}ON${B}\n");
587 Xchat::print("[FILTER TURNED ${B}ON${B}]",
588 $filter_window);
590 } elsif ($cmd =~ /^OFF$/i) {
591 $filter_turned_on = 0;
592 Xchat::print("Filter turned ${B}OFF${B}\n");
593 Xchat::print("[FILTER TURNED ${B}OFF${B}]",
594 $filter_window);
596 } elsif ($cmd =~ /^SERVER$/i) {
597 cmd_server_limit($server);
599 } elsif ($cmd =~ /^SERVERON$/i) {
600 cmd_server_limit($server);
602 Xchat::print("[FILTER TURNED ${B}ON${B}]",
603 $filter_window)
604 if (!$filter_turned_on);
605 $filter_turned_on = 1;
606 Xchat::print("Filter turned ${B}ON${B}\n");
608 } elsif ($cmd =~ /^ALL$/i) {
609 cmd_server_limit(undef);
611 } elsif ($cmd =~ /^HELP$/i) {
612 Xchat::print($filter_help);
613 Xchat::print($filterwindow_help);
615 } elsif ($cmd =~ /^VERSION$/i) {
616 cmd_version();
618 } elsif ($cmd =~ /^DEBUG$/i || $cmd =~ /^INFO$/i) {
619 cmd_debug();
621 } elsif ($cmd =~ /^CLEARSTAT(?:S)?$/i) {
622 cmd_clear_stats();
624 } elsif ($cmd =~ /^SORT$/i) {
625 cmd_sort_by_stats();
627 } elsif ($cmd =~ /^(?:PRINT|LIST)$/i) {
628 cmd_print_rules();
630 } elsif ($cmd =~ /^ALLOW$/i) {
631 $use_filter_allow = !$use_filter_allow;
632 Xchat::print("${B}FILTER:${B} ALLOW rules ".
633 ($use_filter_allow ? "enabled" : "disabled")."\n");
635 } elsif ($cmd =~ /^ADD$/i) {
636 cmd_add_rule($arg);
638 } elsif ($cmd =~ /^DEL(?:ETE)$/i) {
639 cmd_delete_rule($arg);
641 } elsif ($cmd =~ /^SHOW$/i) {
642 cmd_show_rule($arg);
644 } elsif ($cmd =~ /^SAVE$/i) {
645 save_filter();
646 Xchat::print("${B}FILTER:${B} saved DENY rules to $filter_file\n");
648 } elsif ($cmd =~ /^(RE)?LOAD$/i) {
649 load_filter();
650 Xchat::print("${B}FILTER:${B} loaded DENY rules from $filter_file\n");
652 } elsif ($cmd =~ /^WINDOW$/i) {
653 return filterwindow_command_handler(
654 [ 'FILTERWINDOW', @{$_[0]}[2..$#{$_[0]}] ],
655 [ "FILTERWINDOW $_[1][2]", @{$_[1]}[2..$#{$_[1]}] ],
656 $_[2]
659 } else {
660 Xchat::print("Unknown command ${B}/FILTER $_[1][1]${B}\n") if $cmd;
662 return 1;
665 sub filterwindow_command_handler {
666 my $cmd = $_[0][1]; # 1st parameter (after FILTER)
667 #my $arg = $_[1][2]; # 2nd word to the last word
668 my $ctx = Xchat::find_context($filter_window);
670 if (!$cmd || $cmd =~ /^STATUS$/i) {
671 Xchat::print(($filtered_to_window ? "Show" : "Don't show").
672 " filtered content in ".
673 (defined $ctx ? "open" : "closed").
674 " window ${B}$filter_window${B}\n");
676 } elsif ($cmd =~ /^DEBUG$/i) {
677 my $ctx_info = Xchat::context_info($ctx);
678 Xchat::print("${B}FILTERWINDOW DEBUG START ----------${B}\n");
679 Xchat::print("filtered_to_window = $filtered_to_window\n");
680 Xchat::print("filter_window = $filter_window\n");
681 if (defined $ctx) {
682 Xchat::print("$filter_window is ${B}open${B}\n");
683 Xchat::print("$filter_window: network => $ctx_info->{network}\n")
684 if defined $ctx_info->{'network'};
685 Xchat::print("$filter_window: host => $ctx_info->{host}\n")
686 if defined $ctx_info->{'host'};
687 Xchat::print("$filter_window: channel => $ctx_info->{channel}\n");
688 Xchat::print("$filter_window: server_id => $ctx_info->{id}\n")
689 if defined $ctx_info->{'id'};
690 } else {
691 Xchat::print("$filter_window is ${B}closed${B}\n");
693 # requires XChat >= 2.8.2
694 #Xchat::print("'Channel Message' format: ".
695 # Xchat::get_info("event_text Channel Message")."\n");
696 #Xchat::print("'Channel Msg Hilight' format: ".
697 # Xchat::get_info("event_text Channel Msg Hilight")."\n");
698 Xchat::print("${B}FILTERWINDOW DEBUG END ------------${B}\n");
700 } elsif ($cmd =~ /^ON$/i) {
701 Xchat::command("QUERY $filter_window");
702 Xchat::print("${B}----- START LOGGING FILTERED CONTENTS -----${B}\n",
703 $filter_window)
704 if !$filtered_to_window;
706 $filtered_to_window = 1;
707 Xchat::print("Filter shows filtered content in ${B}$filter_window${B}\n");
709 } elsif ($cmd =~ /^(?:OFF|CLOSE)$/i) {
710 Xchat::print("${B}----- STOP LOGGING FILTERED CONTENTS ------${B}\n",
711 $filter_window)
712 if $filtered_to_window;
713 Xchat::command("CLOSE", $filter_window)
714 if ($cmd =~ /^CLOSE$/i);
716 $filtered_to_window = 0;
717 Xchat::print("Filter doesn't show filtered content in ${B}$filter_window${B}\n");
718 Xchat::print("${B}FILTER:${B} ${B}$filter_window${B} closed\n")
719 if ($cmd =~ /^CLOSE$/i);
721 } elsif ($cmd =~ /^HELP$/i) {
722 Xchat::print($filterwindow_help);
724 } else {
725 Xchat::print("Unknown command ${B}/FILTERWINDOW $_[1][1]${B}\n") if $cmd;
726 Xchat::print("${B}${U}USAGE:${U} /FILTERWINDOW $filterwindow_commands${B}\n");
729 return 1;
732 # ======================================================================
733 # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
734 # ----------------------------------------------------------------------
736 Xchat::print("${B}$scriptName $scriptVersion${B} loaded\n",
737 " For help: ${B}/FILTER HELP${B}\n");