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

2007-04-03 【続編】Lotus Notes CalendarからGoogle Calendarへイベントを登録 このエントリーを含むブックマーク

1年ほど前に"Lotus Notes CalendarからGoogle Calendarへイベントを登録する"という記事でコードを書いたんだけど、ときどきリクエストを投げると"Bad Request Error 400"となって帰ってくることがあって困ってました。

今日はちょっと時間があったので、原因究明とコードの改修に挑戦。

今まではGoogle CalendarのDescriptionにあたるフィールド、NotesカレンダーのBody部分を一度空の状態にしてリクエストを投げると成功するので、あとは手作業でコピペしていたため、ここが問題なんだろうということは察しがついてました。

なので原因として推測されるのは

1.開こうとしているURLの長さの問題

2.Body部のURLエンコードの問題

のどちらか、または両方かなと。

まず、1については"Bad Request"となったリクエストのURLの長さを数えてみると720バイトありました。これは特定のスケジュールからだけでなく、複数の"Bad Request"となるスケジュールからも確認できたので、おそらくHTTPで受け付けられるURLの長さは720バイトだろうと判断。

でも720バイトちょうどのリクエストを送っても"Bad Request"となるということは、URLエンコードの問題かなと思って、720バイトから何文字か削ってみたところ、ちゃんと登録画面が開けました。"日本語"という文字をURLエンコードすると"%E6%97%A5%E6%9C%AC%E8%AA%9E"というように"%"+"99"とう形式でエンコードされるのに、"Bad Request"となったURLは"%"で終わっていたり、"%"の後の数字が1桁だったりと、この条件を満たしてませんでした。

上記のことから、

1.開くURLを@Left()をつかって720バイト以内に収める

2.そのURLから@LeftBack()を使って、最後の"%"から左の文字列を@URLOpen()関数に渡す

ということで実現できそうです。

ちなみにIEでのURLの長さの制限は 2,083 文字だそうです。

[IE] URL に使用可能な文字数は最大 2,083 文字

ついでにちょっとだけコードをいじってみました。

このコードをツールバーにボタンを追加して、埋め込んであげればOK。

本当はボタンを押したときに、選択されてる文書のフォームをチェックして、カレンダーの文書じゃなかったらメッセージを返して〜なんてこともしたかったんだけど、めんどくさいのでやめました。

ちなみにLotus Notesは7.0の日本語版、Google Calendarの言語は英語、タイムゾーンは日本(GMT +09:00)で使ってます。

REM {@TimeMerge()で、Googleのタイムゾーンにあわせる};

gtimezone := "Z=-18$DO=0";

gStartDateTime := @TimeMerge( StartDateTime; StartDateTime ; gtimezone );

gEndDateTime := @TimeMerge( EndDateTime; EndDateTime ; gtimezone );

REM {月、日、時、分、秒の1桁を@Replace()で2桁に変換するためのリスト};

short := "0" :"1" :"2" : "3" : "4" : "5" : "6" : "7" : "8" : "9";

long := "00" :"01" :"02" :"03" :"04" :"05" :"06" :"07" :"08" :"09";

REM {開始年月日・時刻をyyyymmdd、hhmmss形式にフォーマット};

syear := @Text(@Year(gStartDateTime));

smonth := @Replace(@Text(@Month(gStartDateTime)); short; long);

sday := @Replace(@Text(@Day(gStartDateTime)); short; long);

shour := @Replace(@Text(@Hour(gStartDateTime)); short; long);

sminute := @Replace(@Text(@Minute(gStartDateTime)); short; long);

ssecond := @Replace(@Text(@Second(gStartDateTime)); short; long);

startDate := syear + smonth + sday;

startTime := shour + sminute + ssecond;

REM {終了年月日・時刻をyyyymmdd、hhmmss形式にフォーマット};

eyear := @Text(@Year(gEndDateTime));

emonth := @Replace(@Text(@Month(gEndDateTime)); short; long);

eday := @Replace(@Text(@Day(gEndDateTime)); short; long);

ehour := @Replace(@Text(@Hour(gEndDateTime)); short; long);

eminute := @Replace(@Text(@Minute(gEndDateTime)); short; long);

esecond := @Replace(@Text(@Second(gEndDateTime)); short; long);

