理系学生日記

おまえはいつまで学生気分なのか

IT 勉強会カレンダーを iCal でちょっと使い易くする

IT 勉強会カレンダーにはぼくもお世話になっています。ぼくはこのカレンダーを iCal に登録している。ところが、iCal だとちょっと困ったことが起こってしまいます。

勉強会カレンダーには、その勉強会に関する URL まで配信してくれていますが、iCal ではこの URL にリンクを張ってくれません。

これはなぜかというと、URL の情報が、Description プロパティで配信されてしまってるからです。iCal だと、Description プロパティはメモ欄になるみたいで、これじゃイチイチ URL をコピペしてブラウザに貼り付けないといけない。。
iCalendar を定義している RFC2445 では、Description プロパティの目的を以下のように示しています。(勝手に訳した)

目的:
このプロパティは "SUMMARY" プロパティよりも完全なカレンダーコンポーネントの説明を提供します

本来、この URL が提供されるべきは URL プロパティだと思うのですよ。

目的:
このプロパティは、iCalendar オブジェクトに関連した URL を定義する

というわけで、Description プロパティの値を URL プロパティに設定してあげれば良い。

hakobe さんが一年前に IT 勉強会用のスクリプトを作られてた(IT勉強会カレンダーをフィルター - はこべにっき ♨)ので、それを基に(ていうか上記の処理を加えただけ)こんなのを作ります。

use strict;
use warnings;
use URI::Fetch;
use Data::ICal;
use utf8;
use Encode;

my $CAL_URL = 'http://www.google.com/calendar/ical/fvijvohm91uifvd9hratehf65k%40group.calendar.google.com/public/basic.ics';

my $res = URI::Fetch->fetch( $CAL_URL ) or die URI::Fetch->errstr;
my $ical = Data::ICal->new( data => decode_utf8( $res->content ) );
die $ical->error_message if ref( $ical ) eq 'Class::ReturnValue';

my $entries = $ical->entries;
$ical->{entries} = [];
for my $entry (@$entries) {

    if ( $entry->property( 'description' ) ) {
        $entry->add_property( url => [
            $entry->property( 'description' )->[0]->value,
            { value => 'URI' }
        ]);
        $entry->add_property( description => undef );
    }

    my $summaries = $entry->property('summary');
    unless ($summaries) {
        $ical->add_entry( $entry );
    }
    else {
        my $summary = $summaries->[0];
        $ical->add_entry( $entry ) if $summary->value =~ /(?:東京|筑波|オンライン|千葉)/;
    }
}
my $output = $ical->as_string;
print encode( 'utf-8', $output );

これで生成された iCalendar のデータを iCal に読み込ませるとこんな感じ。

ちゃんと URL 欄にリンクが張られてることがわかります。やったね!