このブログでは、はてなブックマークの情報を1日1回エントリにしてアップしているんですが、
MovableTypeを3.3に上げて純正のタグエリアを使用するようになって、
アップ用プログラムのちょっとした不備が表面化しました。

というのも、アップ時に利用しているNet::MovableTypeモジュールにはタグ登録用の手段がなく、
そのままだと、自動的に作成されたエントリにタグを付けることが出来ないからです。
(CPANの最新版のドキュメント読んでも用意されてないから…ないんだと思う)


解決策として取り得る方法としては例えば以下の3つが考えられるでしょう。

  1. Net::MovableTypeを独自に拡張する
  2. アップ用プログラムを拡張してタグを登録→再構築する
  3. タグ登録→再構築プログラムを別途用意して運用する

1番目はさすがに…自信がないです。
MovableType側の仕様は固まっているわけなので、注意深くテストを行った上で実装すれば、
僕でも出来なくはないと思いますがすぐというわけには。

現実的かつ一番やりたかったのは2番目なのですが、
そのテスト的な意味合いも含めて、3番目のプログラムを作成してみました。



追記。

Ogawaさんから、それKeywordsAsTags_Pluginで出来るよ、と情報をいただきました。
あああ!それってそうやって使うんですね!
失念っていうレベルじゃねーな;
ありがとうございます!

…というわけで、試した上で別エントリアップする予定です。
参考にしたコードは、以下の2つです。


Ogawaさんのmt-keywords2tagsは、
大量のエントリをコンバートする目的で作られているので、再構築は行いません。

今回は、それほど多くのエントリを処理する必要はなく(基本的には1つ)、
再構築をしても問題ない、むしろした方がよい、ということで、
mt-keywords2tagsをベースにタグを追加後に再構築して回す…
…というような感じでマッシュアップ。

本当のことを言えば、複数のエントリを処理することも考慮して、
タグ追加フェーズとリビルドフェーズは分けておいた方が良いのかも知れませんが、
とりあえず一緒に処理してみます。


できあがったコードは以下。

#!/usr/bin/perl -w
#
# arranged by is / for Tagging->NewEntry
#
# ** Original Copyrights ***********************************************
# $Id: mt-keywords2tags.cgi 217 2006-06-05 08:46:56Z ogawa $           *
# A simple tool for converting entries' keywords into tags for MT 3.3+ *
#                                                                      *
# 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) 2006 Hirotaka Ogawa                                    *
# **********************************************************************
#
use strict;
sub BEGIN {
    my $dir;
    require File::Spec;
    if (!($dir = $ENV{MT_HOME})) {
        if ($0 =~ m!(.*[/\\])!) {
            $dir = $1;
        } else {
            $dir = './';
        }
        $ENV{MT_HOME} = $dir;
    }
    unshift @INC, File::Spec->catdir($dir, 'lib');
    unshift @INC, File::Spec->catdir($dir, 'extlib');
}

use MT;
use MT::Entry;

my $mt = MT->new or die MT->errstr;
my $iter = MT::Entry->load_iter;

while (my $e = $iter->()) {
    next unless $e->keywords;
    next unless $e->title =~ m/^Hatena\:\:Bookmark\:\:konaze/;
    next if $e->tags;
    my @tags = split_tags($e->keywords, 1);
    next unless scalar @tags;
    $e->set_tags(@tags);
    $e->save_tags;
    $mt->rebuild_entry( Entry => $e );
#    last;
#    print $e->id . ": " . join(', ', @tags) . "\n";
}

sub split_tags {
    my ($string, $case_sensitive) = @_;
    return unless $string;
    my @tags;
    $string =~ s/\#.*$//g;
    $string =~ s/(^\s+|\s+$)//g;
    $string = lc $string unless $case_sensitive;
#    $string =~ s/\[[^[]+\]//g; # uncomment this to discard [short title]

    if ($string =~ m/[;,|]/) {
	# tags separated by non-whitespaces
	while ($string =~ m/(\[[^]]+\]|"[^"]+"|'[^']+'|[^;,|]+)/g) {
	    my $tag = $1;
	    $tag =~ s/(^[\["'\s;,|]+|[\]"'\s;,|]+$)//g;
	    push @tags, $tag if $tag;
	}
    } else {
	# tags separated by whitespaces
	while ($string =~ m/(\[[^]]+\]|"[^"]+"|'[^']+'|[^\s]+)/g) {
	    my $tag = $1;
	    $tag =~ s/(^[\["'\s]+|[\]"'\s]+$)//g;
	    push @tags, $tag if $tag;
	}
    }
    @tags;
}


応急的なコードを常用に転用しようとしてるところで無理がある気がしないでもないですが、
シェルから起動して処理した感じでは、何とかなりそうな感じ。
(すみません、体感だけでベンチ取ってません)


これをはてなブックマーク投稿用プログラムの事項から十分な時間を取って、
cronで回せば、とりあえず表題の件についての解決策を1つ手に入れたことになります…が。
やっぱどう考えても、プログラムに組み込むべきだよなぁ。
実行タイミングとか、処理数とか考えても。

無理矢理組み込めば出来るんですが、
何とか美しくできないか…引き続き検討中です。