天然パーマです。

「これ☆ほしい」BugFix & タイムライン機能追加 & 評価とコメントお願いします

ウェブで話題の「みんなの物欲」がひとめでわかるサイト『これ☆ほしい』(リリース)。 エントリー情報が更新されないというバグ(?)を修正しました。 それに伴い、DBを初期化してしまったので、過去のエントリーのPermalinkがずれてしまいましたが、 ご了承ください。これで、 とあるエントリーにUserが新しく「これほしい」とタグをつけてはてブすれば、 その分カウントが一つ増えるようになりました。

さらに加えて、新機能「タイムライン」を追加してみました。 これは「これ☆ほしい」に登録された人気エントリーを「時系列Xほしいカウント」で 並べて見ることができるというものです。 @nifty TimeLineAPIを使っています。 「ほしいカウント」が5とか6とかのエントリーが多いので下の方はわりとカオスになっちゃってますが、 それを差し引けば、時間別にどんな物が流行ったのかが一目瞭然なのでわりかし面白いかもしれません。

これ☆ほしい

また、つくるぶというサービスが提供しているサイトスカウターなるものを設置してみました。

サイトスカウターは、デベロッパーのみなさんが作成したサイトに設置することで、サイトのPV(サイトスカウターのロード回数)、サイトにアクセスしたユーザーからの評価点やコメントを得ることができるツールです。

サイトスカウター あなたのサイトを診断します -つくるぶより

「これ☆ほしい」のトップページなどの右サイドに貼り付けてあるので、是非みなさん、 評価及び、コメントをお願いします。お願いします。お願いします。 このサイトスカウターの評価&コメントは「Mashup up Award 3rd」審査の参考になるということなんで、 みんなのおかげでもしかしたら、もしかするかもよ! だから、お願いします。おながいします。お願いします。

これ☆ほしい

補足 : コードの話

まず、バグをどうやって直したか、というかバグって呼んでいいのか? とりえあずこんな状態でした。

公開してから気づいて、速攻で直したんだけど、 これ☆にはちょっとしたバグがありました。 記事が重複して現れるという現象です。 例えば『iPod Touch @ Apple』へのリンクを持つページが3つ登録されちゃうとか。 強引に直して重複は無くなったけど、その代わり更新情報が取れなくなってしまっている現状です。 これはStore-DBICの仕様なのでしょうがない…。

ゆーすけべー日記: 「これ☆ほしい」公開から2日目でのフィードバックまとめより

解決策として、otsuneさんに教えてもらった、 「SmartFeedでEntryを一つのFeedにまとめてからStore-DBICする」という方法で直しました。 config.yamlにSmartFeed::Allを加えて、Store::DBICのruleを設定すればすればOKです。 Dedupedも不要になりました。

 
  - module: SmartFeed::All

  - module: Store::DBIC
    rule:
      expression: $args->{feed}->id eq 'smartfeed:all'
    config:
      schema_class: Plagger::Schema::SQLite
      connect_info: [ 'dbi:SQLite:/path/to/plagger.db', ]

次に、@nifty TimeLine へ APIを使ってポストする部分について解説。 「これ☆ほしい」のエントリーからカウントが5以上のものをひっぱってきて、 まだTimeLineに登録されていなかったら新規「できごと」を作成してポスト、 登録されていたら「できごと」更新という機能を持つPerlプログラムを作りました。 それをcronで回しています。

エントリー情報は、 Plaggerが生成して、Catalyst側で利用しているdbから(Catalystアプリの)DBIx経由で取得しています。 自分で書いた記事ですが、 「Catalystのモデルを外部スクリプ&トから操作する(Loaderが0.03007の場合) (Yusukebe::Tech)」がもろ参考になります。 ちなみにTimeLine向けに、dbのEntryテーブルに「timeline_id」というフィールドを追加しました。 APIを使ってTimeLineにポストする部分はkazeburoさんの 「WebService::TimeLine」 を使わせていただきました。 このniftyのAPI、ちょっとした癖があって、

  • タイトルと本文の先頭と末尾に空白が含まれるとポストされない
  • タイトルと本文が空だとポストされない

ので、適当に対策。できあがった、Perlのコード例は以下です。 Catalystアプリのホームディレクトリから一回層下にあるディレクトリに置いてあります。

 #!/usr/bin/perl

use strict;
use warnings;
use FindBin;
use Path::Class::File;
use DateTime;
use DateTime::Format::W3CDTF;
use WebService::TimeLine;
use URI::Escape;

use lib "$FindBin::Bin/../lib";

my $timeline_id = 'XXXX';
my $api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

my $db_path = Path::Class::File->new('./', 'plagger.db')->absolute;

{
    package MinBuyo::Model::DBIC;
    use base qw/DBIx::Class::Schema::Loader/;
    __PACKAGE__->connection('dbi:SQLite:' . $db_path);
    __PACKAGE__->loader_options();
}

my $timeline = WebService::TimeLine->new( 
                              timeline_key => $api_key,
                              );

my $entries = MinBuyo::Model::DBIC->resultset("Entry")->search();

while( my $entry = $entries->next ) {

        unless($entry->timeline_id){
                &create_article($entry);
                print "posted : " . $entry->link . "\n";
        }else{
                &update_article($entry);
                print "updated : " . $entry->link . "\n";
        }

}

sub create_article{
        my $entry = shift;
        my $dt = DateTime->from_epoch( 
                    epoch => $entry->date, time_zone => 'Asia/Tokyo',
	                                 );
        my $title = create_title($entry->title);
        my $article = $timeline->create_article(
                  timeline_id => $timeline_id,
                  title       => &strip($title),
                  description => &strip($entry->body),
                  start_time  => DateTime::Format::W3CDTF->format_datetime($dt),
                  end_time    => DateTime::Format::W3CDTF->format_datetime($dt),
                  grade       => $entry->rate,
                  link => [$entry->link]
        ) or die $timeline->errstr;
        $entry->timeline_id($article->{id});
        $entry->update;
}

sub create_title {
        my $title = shift;
        utf8::decode($title);
        $title = substr($title,0,50);
        utf8::encode($title);
        return $title;
}

sub strip {
        my $str = shift;
        utf8::decode($str);
        $str = "..." unless $str; # if content is null , set '...'
        $str =~ s/^\s*(.*?)\s*$/$1/; # strip white space
        $str =~ s/^ *(.*?) *$/$1/;
    utf8::encode($str);
        return $str;
}

sub update_article{
        my $entry = shift;
        my $article = $timeline->update_article(
                    $timeline_id,
                    id => $entry->timeline_id,
                    # update properties...
      );
}

以上、とりあえず、 「サイトスカウター@これ☆ほしい」の評価&コメントお願いしまつ。