iCalからGoogle Calendarへ同期をとるツール書いた

wtnabe/ical2gcal - GitHub

何ができるか

  • iCalendar 形式のデータを指定の Google Calendar へ同期させる1
  • 複数の iCalendar データを一つの Google Calendar にまとめることができる

なぜ必要か

  • Android の少なくとも 2.3 までのカレンダーは「照会」を使えないから
  • 個人的には Google Calendar は使っていないが「照会」したいカレンダーがいくつもあり、それらをいちいち手作業でインポートしたりせずに Android 上で確認したいから

どうやって動かすか

準備するもの

  • Ruby
  • gem install ical2gcal
  • googleアカウント
  • 同期をとるカレンダーのURL(またはパス)
  • 同期先のカレンダーとその名前

あとは

ical2gcal –help でなんとなく察して。

使用例

こんなことができます。

  • RTM のプライベートアドレスから Google Calendar への同期を明示的に行える
    • Google Calendar で直接参照すると反映がとても遅く、使いものにならない
  • Trac の milestone の締め日を iCalendar 形式で取得して Google Calendar 上で確認可能

その他、URL やパスのある iCalendar 形式のデータであればなんでも Google Calendar と同期できる。

自分の場合はこれを自宅サーバや社内のサーバで cron で定期実行して Android のカレンダー上で気にしなければいけない日時を俯瞰できるようにしている。

制限

  • 「1実行 : 1Google Calendar」の対応なので、同期したいカレンダーが複数ある場合は何回も実行しなければいけない

ただ、このおかげで同期頻度を調整もしやすいので、これでいいかなと思っている2

できあがった Google Calendar を Android 端末で利用する際の問題

このツールを使って Google Calendar を別なツールやプログラムから更新することができる。しかしこれを Android で同期しようとすると問題になる場合がある。

どうも Android のカレンダープログラムは外部のカレンダーデータについては Google Calendar との同期しかできないのにその同期が正しく動作しないというバグがあるらしい。

手元で確認したおかしな動作は以下の通り。

  1. Google Calendar に正しく反映されていても Android のカレンダープログラム上で再現されない
  2. そもそも Mobile の Google Calendar は終日のイベントを表示してくれない

2 については Google のサーバ側の挙動なのでどうにもならないけれど 1 については

  • 同期に失敗しているカレンダーを Android 上で削除
  • いったん更新(同期)して
  • 再度同期したいカレンダーを追加

すると正しく反映されるようだ。こちらのアプリだとダメであちらのアプリだと大丈夫、という話もフォーラムなどでは見かけるが、手元の環境では一切そういうことはなかった。

とにかく

削除 -> 追加

を行う。

Andorid 上の削除は Google Calendar からの削除にはならず、あくまで Android とのリンクを切る、という感じで動作するらしい。

しかもこの問題、必ず反映されなくなるかというとそうでもない、とてもいやらしい発現具合。結局、

終日のイベントが表示されないのを分かったうえでブラウザで Google Calendar を開くのがいちばん確実

という状態。

しかし、かなり有名なバグっぽいんだけど全然直ってないのね。

cf.

開発時に気づいたこと

  1. Ruby で書いたわけだが、意外なことに Google Calendar 上の event を削除できないライブラリが多い
  2. 必ずしも event の削除に成功するわけではない
  3. 全イベントを削除するのが面倒、あるいはできないからってカレンダーを削除して作り直しちゃダメ3

2 については実は今も解決はしていない。個人的には cron で定期実行しているうちになんとなく解決するので良しとしている4

1 については一度 event を削除できないライブラリを採用して作り始めてしまい、仕方なく googlecl という Python でできたコマンドラインで Calendar などを管理できるツールで削除を行ってみたがこれを cron で自動実行することができなかった。5

