そんなスクリプトをわざわざ作らなくても,Settings -> Calendars -> CALENDAR -> Notifications -> Daily agenda にチェックを入れておけば,5am(実際は4:30am頃?)にメールで予定一覧を送ってくれる.が,フォーマットが気に入らない(携帯メールに転送すると文字数制限をオーバーする),好きなメールアドレスに送れない(G-mailのフィルタで転送すればいいが)といった問題があるので, Google Calendar API を使って,1日の予定を一覧するPHPスクリプトを作ってみた.
Google Calendar API †
Google Calendar の Settings -> Calendars -> CALENDAR -> Private Address: -> XML を選択すると,
http://www.google.com/calendar/feeds/USERID/private-MAGICCOOKIE/basic
のようなフォーマットのURLが表示される.USERID,MAGICCOOKIE は個々のユーザのカレンダーに固有の値(他人に知られるとよろしくない).ここで,basic の代わりに適当なパラメタを設定してやることで,例えばある日の予定をXML形式で得ることができる.Data API Reference Guideを参考に,11月4日の予定を取得するようにパラメタを設定すると,
http://www.google.com/calendar/feeds/USERID/private-MAGICCOOKIE/full?start-min=2009-11-04T00:00:00&start-max=2009-11-04T23:59:59&orderby=starttime&sortorder=a&singleevents=true
こんな感じになる.
この結果のXMLを適当にソートするなどして表示すれば,目的は達せられる.
本日の予定を一覧するPHPスクリプト †
以下のPHPスクリプトでは,複数のカレンダーを統合できるようにした(カレンダーごとに USERID と MAGICCOOKIE が異なり,個別にXMLを取得しなければならない).
<?php
class TEvent
{
public $StartTime = '';
public $EndTime = '';
public $Title = '';
public $Description = '';
}
function CmpEvents($a, $b)
{
if ($a->StartTime == $b->StartTime) return 0;
if ($a->StartTime=="all day") return -1;
if ($b->StartTime=="all day") return 1;
return ($a->StartTime < $b->StartTime) ? -1 : 1;
}
function agenda_of_google_calendar($htitle,$userid,$magicCookie,&$events)
{
// $date= '2009-09-30'; // for test
$date= date("Y-m-d");
$target= 'http://www.google.com/calendar/feeds/'
. $userid
. '/private-'
. $magicCookie
. '/full?'
. 'start-min='.$date.'T00:00:00'
. '&start-max='.$date.'T23:59:59'
. '&orderby=starttime&sortorder=a' .'&singleevents=true';
$xml = simplexml_load_file($target);
// 2009-05-15T14:30:00.000+09:00
$date_pattern='([0-9]{4}-[0-9]{2}-[0-9]{2})T([0-9]{2}:[0-9]{2})(:[0-9]{2})';
foreach ($xml->entry as $item)
{
$gd = $item->children('http://schemas.google.com/g/2005');
$startTime = $gd->when->attributes()->startTime;
$endTime = $gd->when->attributes()->endTime;
$title = $item->title;
$description = $item->content;
if (ereg($date_pattern, $startTime, $sregs)
&& ereg($date_pattern, $endTime, $eregs))
{
$event= new TEvent();
$event->StartTime=$sregs[2];
$event->EndTime=$eregs[2];
$event->Title=$title;
$event->Description=$description.$htitle;
$events[]=$event;
}
else
{
$event= new TEvent();
$event->StartTime='all day';
$event->Title=$title;
$event->Description=$description.$htitle;
$events[]=$event;
}
}
}
$events= array();
$userid= 'USERID1';
$magicCookie= 'MAGICCOOKIE1';
agenda_of_google_calendar(' (Akihiko)', $userid, $magicCookie, $events);
$userid= 'USERID2';
$magicCookie= 'MAGICCOOKIE2';
agenda_of_google_calendar(' (Lab.)', $userid, $magicCookie, $events);
usort($events, CmpEvents);
// style(hrml):
// $eol="<br>\n";
// $date_style=array('<font color="#882222">','</font>');
// $cont_style=array('<font color="#0000ff">','</font>');
// $indent='';
// $space=' ';
// style(text):
$eol="\n";
$date_style=array('','');
$cont_style=array('','');
$indent='';
$space=' ';
echo "Agenda@".date("Y-m-d(D)")."$eol";
$prev_is_allday=false;
$delim='';
foreach ($events as $item)
{
if ($item->StartTime!='all day')
{
echo $delim;
echo $indent.$date_style[0].$item->StartTime.'-'.$item->EndTime.': '.$date_style[1] .$eol
.$indent.$space.$cont_style[0].$item->Title.'; '.$item->Description.$cont_style[1].$eol;
}
else
{
if (!$prev_is_allday)
{
echo $delim;
echo $indent.$date_style[0].'all day: '.$date_style[1] .$eol;
$prev_is_allday=true;
}
echo $indent.$space.$cont_style[0].$item->Title.'; '.$item->Description.$cont_style[1].$eol;
}
$delim=$eol;
}
?>
すべてのイベントを開始時間でソートできるようにイベントクラス(TEvent)を定義している.CmpEvents は開始時間でソートするための比較関数.開始時間が all day(終日)の場合は最初にくるようにしている.
関数 agenda_of_google_calendar($htitle,$userid,$magicCookie,&$events) で予定を取得し,TEventクラスの配列 $events に保存する.$htitle には Description の最後に追加する文字列, $userid には USERID, $magicCookie には MAGICCOOKIE をそれぞれ指定する. 複数のカレンダーを統合するには,それぞれのカレンダーごとに USERID と MAGICCOOKIE を取得して,複数回 agenda_of_google_calendar を実行する.上のサンプルでは2つのカレンダーを統合している.
usort でイベントの配列を開始時間でソートする.それ以降は,出力のコード.ここではテキストフォーマットで出力するようにしているが, style(text): 以下5行をコメントアウトし, style(html): 以下5行をアンコメントすれば,HTML形式で出力できる.
おまけ:毎日メールで送信 †
CRON を使うのがてっとりばやいと思う. crontab -e で,以下のような一文を追加すれば,毎日4:30amにメールが(MAILADDRESSに)送られる.
30 4 * * * php /home/akihiko/bin/php/google-calendar.php | nkf -s | mail -s "Agenda(`/home/akihiko/bin/linux/today`)" MAILADDRESS
なお, /home/akihiko/bin/php/google-calendar.php は上記のスクリプト,/home/akihiko/bin/linux/today は日付を返すbashスクリプト:
#!/bin/bash
LANG=C
date +'%m/%d(%a)'
メールで送信するためには,常時稼働しているサーバマシン上で CRON を実行する必要がある.Debian でのメール送信には Exim4 を使うとよいようだ(以下の参考URLを参照).