2005年08月22日 08:46 [Edit]

duplicateTBPingfilter

重複TBは簡単に防げるはずなのだが-(o)さんのコメント
MT用ならこういうの。
http://www.koikikukan.com/archives/2005/05/28-235959.php
MT3.2用にはもう少しスマートに書ける。

というわけで、MT Hackerでもない癖して小粋空間に行ってソースをとってきてみた。

それで気がついたのだけど、いちいちMT::TBPing->load_iterで過去TBを一つづつたぐってるのね。これは効率悪いよ。眞鍋かをりクラスのblogだと1000回以上イタることになる。これはMT側に適切なAPIがないことに原因があるのかな?

それにこれだと、重複を弾くだけで、出来れば重複した場合、新しいので上書きしたいよね。

まあblogに関して言えば私のようなをっさんはbloggerに徹して、blog hackerにはなりたくないのだけど、ちょっと気になった。

ついでなので、小粋空間の Yujiro Araki氏へのお礼もかねて、5分ほどかけてsourceをRefactorしてみた。手元でMTを動かしているわけではないので、-I/path/to/MT/lib -wcで構文checkしただけなのだけど、動くかな。コードは20行ほど短くなって、かつ見通しがよくなったと思う。コメントを除けば50 lines弱だし。

Dan the (Perl|Not MT) Hacker

# Movable Type plugin for filtering duplicate trackback ping.
#
# Release 1.02 (May 30, 2005)
#
# This software is provided as-is. You may use it for commercial or 
# personal use. If you distribute it, please keep this notice intact.
#
# Copyright (c) 2005 Yujiro Araki
#
# Refactored by Dan Kogai <dankogai@dan.co.jp> (Aug 22, 2005)
#
package MT::Plugin::DuplicateTBPingFilter;
use strict;
use MT::Trackback;
use MT::TBPing;
our $VERSION = 1.02;
our $NAME = __PACKAGE__ ; $NAME =~ s/.*:://o;

# Customize the following
our $title   = 1; # Use title for filtering when set
our $excerpt = 1; # Use excerpt for filtering when set
our $counter = 0; # the # of TBs to check
our $log     = 1; # 0: never 1:only duplicate 2:always
# end Customize

require MT::Plugin; # why not 'use MT::Plugin;' ?
my $plugin = MT::Plugin->new
    ({ name =>        "$NAME $VERSION",
       description => "Filters duplicate trackback ping to the same entry.",
     });
MT->add_plugin($plugin);
MT->add_callback('TBPingFilter', 11, 'duplicate trackback ping filter',
                 \&duplicate_tbping_filter);

sub same_url     { $_[0]->source_url eq $_[1]->source_url }
sub same_title   { !$title   || $_[0]->title eq $_[1]->title }
sub same_excerpt { !$excerpt || $_[0]->excerpt eq $_[1]->excerpt }
sub is_duplicate { same_url(@_) && same_title(@_) && same_excerpt(@_) }
sub duplicate_tbping_filter {
    my ($eh, $app, $ping) = @_;
    my $ping_iter = MT::TBPing->load_iter({tb_id=>$ping->tb_id}, 
                                          {'sort' => 'created_on', 
                                           direction => 'descend'});
    while (my $old_ping = $ping_iter->()) {
        next if $ping->id eq $old_ping->id;
        if (is_duplicate($ping, $old_ping)){
            $app->log("Filtered duplicate trackback ping from " 
                      . $ping->source_url) if $log;
            return 0;
        }
        next if !$counter;
        --$counter <= 0 and last;
    }
    $app->log("No duplicate found for" . $ping->source_url) if $log >= 2;
    return 1;
}

1;
__END__

この記事へのトラックバックURL

この記事へのコメント
livedoor Blogのいぢりかたもエントリってほしいなぁ。
Posted by SS at 2005年08月27日 21:18
MTではObjectを一個fetchするたびに呼ばれるコールバック用のhookがあり、このコールバックの副作用としては当然loadを中断するというものを含まれ得ます。したがってselectall_arrayrefとかするとセマンティクスが変わってしまうわけですね。そういうわけでこれ以上効率の良いやり方はないのです。
Posted by (o) at 2005年08月23日 13:07
こんばんは。
ご指導ありがとうございました!
Posted by yujiro at 2005年08月22日 23:16