結局ライブラリを置き換えて Google Calendar へ投げる部分はすべて作り直した。また iCal のライブラリでパースして Google Calendar のライブラリでイベントを作成するわけだけど、

  • Google Calendar ライブラリが end time を必要とするが元の iCal が終日イベントの場合に end time がないことがある
  • Google Calendar ライブラリには「終日」を明示するメソッドがあるが iCal をパースするライブラリにはこれを取得する方法がない6
  • DateTime オブジェクトと Time オブジェクトの違い
  • timezone が合わない7

など、実際にいじってみて初めて知った細かい差異にいちいち引っ掛かった。

課題

API 呼び出しについてはテストがなんにもない。まさにレガシーコード。

当初は Google Calendar の情報を解釈するのに標準の rss/atom モジュールを使おうかと思っていたんだけど、これで Atom を解釈する例が見つからなかったので simple-rss を利用している。標準のライブラリが Atom に対応していなかった時代が続いてるうちに gem のライブラリで処理するのがフツーになってしまったようだ。ちょっと残念。まぁ依存も少なくていいんだけど、少しだけ標準添付のライブラリで処理できた方が嬉しいなと思った。

まとめ

Twitter でも結構長いこと不満を並べていたが、これでようやく RTM を起点にカレンダーで予定を俯瞰できるようになった。Android と Google Calendar との同期についての不満は解消されていないが、時が解決するかブラウザでの閲覧にだんだん慣れていくか、呼吸するようにカレンダーの削除 -> 追加が行えるようになるかのいずれかだろうと思っている。

ちなみに、今カレンダーアプリは

Calendar Pad - Android マーケット

を使っている。もっと有名なものもあるんだけど iOS のカレンダーのように一覧上である程度情報が見えて、Evo の画面をちゃんと使い切るアプリがあまりなくてこれになった。ただし、カレンダーの追加/削除にはどうしても標準の「カレンダー」を使わなくちゃダメで、かつ最新の状態はブラウザで見るのが確実なので、結局

  • ホーム画面に Google Calendar のブックマークを置く
  • ホーム画面にフォルダを作って今挙げた二つのカレンダーを登録

という、なんだかなーという状態になっている。

  1. 1回だけインポートできるツールはいくつかあるけど、このツールなら何回でも同期させられる 

  2. 例えば毎日同期をとるもの、毎時同期をとるもの、など。 

  3. IDが変わり、URIが変わるので「照会」や「同期」している側で認識できなくなる 

  4. 真面目に対応するならエラーがゼロになるまで retry した方がいいんだろうけど、ダメなときはしばらくダメだったりするので対応は難しいんじゃないかなとなんとなく思っている。 

  5. 削除時に y/N で確認を求められるが、これをうまく制御できなかった。cron でなく手で起動した場合には動作したが、それでは自分の目的を達成できなかった。 

  6. 開始時刻が 0:00 で終了時刻がない場合に終日と判断するようにした。 

  7. 無理矢理削って処理したらlocaltimeになった 

Retrospectivaを試してみた

実際に試したのは 4月29日。

Trac に対する不満

Trac からの移行を考えている。なんでかっていうと

  • Trac は複数のプロジェクトを扱うことができない
  • 1Trac : 1ユーザーDB になるのでプロジェクトが増えるとユーザー管理が面倒くさい

Trac は基本的に認証用のユーザー DB と権限管理のユーザー DB が分離している。デフォルトでは認証は HTTP サーバの BASIC 認証を利用していて、権限を Trac の DB に保存する形。この形のままプロジェクトごとに Trac が増えていくとかなり管理しにくいこと請け合い。

もしかするとリポジトリは1つにすべしという考え方に基づいているのかもしれない。でも自分の経験では適切に分割してある方がやはり扱いやすい。これは皮肉なことに(?)特に Trac を使い始めてから強く感じている。例えば複数のプロジェクトの branch が増えてくると Trac で browse するのも一苦労1。開発プロジェクトと管理プロジェクトではチケットの設計だってずいぶん違う。

まぁそんな訳で複数のリポジトリ、複数のプロジェクトを一つの ITS で管理できたらいいなと思うようになってきていた。調べると Trac にも複数のプロジェクトを横断的に閲覧することを助けてくれる plugin はある。でもそれは目的と違うんだよなぁ。

