Plagger::Plugin::Filter::POPFile

そーいやPOPFileってXMLRPC通信できるんだよなあと思い出したので作ってみた。SpamAssassinも悪くはないけど、こっちの方がウェブインタフェース用意されている分使いやすいかな。

ちなみにPOPFileにはWindowsインストーラもあるんですが、どうもこいつの設定がよろしくないらしく、POPFile直下のlibディレクトリにふだん使っているActivePerlのlibディレクトリから

lib/auto/List/Util/
lib/List/
lib/Scalar/

以下の内容をコピってやらないとXMLRPCが動作しませんでした。もちろん詳細設定でxmlrpc_enabledをtrueにしたときにはPOPFileを一度再起動しないといけないというのもお忘れなく。

package Plagger::Plugin::Filter::POPFile;
use strict;
use base qw( Plagger::Plugin );

our $VERSION = '0.01';

use XMLRPC::Lite;
use File::Temp ();
use File::Path ();
use Encode;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'plugin.init'        => \&connect_popfile,
        'update.entry.fixup' => \&filter,
        'update.fixup'       => \&disconnect_popfile,
    );
}

sub connect_popfile {
    my($self, $context, $args) = @_;

    $context->log(debug => "hello, POPFile");
    $self->{popfile} = XMLRPC::Lite->proxy($self->conf->{proxy});
    $self->{popfile_session} = $self->{popfile}->call(
        'POPFile/API.get_session_key',
        'admin',
        ''
    )->result;

    $context->log(debug => "session: $self->{popfile_session}");

    File::Path::mkpath($self->assets_dir) unless -d $self->assets_dir;

    $self->{popfile_tempdir} = File::Temp::tempdir(
        DIR => $self->assets_dir,
        CLEANUP => 1,
    );
}

sub disconnect_popfile {
    my($self, $context, $args) = @_;

    $context->log(debug => "good-bye, POPFile");
    $self->{popfile}->call(
         'POPFile/API.release_session_key',
         $self->{popfile_session}
    );
}

sub filter {
    my($self, $context, $args) = @_;

    my $tag      = $self->conf->{spam_tag}    || 'SPAM';
    my $bucket   = $self->conf->{spam_bucket} || 'spam';
    my $encoding = $self->conf->{encoding}    || 'utf8';
    my $entry    = $args->{entry};

    my ($fh, $filename) = File::Temp::tempfile(
        DIR => $self->{popfile_tempdir},
        UNLINK => 1,
    );

    print $fh
        'From: plagger@localhost (', $entry->permalink, ")\n",
        'To: plagger@localhost', "\n",
        'Subject: ', encode($encoding, $entry->title), "\n\n",
        encode($encoding, $entry->body),  "\n";
    close $fh;

    my $result = $self->{popfile}->call(
      'POPFile/API.classify',
      $self->{popfile_session},
      $filename
    )->result;

    $context->log(debug => "result: $result");

    if ($result eq $bucket) {
        $context->log(debug => "spam found");

        $entry->title("[$tag] " . $entry->title) if $self->conf->{add_tag_to_title};
        $entry->add_tag($tag);
    }
}

1;

__END__

=head1 NAME

Plagger::Plugin::Filter::POPFile - yet another spam filter

=head1 SYNOPSIS

  - module: Filter::POPFile
    config:
      proxy: http://localhost:8081/RPC2
      encoding: euc-jp
      spam_tag: SPAM
      spam_bucket: spam
      add_tag_to_title: 1

=head1 CONFIG

=over 4

=item proxy

Specifies your POPFile proxy URL.

=item encoding

Specifies your POPFile encoding. Specify 'euc-jp' for Nihongo users.

=item spam_tag

Specifies a tag string that will be added to entry's title or
tag (category)

=item spam_bucket

Specifies a bucket name that the spams are going in.

=item add_tag_to_title

If set to true, the tag (enclosed in brackets) will be added to spam
entry's title.

=back

=head1 AUTHOR

Kenichi Ishigaki

=head1 SEE ALSO

L<Plagger>, POPFile

=cut