gcalapi AuthSubでカレンダーリストを取得する

あけましておめでとうございます。あんまり正月とか関係なしに淡々と開発しております。
年末年始に外出すると混むんだもん。

で、メイドめーるでデフォルト以外のGoogleカレンダーの情報がとれない件。

googlecalendar.PNG
Googleカレンダーでは、こうやって複数のカレンダーをまとめて表示させることが出来るのですけど、メイドめーるがメールしてくれるのは一番上のものだけになっております。
なんでかというと、Googleカレンダーにアクセスするのに使っているgcalapiで、カレンダーリストを取得するAPIがみつからなかったからです。

正確に言うと、ユーザー名とパスワードを使ったらとれるのですけど、なぜかAuthSub認証の場合だけ実装されていないのです。
Googleのドキュメントを見たら、取得する方法があるみたいなので、コードを追加してみました。

module GoogleCalendar
class ServiceAuthSub
CALENDAR_LIST_PATH = "http://www.google.com/calendar/feeds/default/allcalendars/full"
# get the list of user's calendars and returns http response object
def calendar_list
logger.info("-- get_calendar_list_responce st --") if logger
auth unless @auth
uri = URI.parse(CALENDAR_LIST_PATH)
res = do_get(uri, {})
logger.info("-- get_calendar_list_responce en(#{res.message}) --") if logger
res
end
alias :calendars :calendar_list
end
end

これだけ実装してあげれば、あとは通常認証と同じコードが働くので、こんなふうにして複数のカレンダーを取ってくることが出来ます。

require 'gcalapi'
require 'googlecalendar/service_auth_sub'
require 'googlecalendar/calendar'
srv1 = GoogleCalendar::ServiceAuthSub.new(user.calendarToken)
cal_list1 = GoogleCalendar::Calendar.calendars(srv1)

出来ればこのコード、本家に取り込んでいただけるとみんな幸せになるように思うのですけど。連絡つくかな?

作ったツールの感想を見る方法まとめ

photo by Clover_1

