Atom API って便利ね

  • 投稿日:
  • by
  • カテゴリ:

mixi 日記が空っぽなのはさみしいけどこっちの blog エントリをコピペで投稿するのはめんどくさい、という必要に駆られて自作した MT 用の mixi 日記投稿プラグイン。

しばらく blog もさぼってたのでいつからかはわかりませんが、プラグイン経由で投稿した mixi 日記が豪快に文字化けするようになってしまってました。
ちょっと前までは問題なく使えていたので mixi 側の仕様が変わったんだと思いますが、詳しく調べてないので原因は謎。

これまでは WWW::Mechanize で Web ブラウザ同様に mixi にログインして投稿フォームから送信、というわりとめんどい手順を踏んでたんですが、OpenID にも対応しているきょうび REST 使えないとかありえないよねー、と調べてみたら非公式ながら API があることが判明。
それ使ったらこれまでよりずっと簡単に mixi 日記が投稿できるようになりました。

ざっと調べて見つけた Web サイトでは LWP::UserAgent で直に API 叩いてましたが、せっかく CPAN Module があるんだからそっちを使う感じに。といってもたいしたことはしてません、XML::Atom でちょろちょろっと書いただけです。

参考にしたサイトは次のような感じ。

たけまる / mixi station API
http://teahut.sakura.ne.jp/b/2007-07-01-1.html
mixi for iPhoneから発掘されたmixi日記投稿用API « ku
http://ido.nu/kuma/2008/07/30/digging-mixi-for-iphone-application-and-new-api-for-posting-a-diary-with-a-photo/

いくら非公開とはいえネット使う API は簡単に解析されるわねぇ。

なんとなくプラグインのソース貼ってみますが、テンプレートとかないと動作しないのであしからず。

# $Id: mt-mixi_link.pl 8 2009-03-19 09:53:33Z mocel $

package MT::Plugin::mixiLink;

use strict;
use base 'MT::Plugin';
use MT 4;
use Encode ();
use Encode::Guess;
use Time::HiRes qw/sleep/;
use XML::Atom::Client;
use XML::Atom::Entry;

our $PLUGIN_NAME = 'mixiLink';
our $VERSION = '0.04';

#@MT::Plugin::mixiLink::ISA = qw(MT::Plugin);

my $APP;
my $plugin = MT::Plugin::mixiLink->new({
    name => $PLUGIN_NAME,
    version => $VERSION,
    description => "",
    doc_link => 'mt-plugins/mt-mixi_link/docs/mt-mixi_link.html',
    author_name => 'Mocel',
    author_link => 'http://archive.guma.jp/',
    l10n_class => 'mixiLink::L10N',
    blog_config_template => 'mixi_link.tmpl',
    settings => new MT::PluginSettings([
        ['mixi_id', { Default => '', Scope => 'blog' }],
        ['mixi_uid', { Default => 0, Scope => 'blog' }],
        ['mixi_passwd', { Default => '', Scope => 'blog' }],
    ]),
});

MT->add_plugin($plugin);

sub instance { $plugin }

sub load_config {
    my $plugin = shift;
    my ($args, $scope) = @_;

    $plugin->SUPER::load_config(@_);

    if ($scope =~ /blog:(\d+)/) {
        my $blog_id = $1;
        $args->{blog_id} = $blog_id;
    }
}

sub init_registry {
    my $plugin = shift;
    $plugin->registry({
            applications => {
                cms => {
                    list_actions => {
                        entry => {
                            mixi_link => {
                                label => 'Submit mixi',
                                code => \&itemset_mixi_link,
                                permissions => 'can_edit_entry',
                                dialog => 1,
                            },
                        },
                    },
                },
            },
        }
    );
}

sub doLog {
    my ($msg) = @_; 
    return unless defined($msg);

    use MT::Log;
    my $log = MT::Log->new;
    $log->message($msg) ;
    $log->save or die $log->errstr;
}

sub apply_default_settings {
    my $app = shift;
    my ($data, $scope) = @_;

    if ($scope ne 'system') {
        my $sys = $app->get_config_obj('system');
        my $sysdata = $sys->data();

        if ($app->{settings} && $sysdata) {
            foreach (keys %$sysdata) {
                $data->{$_} = $sysdata->{$_} if !exists $data->{$_};
            }
        }
    }
    else {
        $app->SUPER::apply_default_settings(@_);
    }
}