ごく大雑把に特徴

というわけで Retrospectiva. ざっと調べたのと軽く動かしてみた印象での特徴は以下のような感じ。

  • Ruby on Rails アプリ
  • ということは ActiveRecord で扱えるすべての DBMS とともに動く
  • 機能的には Trac + WebAdmin + blog
  • 独自に認証の機構を持つ
  • 複数プロジェクトを管理可能、これらをグループと関連づけて運用する
    • プロジェクトごとに参加メンバーが違うなど

この時点で複数プロジェクトのために複数 Trac を設置して、それぞれバラバラにユーザー管理しなければいけないという事態からは解放される。

インストール

Rails のインストールは省略。今回はFreeBSD上で、すでにOpenFL(Fastladder.org)のために構築してあった Rails 2.0.2 の環境でテスト。

試した時点ではアーカイブのダウンロードという選択肢はなく、svn co する以外にない。ちょっとビジネス寄りの人にはいやがられるかもね。

Rails 2.0.2 では stable 1.0 は動かなかった。trunk(Rev.495) は動いた。

リポジトリとの関連付けは任意

Trac と大きく違うのは、

  • リポジトリとプロジェクトは必ずしも結びついていなくてよい
  • リポジトリは local だけでなく remote でもよい
    • 試してないけどたぶん2

つまり、リポジトリを使わないプロジェクト(開発以外)などにも使えるってことだ。これはなかなかいいと思う。メニューのカスタマイズもできるので Browse のメニューは必要なければ消しちゃえばいい3。開発者と非開発者で同じ Retrospectiva を共有しやすいと思う。

subversion 以外とも連携できるようにということは配慮されているみたいだけど、今のところ subversion しか使えないように見える。4

migration

trac からの移行用スクリプトはある。どれだけ双方のバージョンに追随しているのかは分からないけど。

「とりあえず見るだけ」ってどうやんの?

「Default」グループに各Viewの権限を、すべてのプロジェクトに対して割り振っておく。これやっておかないと(少なくとも試した rev. では)ログインしないと何にもできない状態になる。Trac に慣れているとここは面食らう。

redMineとの比較

ついでに redMine とも比較してみた。ただし gihyo.jp の記事を読んだだけ。これによると Trac, Retrospectiva に対する特徴としては

  • 最近のバージョンはパッケージに Rails 同梱でインストール簡単
    • Rails との互換性の問題などは考える必要がない
  • ロールによる権限管理
  • ワークフローが定義可能
  • Issue ごとに進捗率が設定可能
  • svn commit メッセージ連携機能
    • Issue の close を commit だけで完了可能(たぶん Trac なんかでも plugin でできなくはないと思うけど、標準で用意されてるってのが大きいのかな?)
  • Wiki, 文書、ニュース
    • ニュースが blog 的なものだとすると文書は?
    • Wiki は履歴が残る
  • forum もある

個人的な印象だけど、

なんか全体的にグループウェア的で、Tracクローンとは呼べないと思う。

Trac の経験があるなら移行は Retrospectiva の方が楽。redMine の方がどちらかというと開発者よりもマネージャ寄りの機能が充実しているような気がするけど、それは単に Trac も Retrospectiva もそういうことをあまり考えていないだけかもしれない。

まとめ

いずれにせよ Retrospectiva も redMine も Trac のようには plugin も情報も充実していない。Trac のどこに不足を感じ、これらのどこに魅力を感じるのか考えて決めるべし。

余談 - API ってないの?

贅沢を言えば Retrospectiva を API で操作できればなーって感じ。例えば

Mylyn&Tracでリズムに乗ってタスクを大掃除♪ (1/4) - @IT