twitterにメイドめーる(http://www.maidmail.jp/)に対する質問をつぶやいたら,30分後に開発者から返事が来た.
早すぎ!びっくり!
以前にもmixiでアイマスのMADについて日記を書いたら,作者の足跡がついたことがあったけど,どうやってキャッチしてるんだろ.
常に検索かけてる?
自動検索ツールとか使ってる?
(朝のリレー 2008-12-09

30分は偶然ですけど、自分の作ったツールについての感想やご意見は興味があるので、いくつか検索ツールをつかってウォッチしています。

ブログを検索するツール

いずれも、キーワードが登場したサイトについてのRSSを出力してくれます。
ツールによって拾ってくれるサイトの傾向が異なるので、全部RSSリーダーに入れておくと漏れがでなくていい感じです。
あえて一個にするなら、Yahoo!ブログ検索がわりと安定して言及を拾ってくれているように思います。

アクセス解析

Google Analyticsとか。
参照元サイトというのを見ると、リンクしていただいている人を発見することが出来ます。
RSSはとれないので、アクセス解析のついでに見るくらいですね。
あ、Macfanに掲載されてる!

そのほか

Twitter検索 : Search

twitterのつぶやきを検索できます。メイドめーる公開した日にユーザー登録できないトラブルに気づいたのはこの検索のおかげ。
はてなブックマーク
ブックマークコメントをRSSで見ることが出来ます。

mixiの日記

 一番普通の人の意見が出ていると思うので是非みたいのですけど、RSSで取る方法がない。
何か発表した翌日くらいに自分でキーワードを入れて調べるしかありません。SNSだからしょうがないのかなぁ。

名前大事。

 いずれのツールも、要するにキーワードで引っかかったものを見ているだけなので、なるだけユニークな名前であることがポイントになります。
メイドめーるが秘書メールでないのは、秘書メールというサービスはすでにたくさんあって、全然関係のないツールの感想とかも混じってしまうからです。
それまでGoogleで一件とか二件しか出なかったキーワードが突然メジャーになって、自分のツールについての話題で埋め尽くされるのを見るのが楽しいです!
メイドめーる – Google 検索
いいめも – Google 検索

駄目じゃん、というコメントで埋め尽くされる可能性だってあるわけですけどね。

[rails]自分のドメイン名をとるためにはrequest.domainがいいらしい

photo by  flyzipper
 rails上で自分のドメイン名をつかってナンヤカンヤしたい時というのがあって。

ENV[‘HOSTNAME’]

 これは論外っぽい。

[default] ENV
[default] :{“HOSTNAME”=>”xxxx.mogya.com”,

仮想ドメインの設定を無視してホスト名を返してくれます。HOST_NAMEという値ですから、当たり前か。

request.env:[‘SERVER_NAME’]

request.env:{“SERVER_NAME”=>”maidmail.jp”,

 ねらい通り、ドメイン名を返してくれます。ただ、このヘッダも、あとrequest.env[‘HTTP_HOST’]も、ちょっとしたことで簡単に偽装されてしまうので、迂闊につかえません。

request.domain

[default] request.domain:maidmail.jp

 こっちを見ると、request.env:[‘SERVER_NAME’]が偽装されてしまうような場面でも、正しいドメイン名がとれました。
ソースを見ると、HTTP_X_FORWARDED_HOSTというヘッダを使うみたいです。

# File vendor/rails/actionpack/lib/action_controller/request.rb
318: def domain(tld_length = 1) 319: return nil unless named_host?(host) 320: 321: host.split('.').last(1 + tld_length).join('.') 322: end 280: def host 281: raw_host_with_port.sub(/:\d+$/, '') 282: end 271: def raw_host_with_port 272: if forwarded = env["HTTP_X_FORWARDED_HOST"] 273: forwarded.split(/,\s?/).last 274: else 275: env['HTTP_HOST'] || env['SERVER_NAME'] || "#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}" 276: end 277: end

HTTP_X_FORWARDED_HOSTがとれなかった場合に限り、env[‘HTTP_HOST’]やenv[‘SERVER_NAME’]を見てくれるので、HTTP_X_FORWARDED_HOST非対応のサーバでも、request.domainを見ておけば悪いようにはしない実装になっているみたいです。

HTTP_X_FORWARDED_HOSTのうまい説明が見つけきれなかったのですが、これってどういう環境変数なのかなぁ?どれくらい信用のおける値なのでしょう?

[メイドめーる]時刻がとれるようになりました

calendar by iheartlinen

1. 時刻がとれるようになりました。

 これまで、メイドさんに予定をメールしても、日付しか拾ってくれなかったのですが、時刻もある程度拾ってくれるようになりました。
たとえば、「12月6日午後3時15分から午後4時30分まで、株主総会」というメールを送ると、
2008/12/06 15:15 ~ 2008/12/06 17:15の予定が登録されます。

#他にも各種書き方が読めたり読めなかったりすると思われます。
 「こういうフォーマットも読めるようになってほしい」等のご要望を聞かせていただけたら、ボクからもメタデータさんにお伝えするようにします。

2.メールのサブジェクトも見るようにしました。

 予定のタイトルが思ったように入らないことが多いので、取得に失敗した時はメールのサブジェクトを採用するようにしました。
これで多少マシになるんじゃないかと思うのですが、どうでしょう?

3.パスワードリセット機能がつきました。

 ログインに失敗した時、「パスワード忘れちゃった」のリンクをたどると、パスワードをリセットすることが出来ます。

お試しくださいませ☆

ちなみに、予定にあるけどまだ対応できていない機能としましては
・標準以外のカレンダーを見たい
・GoogleAppsへの対応
があります。がんばりまする。

萌えるRailsアプリの作り方

第31回 Ruby/Rails勉強会@関西で、メイドめーるについてお話しさせていただきました。

メイドめーる

View SlideShare presentation or Upload your own. (tags: ruby関西)

会場で教えていただいたこと。

rake statsで統計情報がとれる

+----------------------+-------+-------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers | 389 | 315 | 5 | 33 | 6 | 7 |
| Helpers | 36 | 34 | 0 | 2 | 0 | 15 |
| Models | 360 | 288 | 9 | 17 | 1 | 14 |
| Libraries | 37 | 32 | 0 | 2 | 0 | 14 |
| Integration tests | 0 | 0 | 0 | 0 | 0 | 0 |
| Functional tests | 159 | 126 | 6 | 24 | 4 | 3 |
| Unit tests | 173 | 144 | 6 | 7 | 1 | 18 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total | 1154 | 939 | 26 | 85 | 3 | 9 |
+----------------------+-------+-------+---------+---------+-----+-------+
Code LOC: 669 Test LOC: 270 Code to Test Ratio: 1:0.4

テスト少なすぎ、とスルドいつっこみをいただきました^^; 書かないとね。

あと、プレゼンの最後にもつけてありますが、今日話に出てきたサイト一覧です。

Railsでのメール処理に関するサイト

GCalAPIに関するサイト

GoogleカレンダーAPIに関するサイト

Mextractrに関するサイト

GoogleAuthSubに関するサイト

[mextractr]gemでインストールできるようになりました。

先日公開したmextractr_webapi.rbが、gem経由でインストールできるようになりました。

こんな具合にして使うことが出来ます。

[daisuke@snares ~]$ sudo gem install mextractr_webapi
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed mextractr_webapi-0.0.1
1 gem installed
[daisuke@snares /var/maidmail]$ script/server
>> require "mextractr_webapi"
>> mextractr = MextractrWebApi.new(API_KEY)
>> res = mextractr.parse("11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 ")
>> pp res
{"id"=>"20081202_0001",
"where"=>
[{"georss:point"=>nil, "valueString"=>"京都"},
{"georss:point"=>nil, "valueString"=>"京都"}],
"what"=>[{"valueString"=>"オフ会"}],
"when"=>[{"valueString"=>"11/29(土)", "startTime"=>"2008-11-29"}],
"updated"=>"2008-12-02T12:16:50+09:00"
"content"=>
"11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 ",
"response"=>
"\n\n  Mextractr WebAPI results\n  2008-12-02T12:16:50+09:00\n  \n    Mextractr\n  \n  20081202_0001\n  \n    \n    20081202_0001\n    extracted event metadata\n    \n      Mextractr WebAPI\n    \n    2008-12-02T12:16:50+09:00\n    11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 \n    \n    \n    \n    \n  \n\n",
}

enjoy!

波線を含むメールが文字化けする問題への対処

 メイドめーるでは日本語のメールを送信するために、
ヽ( ・∀・)ノくまくまー(07-31[長年日記])で書いていただいている、Iso2022jpMailerを使っています。
クラスを継承するだけでつかえるとてもいいアイデアだったのですが、たった一つ問題が。

IMGP8827.JPG

「~」が文字化けするのです。普通のアプリケーションだったら、まあ横棒でいいか、とか言えるし、実際メイドめーるも今日までそうやってごまかしてきたのですけど。萌え萌えなメイドさんがメールをくれるアプリケーションにおいて「~」がつかえないと言うことは、「おはようございます~」がつかえないことになってしまいます。
「おはようございますー」と「おはようございます~」は断じて違うのです!

とまあそんなわけで、技術的に追求した結果、一応「~」が出せるようになりましたのでご報告です。

IMGP8828.JPG

やり方としては、Iso2022jpMailer の

@mail.body = NKF::nkf('-j', @mail.body)

の部分を

@mail.body = NKF::nkf('-Wxm0 --oc=ISO-2022-JP-1', @mail.body)

に置き換えます。
ついでに、タイトルとかに「~」がはいることもあるだろうから、

text = NKF.nkf('-j -m0', text)

も、

text = NKF.nkf('-Wxm0 --oc=ISO-2022-JP-1', text)

にしちゃいました。

技術的な話

正直に言うと、なんでこれで化けないのか、最終的な理由は理解できていません。
ただ、あれこれやっているうちに、化ける時と化けない時があって、比較するとこうなっていることが分りました。

wave_on_jis.PNG

上がうまくいく場合で、下が駄目な場合です。日本語メールなのでJISコードでエンコードしてあります。
OKな時は1B 24 42で始まっていて、駄目な時は1B 24 48で始まる…、つまり、JIS X 0208-1983でエンコードしてあればOKで、JIS X 0212-1990だと駄目なことが分ります。
NKFのコマンド詳細を見ながら、irbでいろいろやってみると。

>> NKF::nkf('-jWxm0', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,44,22,37,1b,28,42,
=> nil
>>NKF::nkf('-Wxm0 --oc=ISO-2022-JP', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,44,22,37,1b,28,42,
=> nil
>> NKF::nkf('-Wxm0 --oc=ISO-2022-JP-1', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,42,21,41,1b,28,42,
=> nil
>> NKF::nkf('-Wxm0 --oc=ISO-2022-JP-3', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,50,28,37,1b,28,42,
=> nil

–oc=ISO-2022-JP-1の時だけ、ねらい通りの変換をしてくれるようです。ということで、Iso2022jpMailerにも、同じ引数を渡してあげると、「~」が出るようになった次第。
「ISO-2022-JP-1」って、JIS X 0212に対応させるための引数で。むしろ逆のような気がするし、なんでISO-2022-JP-3で駄目なのかも謎です。

[ruby]mextractor web apiのライブラリ

Mextractrに関する注目が集まっているので、自分が使っているライブラリを公開します。

mextractr_webapi.rb

#RubyForgeのプロジェクトは今申請中なので、gemはちょっとお待ちくださいませ。

使い方としては、APIキーを取得して、

$ script/console
Loading development environment (Rails 2.0.2)
>> require "mextractr_webapi"
>> mextractr = MextractrWebApi.new(MEXTRACTR_KEY)
>> res = mextractr.parse("11/27(木)、京都市中京区のはてな京都オフィスでShibuya Perl Mongersテクニカルトークのパブリックビューイングが開催されます。")
>> pp res
{"id"=>"20081127_0001",
"updated"=>"2008-11-27T10:05:38+09:00"
"response"=>
"\n\n  Mextractr WebAPI results\n  2008-11-27T10:05:38+09:00\n  \n    Mextractr\n  \n  20081127_0001\n  \n    \n    20081127_0001\n    extracted event metadata\n    \n      Mextractr WebAPI\n    \n    2008-11-27T10:05:38+09:00\n    11/27(木)、京都市中京区のはてな京都オフィスでShibuya Perl Mongersテクニカルトークのパブリックビューイングが開催されます。\n    \n    \n    \n  \n\n",
"content"=>
"11/27(木)、京都市中京区のはてな京都オフィスでShibuya Perl Mongersテクニカルトークのパブリックビューイングが開催されます。",
"where"=>
[{"georss:point"=>nil, "valueString"=>"木)、京都市中京区"},
{"georss:point"=>nil, "valueString"=>"京都"}],
"when"=>[{"valueString"=>"11/27(木)", "startTime"=>"2008-11-27"}],
}

という具合です。
res[‘when’][0][‘startTime’]とか、res[‘where’][0][‘valueString’]という具合で各値を取り出すことが出来ます。

あと、MextractrWebApi.new(MEXTRACTR_KEY)の二つ目の引数にloggerを渡すと、取得してきたatomの内容とかを見ることが出来るので、挙動がおかしい時に犯人を突き止める一助になります。

[メイドめーる]メタデータ賞をいただきました

Drecom Award on rails 2008において、メイドめーるメタデータ賞を受賞しました。

もともとメタデータさんのMextractr WebAPIを見て作り始めたアプリケーションなので、もしかしてとれるかなぁ、と思っていたのですが、その通りになるとやっぱり嬉しいです。

メタデータの野村さんがブログにメッセージを書いてくださっています。

[mashup] メイドめーる その2 【表彰式!】 [mextractr] – 野村直之の日記: IT – とくにメタデータ – , 音楽
3分間ほど講評させていただいた中で、
・エンタープライズシステムの近未来を見せてくれている(!)
など申し上げました。これは、メイドめーるに対する正直な感想です

えええぇ~っ!?
そんな大それたアプリケーションではないのですけどね(汗)

[css]idとclassの覚え方

CSSを書いていると、「id要素の頭はシャープだっけドットだっけ」というのが思い出せなくてときどき検索する羽目に陥ります。
不必要に物事暗記しない主義なのですが、さすがにこれは効率が悪い。

  • idは、ユニークさを表すidだから、順番を表す#がつく。
  • classは、プログラミング言語のclassと一緒だから、this.getValueみたいにドットがつく。

これで覚えられるかな?なんか他にいい方法があったら教えてください。