Enhancements for wordfilter.pl\n\n o reload words on file modification\n o use a hash so word lookup is O(1)

This commit is contained in:
Robert Barretto 2025-04-28 17:04:33 -05:00
parent de1c3ea8f1
commit 5ae27a4e2c

View file

@ -1,9 +1,11 @@
use POSIX qw(strftime); use POSIX qw(strftime);
use File::stat;
my $filename; my $filename;
my @words; my $last_mtime;
my $read_date; my %words_lookup;
my $debug; my $debug;
my $logfile; my $logfile;
@ -12,34 +14,44 @@ sub dolog {
return unless $debug; return unless $debug;
my $ts = strftime("%Y-%m-%d %H:%M:%S", localtime); my $ts = strftime("%Y-%m-%d %H:%M:%S", localtime);
open(OUT, ">>$logfile"); open(OUT, ">>$logfile");
print OUT "$ts $str"; print OUT "$ts $str\n";
close(OUT); close(OUT);
} }
sub refresh_words { sub refresh_words {
my @now = localtime(); my ($id) = @_;
my $year = $now[5];
my $mon = $now[4]; my $stat = stat($filename);
my $mday = $now[3]; # If the filtered words files doesn't exist, nothing to do
my $dayno = 0 + ($year + 1900) * 10000 + $mon * 100 + $mday; return unless $state;
return unless ($dayno > $read_date);
@words = (); # If the filtered words file hasn't been modified, nothing to do
$last_mtime ||= 0;
return unless ($stat->mtime > $last_mtime);
# The filtered words file has changed. Create a new lookup hash
%words_lookup = ();
if (open(my $fh, '<', $filename)) { if (open(my $fh, '<', $filename)) {
while (my $row = <$fh>) { while (my $row = <$fh>) {
chomp($row); chomp($row);
next if length($row) < 1; next if length($row) < 1;
push @words, lc($row); push @words, lc($row);
} }
dolog("load from " . $filename . ", found " . @words . " words\n"); dolog("[$id] - '" . $filename . "' modified. Loaded " . scalar(@words) . " words.");
close($fh); close($fh);
} }
$read_date = $dayno;
# Create new hash for O(1) lookups
%words_lookup = map { $_ => 1 } @words;
# update last modified time
$last_mtime = $stat->mtime;
} }
sub create_config { sub create_config {
my ($name, $configdata) = @_; my ($name, $configdata) = @_;
$filename = $configdata; $filename = $configdata;
$read_date = 0; $last_mtime = 0;
$debug = 1; $debug = 1;
$logfile = "/tmp/wordfilter.log"; $logfile = "/tmp/wordfilter.log";
} }
@ -47,10 +59,12 @@ sub create_config {
sub check { sub check {
my ($id, $msg) = @_; my ($id, $msg) = @_;
refresh_words; refresh_words($id);
foreach my $word (@words) { my @msg_words = split /\s+/, $msg;
next unless ($msg =~ /\b${word}\b/); # check each word in the message to see if has any filter words
dolog("reject message " . $id . " containing `" . $word . "' in message: `" . $msg . "'\n"); foreach my $msg_word (@msg_words) {
next unless (exists $words_lookup{lc($msg_word)});
dolog("[$id] - rejecting message containing '" . $msg_word . "' in message: '" . $msg . "'");
return 8; return 8;
} }
return 0; return 0;