では Trac に XmlRpcPlugin を追加して Eclipse との連携を実現している。こういうのが Retrospectiva にもあれば、eclipse に限らず外部のツールと連携させやすくなる。ブラウザさえあれば管理できるのがこれらのツールのメリットでもあるけれど、やはり HTML 上の UI には限度があると思う。Mozilla アプリの extension でも AIR でもいいけど、扱いやすい外部ツールを用意しやすくする仕組みは大事だよなーと、Twitter を irc クライアントで利用しながらつくづく思うのであった。

  1. ViewCVS を使っていたときは HTML の table にズラッと出てくる形ではなかったのでそれほど気にならなかった。 

  2. てゆーか svnsync なんてものが 1.4 以降からあったのか。 

  3. はず。 

  4. ちょっと grep 掛けてみただけ。 

Web 上のリソースの賞味期限

ときどきの雑記帖 リターンズ 2007年04月29日

自分は二つのことを意識しています。

  1. 古くならない情報を載せる
    • 古くなっても構わない情報を載せるってことです
    • PC説教講座ではこれを基本にしています。が、そうでないコンテンツもあります
  2. 古くなっていることがはっきり分かるようにする
    • 年月日がはっきり分かるようにする
      • tDiary は日記作成日が自動でセットされるのでだいたい問題ない
      • Wiki を使ったものは last modified そのものが自動的にセットされるのでたぶん問題ない
      • 説教講座もこれを目指しましたがよく分からなくなっちゃってるものも結構あります
    • バージョン番号がはっきり分かるようにする
      • まぁだいたいは OS やアプリについて書いているので、これらのバージョン番号を明記するようにしています。全部書けているかどうか分かりせんが

ふと MacPerl

MacPerl は System 7.0 から動く Classic Mac 用の Perl. Mac らしい UI がついている。OSX で動いているのは普通の Perl.

5.6 のバージョンが出てる。5.8 は alpha が出て止まってる。まぁいずれにしても 2002年に止まったと見ていいのかな。JPerl は 5.2.(5.004ベース?)

実際に使おうという気はないんだけど、とりあえず見てみた。

Panther の Finder では put できません

Re:FTPクライアント

(in Macにもっとも必要なアプリケーションは何か?

で気になってたんだけど、試すのが面倒でここまできてしまったもの。以下の環境で確認。

OS10.3.9
Finder10.3.2
言語英語と日本語

結果、英語環境だろうが日本語環境だろうが Finder では put できません。確かにこれで put までできれば十分使いものになりそうだなぁ。ミラーリングとかはできないだろうけど、普段使いにはよさげ。RBrowser Lite も使ってるんだけど、どうにも反応が重くて。

まぁそもそも GUI で ftp を使う機会ってあんまりないんだけど、smb も afp も WebDAV も GUI でマウントしたあとはコマンドラインでぐりぐりできちゃうし、ftp だけ別なのはちょっとイヤかも。lftp とか使えばいいんだろうけど。Tiger はできるのかな?

ttPage-plus

ネットワークが遅くて何をするにも待ち時間が長いので余計なことをしようとしているうちに見つけてしまった。念願の Unicode 対応版。

ついでに Wiki も

立ててみた。何かしらメモをためていけば役に立つだろう。以前は Kacis で設定メモを書いたりしていたが、ローカルに Wiki を立てても余裕のスペックだし、この方が更新も楽だし、ばんばんや。YukiWiki にしようかと思ったが、ノウハウが豊富な PukiWiki にしとく。YukiWiki の 2.1 系はまだ安定してなさそうだし。(というか結城さんは文章に比べてプログラミングは「気楽すぎる」感じがするんだよな。)

ダメじゃん > PortForwarder2

実家のマシンがことあるごとに調子悪くなるのに業をにやして Celeron 2GHz + Win2k の中古マシンを調達した。リモートメンテもできるように ssh2 対応になった PortForwarder 2 を入れて RemoteForward の設定をしたのだが、、、うまくいかなかった。

仕方がないので 1 を入れたらうまくいった。が、これだけのために ssh1 の接続を許可してしまったのがなんだか気持ち悪い。一応 scponly で non-interactive shell に閉じ込めたが。。。

About

例によって個人のなんちゃらです