しょこたんが出るTV番組の情報をGoogle Calendarに入れておくことで見逃さないようにするテスト

タイトルのまんま。
前回、しょこたん☆ぶろぐの更新情報をGoogle Calendarに入れるってのができたので、今回はTV番組情報をLivedoor番組表から取得して、Google Calendar APIで更新かけてみる。

アイディアソースは [Plagger] テレビ番組表を Plagger で #2 - Bulknews::Subtech - subtech

結論から言うと、コアの部分はサクッとできた。

けど、今のやりかたじゃぁ色んな所が決定的にダメ。あー、ダメなんじゃなくて、需要を満たせてない、が正しいか。
いずれにしても対応するのには今の僕の知識と技術では結構時間がかかりそう。
すぐできると思ったんだけどなぁ。。。誰かいいアイディア・方法を教えてplease...(突っ込みコメント、TB歓迎!!)

ということで、ここまでのやり方と対応詳細は以下の通り。
まずTV番組情報のソースはlivedoor番組表。何故Livedoorかというと番組表をRSSで配信してくれてるから。
番組表RSS配信サービス

詳細検索で「中川翔子」をフリーワードで指定、放送地域でとりあえず東京都とか指定してやればフィードのURLが生成される。東京以外の地域はどうせ見れないから気にしないことにする。
ちなみに「フリーワード」でなく「出演者」で検索すると出てこない番組があったりします。うたばんとか。

で、そのRSSをPlagger使って取得。Publish::GoogleCalendarを使って更新かければ終了、なんだけど
(1) GoogleCalendar.pmはイベントの終了時刻に対応してない(5分後に決め打ち)
(2) Plagger::Entryが終了時刻を持ってない
(3) LivedoorのRSS見ると分かるけど、番組のitemは

ポケモンサンデー
http://tv.livedoor.com/program/detail/56441789.html

「だるまさんがころんだ、靴飛ばし」

テレビ東京
2008-01-27T07:30:00+09:00
livedoor TV



  アニメ/特撮/国内アニメ
  2008-01-27T07:30:00+09:00
  2008-01-27T08:30:00+09:00

  9502176
  http://tv.livedoor.com/tvpi.epg?pid=56441789
  TIM,ロバート,中川翔子


という感じ、17行目の部分に終了時刻があったりする。

なので、
・Plagger::Plugin::Namespace::LivedoorTVを自作
mizzy.org : Plagger::EventにあるEvent.pmを持ってきて置いてみる。そのままじゃ日付の扱いがイケテないので、そこだけ直す
・Entry.pmでEvent.pmを扱えるよう、上記のサイトの通りに改造
・Namespace::LivedoorTVで情報をPlagger::Eventに詰めて $entry->add_event とかする
 Eventを流用じゃなくて新規にTVProgram.pmとかを作っても良かったんだけど、終了日がないって当面の問題を解決する以上のことをやるのは面倒なのでとりあえず今は流す
 (参考にしたのはNamespace::Hatenafotolife
・GoogleCalendar.pmを改造して、entry->event->dtend みたいなものを取得できるようにする
という対応をして動いたのが冒頭のスクリーンショット。plagger初心者な僕でも、なんだかんだで2時間程度でここまではできちゃうとは、やっぱりplaggerスゴい。

パッチとかコードとかは後で貼るを貼った。
・GoogleCalendar.pmのパッチ:ダウンロード
 (ついでにタイトルの嫌だった所も直してる)
・Entry.pmのパッチはここにあるのをそのまんまPlagger0.7.17に当てた
・Event.pm(dtstart、dtendをmk_date_accessorsにした)
package Plagger::Event;

use strict;

use base qw( Plagger::Thing );
__PACKAGE__->mk_accessors(qw( summary description location organizer ));
__PACKAGE__->mk_date_accessors(qw( dtstart dtend ));

1;
・LivedoorTV.pm
package Plagger::Plugin::Namespace::LivedoorTV;
use strict;
use base qw( Plagger::Plugin );
use Plagger::Event;

sub register {
    my($self, $context) = @_;
    $context->register_hook($self,
                            'aggregator.entry.fixup' => \&handle,);
}

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

    my $livedoortv = $args->{orig_entry}->{entry}->{"http://tv.livedoor.com/spec/-/1.0/"}->{feed}->{tv} || {};

    my $ldtv_startDatetime = $livedoortv -> {startDatetime};
    my $ldtv_endDatetime = $livedoortv -> {endDatetime};

    my $event = Plagger::Event->new;
    $event->dtstart($ldtv_startDatetime);
    $event->dtend($ldtv_endDatetime);

    $args->{entry}->add_event($event);
}

1;

んで、現状の課題点
(1) Filter::RuleでFreshの指定が効かない
 ・実行する都度、同じ番組情報がどんどんGoogle Calendarに追加されていく
 ・だから現状、cronでは動かせない
 ・Plagger::Rule::Freshのソースみたら、キャッシュファイルのタイムスタンプとRSSエントリの日付を比較してるように見える
 ・TV番組は「未来の」ものをヲチしないと意味ないから、Filter::Rule::Fresh的に「Fresh」なのは当たりまえ、そのままでは使えない
(2) 情報ソースが情報の更新時刻を持ってない
 ・いやー、dc:dateがTV番組の開始時刻なんですよねぇ、えぇ。
 ・せめてここが「その情報が公開された時刻」だったらここで終了、なんですが
(3) Google Calendarの文字化け問題
 ・重複するのが嫌なのでAPI経由で更新かけるんじゃなくって、Publish::iCal使うのも考えたんですが、.icsをGoogleカレンダーの「URLで指定」で取り込ませると豪快に文字化けする
 ・文字コードをUTF-8直接だとダメで、数値参照にすりゃぁいける(情報源)。自分でもテストコード上で確認済み

ってことで解決方針。の案。(まだ自分でもどうするのがベターか分かりかねる)

・最も日付が新しい番組の放送開始時刻でFreshのタイムスタンプ更新
 → 未来のタイムスタンプのファイルができること自体すげー気持ち悪い
 → 常に後ろに予定が追加されていくだろう、ってLivedoor側の仕様に期待するのもなぁ。。
・Calendarをaddする直前に、同じ時刻・同じタイトルの予定の有無をチェック
 → スケジュール管理ツール的にはこれがベターかもしれない。時間帯のチェックだけでダブルブッキング防げるし
 → GoogleCalendar.pm大改造・・・
・Livedoor以外の情報ソースを使う
 誰かいいところ知ってたら教えて下さい


まぁそれよりも何よりも、ウチにはHDレコーダーはおろかビデオデッキすらないってのが最大の問題だけどな。