sub __decode {
    my $stuff = shift;

    my $enc = guess_encoding($stuff, qw/euc-jp cp932 utf8/);

    if ($enc && ref($enc)) {
        return $enc->decode($stuff);
    }
    else {
        return Encode::decode_utf8($stuff);
    }
}

#----- Transformer
sub itemset_mixi_link {
    my $app = shift;
    $APP = $app;

    my $user = $app->user;
    return $app->error($app->translate("Permission denied.")) unless $user->can_edit_entry;

    my $str = '';

    use MT::Blog;

    my $blog_id = $app->param('blog_id');
    my $scope = "blog:$blog_id";

    my $blog = MT::Blog->load($blog_id);
    my $blog_url = __decode($blog->site_url);

    $str = qq{Blog ID $blog_id: $blog_url\n};

    use MT::Util;

    my $blog_name = __decode($blog->name);
    $str .= qq{Blog Title $blog_name\n};

    my $mixi_id = $plugin->get_config_value('mixi_id', $scope) || 0;
    my $mixi_passwd = $plugin->get_config_value('mixi_passwd', $scope) || 0;
    my $mixi_uid = $plugin->get_config_value('mixi_uid', $scope) || 0;

    return $app->error($plugin->translate("No settings")) if !$mixi_id or !$mixi_passwd or !$mixi_uid;

    $app->{no_print_body} = 1;
    $app->send_http_header;

    my $html_head = <<'SCRIPT';
<script type="text/javascript">
function progress(str, id) {
    val el = getByID(id);
    if (el) el.innerHTML = str;
}
</script>
SCRIPT

    $app->print($app->build_page('dialog/header.tmpl', { page_title => 'mixiLink', html_head => $html_head }));
    $app->print($plugin->translate_templatized(<<"HTML"));
<__trans phrase="Posting your diary to mixi '[_1]'..." params="$blog_name">
<div class="modal_width" id="dialog-mixilink-weblog">
<div id="msg-conatiner" style="height:310px;overflow:scroll;overflow-x:auto">
HTML

    # Create Atom API Client
    my $mixi_uri = 'http://mixi.jp/atom/diary/member_id=' . $mixi_uid;

    my $mixi_api = XML::Atom::Client->new;
    $mixi_api->username($mixi_id);
    $mixi_api->password($mixi_passwd);
    $app->print("Created Atom API Client.\n");

    use MT::Entry;
    foreach my $id (sort { $a <=> $b } $app->param('id')) {
        my $entry = MT::Entry->load(
            {
                blog_id => $blog_id,
                id => $id,
                status => MT::Entry::RELEASE,
            }
        );

        if ($entry) {
            my $title = __decode($entry->title);
            my $text = __decode(MT::Util::encode_html($entry->text));

            $app->print(qq{Found the diary entry "$title"\n});

            # if "More" exists add the link to entry.
            if ( $entry->text_more ne '' ) {
                $text .= Encode::decode_utf8("\n\n続きは " . $entry->permalink() . ' で。');
            }

            # Create Atom Entry
            my $mixi_entry = XML::Atom::Entry->new;
            $mixi_entry->title($title);
            $mixi_entry->summary($text);

            $app->print(qq{Created a Atom Entry.\n});

            # POST
            $app->print(qq{Submit entry => $title\n});
            my $edit_uri = $mixi_api->createEntry($mixi_uri, $mixi_entry);

            if ($edit_uri =~ m{/member_id=(\d+)/entry_id=(\d+)}) {
                # Success
                my $entry_id = $2;
                $app->print(qq{Completed "$title"\n});  #"
            }
            else {
                $app->print( qq{Confirm error: "$title"\n} );
            }
        }
    }

    my $return_url = $app->return_uri;

    $app->print($plugin->translate_templatized(<<"HTML"));
<form action="GET">
<div class="actions-bar">
<div class="actions-bar-inner pkg actions">
<button onclick="closeDialog('$return_url'); return false" type="submit" class="primary-button"><__trans phrase="Close">
HTML

    $app->print($app->build_page('dialog/footer.tmpl'));
}

sub mixi_abort {
    $APP->error(@_);
}


1;