endDate := eyear + emonth + eday;

endTime := ehour + eminute + esecond;

REM {SubjectフィールドをURLエンコード};

subject := @URLEncode ("Domino"; Subject);

REM {開始終了日時を作成};

REM {AppointmentTypeがAnniversary、All Day Eventは時間指定なしでリクエスト};

dates := @If(

AppointmentType="1" | AppointmentType="2" ;

startDate + "/" + endDate ;

startDate +"T" + startTime + "Z/" + endDate + "T" + endTime +"Z"

);

REM {リッチテキストのBodyフィールドをテキストに変換してURLエンコード};

details := @URLEncode("Domino"; @Trim(@Text(Body)));

REM {LocationフィールドをURLエンコード};

location := @URLEncode ("Domino"; @Text(Location));

REM {Google CalendarのベースとなるURL変数にセット};

REM {将来URLが変更したら、ここを修正する};

REM {イベントの公開属性を変えるには &icc=PUBLIC に変更(ここではPRIVATE)};

REM {スケジュールの空き状態を変えるには &trp=FALSE に変更(ここではBusy)};

gcalurl := "https://www.google.com/calendar/event?action=TEMPLATE&icc=PRIVATE&trp=TRUE";

REM {URLを組み立て};

url := gcalurl + "&text=" + subject + "&dates=" + dates + "&location=" + location + "&details=" + details;

REM {URLは720バイト以下で、URLエンコードが途中で切れないように調整};

accessurl := @LeftBack(@Left(url ;720);"%");

REM {@URLOpen()でHTTPSリクエストを作成};

@URLOpen(accessurl; 1);

@All;

ブラウザFirefoxを使っているので、このボタンから開いた画面の"Submit"ボタンを勝手に押してくれるようなGreasemonkeyスクリプトを書こうと思って、現在あれこれ格闘中です。

それができたら、最後の1アクションが不要になるのに!!!

shigeeshigee 2008/02/08 18:08 はじめまして。
最近転職した先がノーツで、外部カレンダーとの同期で悩んでいましたが、解決の糸口がみつかりました。感謝感謝。
ただね、わたしは1ユーザーなのでデザイナーが使えないのですね。なのでエージェントにしました。アクションボタンだと使い勝手が良いのですけど。

目指すは携帯 - Google - ノーツ の同期です。Googleからノーツ方向は無理なのかな。。。

furuyan_jpfuruyan_jp 2008/02/11 15:17 shigeesさん
コメントありがとうございます。
何人かの知人から直接、同じような問合せをもらったのですが、Notesって自分でツールバーのボタンを作ることができるので、僕はツールバーにボタンを作って上記のコードを貼り付けてます。
ツールバーを右クリックして[ツールバーの設定]を選んでください。既存のツールバーにボタンを追加する場合は[カスタマイズ]を選択、新規にツールバーを作る場合は[ツールバー]を選択して[新規ツールバー]をクリックしてツールバーを作成します。
新規で作った後は、既存のツールバーへのボタンの追加と同様に[カスタマイズ]として、ボタンを追加したいツールバーを選択してからボタンを追加して、コードを貼り付けます。

ちなみに僕も携帯・Notes・Googleの連携をさせたくてこのコードを作成しました。
かなり手間がかかりますが、やろうと思えばできます。

まず携帯のカレンダーに予定を作成したら、自分のNotesメール宛にカレンダーの予定データを添付ファイルとして送信します。
Notesでメールを受信したら添付ファイルを右クリックして[表示]−[すべて呼び出し]として受信ボックスを[F9]でリフレッシュすると、カレンダーからの一斉通知文書が表示されますので、その文書を開いて[Add to Calendar]ボタンを押すと、自分のNotesカレンダーのエントリーとして登録されます。
最後に登録されたカレンダーエントリーを選択して、作成したボタンからGoogle Calendarへ登録します。

もっと簡単にやるには、Gmailの表示を英語にしてメール作成画面でカレンダーのエントリーを作成することができるので、そこから携帯とNotesのアドレス宛にInvitationを送るって方法もあります。

僕は常に持ち歩いてる携帯を、情報のInputにしたかったのですが、GmailをInputにするのであればこっちのほうが簡単ですね。

トラックバック - http://d.hatena.ne.jp/furuyan_jp/20070403