ishiducaの日記 このページをアンテナに追加 RSSフィード

2010-08-22

[][][]今日の予定を教えてくれる僕だけの秘書をつくろう 15:04 今日の予定を教えてくれる僕だけの秘書をつくろう - ishiducaの日記 を含むブックマーク はてなブックマーク - 今日の予定を教えてくれる僕だけの秘書をつくろう - ishiducaの日記 今日の予定を教えてくれる僕だけの秘書をつくろう - ishiducaの日記 のブックマークコメント

GoogleCalendarのメール通知を利用すれば、本日の予定でも3日後の予定でも細やかに通知してくれるんですが、「今日の予定って?」って尋ねたら教えてくれる秘書がいたらいいですよね^ ^

要するに通知botのことですが、GoogleCalendarとTwitterを使って作ってみました。

流れとしては、

  1. 秘書ボット宛のmentionsの一覧を取得
  2. mentionsの一覧から僕(@ishiduca)のツイートで「今日の予定」というキーワードを含むものを探す
  3. 探し当てた場合で、今回初出のツイートの場合は GoogleCalendarから今日の予定を抽出して僕(@ishiduca)宛に、ツイートする

というもの。

GoogleCalendarからイベントを取得するには

  1. webページ右上あたりの「設定」→「カレンダーの設定」で、「カレンダーの設定」ページに移動
  2. 「カレンダー」タブを選択。僕が閲覧できるカレンダーの一覧が出るのでその中から、使いたいカレンダーを選択して「xxの詳細」ページへ移動
  3. 「カレンダーのアドレス」で[xml]を選択して、URLを取得したら、LWP::UserAgentでxmlを取得。XML::SimpleのXMLinで解析

実際の運用時には、下記の my_secreatary.pl を cron で実行(mentionsの一覧を取得)します。そうすると探し出したツイートと重複したツイートが出てくるので、それに反応しないようにするために、今回も memcached を使います。

また、前回作った My::Twitter モジュールを使います。(mentions一覧を取得するのに get_mentionsメソッド追加しましたけど)

あと直近のツイートと同じツイートを連続すると403エラーが返ってくるので、リプライを投げる時刻をくっつけて誤魔化してます。

my_secretary.pl

#!/usr/bin/env perl
BEGIN {
    # cronで動かすのに暫時的に指定する
    push @INC, '/Users/ishiduca/MyApp/';
}
use strict;
use warnings;
use utf8;
use Encode;
use My::Twitter;
use LWP::UserAgent;
use XML::Simple;
use DateTime;
use Cache::Memcached::Fast;

my $cache = Cache::Memcached::Fast->new({
    servers => [ "localhost:11211" ]
});

my $secreatary = Twitter->new;
$secreatary->set_oauth_consumer(
    consumer_key    => 'Your Secreatary Consumer Key',
    consumer_secret => 'Your Secreatary Consumer Secret',
);
$secreatary->set_access_token(
    token  => 'Your Screatary Access Token',
    secret => 'Your Screatary Access Secret',
);

my $mentions = $secreatary->get_mentions;
for (@{$mentions}) {
    my $id     = $_->{id};
    my $tweet  = $_->{text};
    my $friend = $_->{user}{screen_name};

    if (! $cache->get($id)) {
        $cache->set($id, $_);
        if ($friend =~ /^ishiduca$/ and $tweet =~ /今日の予定/) {
            &hoge;
        }
    }
}

exit 0;


sub hoge {
    my $today = DateTime->now;
    $today->set_time_zone( 'Asia/Tokyo' );
    my $today_ymd = $today->ymd; # ex 2010-08-22
    my $now       = $today->hms; # ex 10:22:33

    my $ua = LWP::UserAgent->new;

    my $calendar_url = "http://www.google.com/calendar/feeds/.../full";
    my $response = $ua->get( $calendar_url );
    die $response->status_line if ! $response->is_success;

    my $parser = XML::Simple->new;
    my $events = $parser->XMLin($response->{_content});

    my $c = 0;
    for my $key (keys %{$events->{entry}}) {
        my $date = $events->{entry}{$key}{'gd:when'}{startTime};

        if ($date =~ /$today_ymd/) {
            $c++;
            my $content = $events->{entry}{$key}{title}{content};
            $date =~ s/:[0-9][0-9]\..+$//;
            $date =~ s/^20[0-9][0-9]-//;
            $date =~ s/-/\./g;
            $date =~ s/T/ /;
            $secreatary->tweet(encode_utf8(
                substr(join(" ", '@ishiduca', "$date", "$content at $now"), 0, 140)));
        }
    }

    if ($c == 0) {
        my $murmur = encode_utf8('今日は何も無いから一緒にお出かけしようよっ');
        $secreatary->tweet(join " ", '@ishiduca', "$murmur at $now");
    }

    exit 0;
}

日付の処理が汚いですね >_<

f:id:ishiduca:20100822150006p:image

こんな感じに。

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20100822