WidgetのAmazon署名対応完了!!

ようやく自分が使っていたAmazon APIの署名対応をすべて完了。

Amazon APIは国によって別々のドメインで提供しているんですが、調子にのってWidgetの国際化対応でロケールにあわせて適切なドメインに投げてたから・・・

  • (de) Erinnerung: Amazon.de Product Advertising API-Authentifizierung
  • (co.jp) 【重要・あと30日です】Product Advertising API の署名認証利用開始のお願い
  • (co.uk) Product Advertising API Reminder
  • (com) Product Advertising API Reminder

もう、わかってるちゅーねん。って思わずツッこんでしまったくらいメールきた。(エセ関西人の性)。でもこうやって見るとフランス人には使われていないようだ。

正直のところ、Amazonにはあまり怒っていなくて、またもや怒りの矛先はxmlのencoding属性がないと日本語が文字化けするどう考えてもフォローできないYahoo Widgetのバグに向いてしまった。だからレスポンスのHTTP HeaderのContent-Typeみろって。

例のごとくAmazonにクエリストリングなしでパラメータをPOSTするとレスポンスのxmlタグにencoding=”UTF-8″が入って結果としてYahoo Widgetで日本語が化けないという技を利用。

Javascript内に秘密鍵を入れたくないのでGoogle App Engineで署名つけてリダイレクトしていたのだがPOSTのリダイレクトはしんどそうなのでApp EngineでPOSTを受け付けた場合は署名付きパラメータを文字列で返して再度Widget側でAmazonへリクエストをPOSTするようにした。

こんな面倒なことはおそらくYahoo WidgetだけなのでGETで受けたときはそのまま署名付きURLでリダイレクトする仕様。

しばらく続いていたサステイニング作業がようやく終わり。最近はブログもつぶやきもせず、ただ疲弊しただけだったがそろそろ新サービスを考えたい。Google Developer Phoneをまだ開けていないので開けよう。

Yahoo Widgetの再開と文字化け問題

GW中はいろいろたまってた調べごとをやっていて何か面白いものを作ったりはできなかった。休みの間はブログもtwitterも遮断してたのでぼちぼちと連休中の出来事なども思い出して書いていこう。

まずは、Yahoo! Widgetの開発を再開したこと。

My Outlook Todayは二年間も開発を放置していたらしい。つーか、Outook使ってた会社を辞めたのがそのあたりだからしょうがない。ただ、それ以上に別のWidgetがアメリカの方で公開されず何回かサポートに連絡したのに調査するだけでその後何も返事がないというやつらのやり方に頭にきてもうYahoo! Widgetいいよ。ってなったのがでかい。

でもそろそろ頭も冷えてきたので再開したよ。

ってのはうそで。Google Calendarを使っていてiPod Touchと同期してたりしたんだけどやっぱりパソコンでも見たいよねーってことでMy Outlook TodayならぬMy Google CalendarをYahoo! Widgetでつくりました!
http://widgets.yahoo.co.jp/gallery/detail.html?wid=10509
日本は本日公開された模様。本家USのほうはまだ公開されない。もう一週間たつのに。あいつら仕事しろよ。

そうだ思い出した。

以前、Yahoo WidgetでXMLHttpRequestのレスポンスが突然文字化けしたことがあったんだけど、My Google Calendarでも同じ問題に遭遇した。

というか、XMLHttpRequestのレスポンスはxmlタグのencode=”utf-8″がないとISO-8859-1と解釈されるっぽいのよ。で、Yahoo Widgetの世界ではutf-8でwidgetを書いてるので、エンジンがISO-8859-1からutf-8に文字コードを変換してくれるのよ。この親切設計(大きなお世話)。

つまり、utf-8のレスポンスなのに、ISO-8859-1からutf-8の変換が入るから文字化けするわけさ。

で、回避方法のひとつとして、XMLHttpReuqestでリクエストヘッダにAccept-Charsetを仕込む方法がforumで紹介されてた。

req.setRequestHeader(“Accept-Charset”,”ISO-8859-1,utf-8;q=0.7,*;q=0.7″);
こんな感じでutf-8でもらえるのに、わざわざISO-8859-1を要求してISO-8859-1->utf-8の変換をいれると・・・・
ただこの回避策は当然サーバサイドがISO-8859-1を返すようになってないとutf-8で返ってくるので解決できない。Google様はそうだった。

Google CalendarはGData APIでjsonで取得することもできるんだけど化け化けなんですよ。どうみても「xmlでencode=”utf-8″がある」以外は化けるのよ。つまりjsonデータはISO-8859-1で解釈される、さすがアメリカ人やることがえぐい。

で、「デフォルトをutf-8にすればいいのかもしれないがそれだとISO-8859-1を期待しているプログラムで問題がおきるようになる。」みたいなことを言っていて。まぁ確かにデフォルトをどっちにおくかってのは難しい問題なんだけど。。。

その前にレスポンスヘッダのContent-Typeを見ろよ!
Google様はちゃんと「Content-Type:application/json; charset=UTF-8」って返してくれてるよ。なんでISO-8859-1->utf8の変換をする必要がある?これはどう考えてもバグでしょう。

発言者がYahooの人か知らないけど、Yahoo Widget Engineの開発者って本当に大丈夫か?ってすげー心配になった。

で、結局My Google Calendarではjsonをあきらめてxmlで取得してDOM呼んで頑張った。。。

人様のYahoo Widgetのソースコードを読む方法

Widget、というかjavascript、というかスクリプト言語・・・もとい。Widgetの良いところの一つは、人様のコードを簡単に参考にできるところにあると思う。正直Widgetつくるときはまず似たようなwidgetを探して読むことから始めるw
Yahoo! Widgetの.widgetファイルは.zipファイルかWidgetConverterでflat化されたファイルかのいずれか。

なのでまずは拡張子.widgetを.zipに変更して解凍を試みる。.zipファイルであればそのまま解凍できてソースコードが読める。

zip解凍できない場合はflatファイルの可能性があり、この場合はWidgetConverterでunflat化する。

Yahoo! Widgetファイルのunlaft化
1) WidgetConveterのダウンロード
http://widgets.yahoo.co.jp/workshop/からコマンドラインツールのWidgetConverterをダウンロード。解凍してConverter.exeをMy Widgetsに置いてしまう。(Windowsの場合)
2) 日本語ファイル名の変更
Yahoo! JapanのYahoo Widget Gallaryでは日本語タイトルのwidgetはそのまま日本語タイトル.widgetの名前でMy Widgetsにインストールされる。しかし、WidgetConveterはうまく日本語名を受け付けてくれないようなので、日本語.widgetのファイルがあったらnihongo.widgetなどのように英数字だけのファイル名にリネームしておく。

3) unlfatを実行
たとえばfoo.widgetというwidgetをfooディレクトリに解凍する場合。

Windows + Rボタンでcmdとうち、コマンドラインを起動して、
(Vista)

cd "Documents\My Widgets"
converter -unflat "foo.widget" -o "%CD%\foo"

(XP)

cd "My Documents\My Widgets"
converter -unflat "foo.widget" -o "%CD%\foo"

と実行する。

(fooのところはファイル名に合わせて適宜置き換えるべし)
#人様のソースコードはだだ参考にするのは良いですが、ファイルそのものやコードをコピーして使う場合はライセンスや作者様に確認するなどしましょう。

Widgetのアーキテクチャーを考えてみる

ちょくちょくMy Outlook Todayの質問が外人さんからくるんだけど、開発を2年も放置している。

outook使ってた会社やめたってのがでかいけど、一応Officeのライセンスもってたけどもうoutookすらインストールしてない状態だし、Microsoft OfficeのバージョンアップせずにOpenOffice使ってる。。。

商用ならまだしも、趣味のプログラミングで自分が使ってないものをサポートするのはしんどい。

ただそれはそれはそれで使ってる人に失礼だと思うので、いま使っているGoogle CalendarでMy Google Todayってのを作ってうまくMy Outlook Todayも保守するってのが落としどころじゃなかろうか。予定とってくるところと、新規予定の作成だけ抽象化すればあとは共通化できるだろうと安易に考えてる。

しかし、久しぶりにWidgetのコードみたら自分のコードがあまりにひどくて心が折れそうになる。widgetにしてもwebアプリにしてもそうなんだけど、javascriptレイヤでUIも書いてしまうから、アプリレイヤ(ビジネスロジック)とUIレイヤ(プレゼンテーション)がごっちゃになってしまう。これじゃー再利用しづらい。

そんなわけでこんな風に作ろうと心に決めた。


widgetにはajaxでデータをとってきて表示するたぐいのものが多い。なのでなんらかのAjaxフレームワークを使いたい。実はいままでprototype.jsを使っていたのだけど、Ext JS CoreがMITライセンスになったのを受けてこれを使ってみることにした。

WALってのはもともと作ろうとしていたWidget Abstract LayerというYahoo WidgetとかSidebar Gadgetとかを抽象化するAdapter。これによってFoundationとApplicaitonレイヤのコードを再利用可能にする。

UIはwidgetによってアプローチが変わってくるのでこの部分は書き直しになるのは仕方がない。Yahoo WidgetやGoogle Desktop GadgetはUI層は独自のコントロールを持っているので独自の記述が必要になるし、Sidebar GadgetはIEなのでEXT JSとかYUIとかjqueryでwebアプリと同じように描画することもできる。このあたりの選択も自由だ。

UI層のコードを減らすためにはfuncationableなものはなるべくApplicationレイヤにねじこめばいい。一番シンプルなのはUI層にはupdateという描画更新の関数しかなくて、設定の変更やデータの変更のイベントをうけてupdateを呼ぶだけってのが良い。あとはApplication層でデータをとってきてUi層からとれるようにするだけでいい。そうすればUI層が書き直しになるといってもそれほど苦にならないはずだ。

new Text();… と書くのかdocument.createElement(“p”);…と書くだけの違いだけだというレベルにまで持って行けば移植しやすくなる。

Widget/Gadget Feedback Aggregator修正

Yahoo! Widgetのコメントをかき集めてfeedにして配信するサービス Widget/Gadget Feedback Aggregator をようやく修正しました。

もうちょっと真面目にWidgetへのコメントをチェックするようにします。。。

昨年末にYahoo Widget(yahoo.com)のリニューアルで置き去りにされていたのをようやく対応しました。USの方はauthor widgetsがFEEDになってるのでwidgetをかき集めるのが少し楽になりましたが、肝心のwidgetのページはデザインが複雑になってコメントをスクレイピングするのが大変でした。

しかし、Google Readerがrss2.0のpubDateを無視してくれる。Dublin Coreとかいろいろあがいてみたが解決できず。。。

SongWidget 0.3.2をリリースしました(Yahoo! WidgetにおけるAmazonの文字化け)

ごめんなさい、ごめんなさい。半年ほったらかしにしていたSongWidgetのバグ修正版をリリースしました。(もっと放置してるwidgetもあるのは内緒)
http://makotokw.com/ja/portfolio/yahoowidget/songwidget
COMを同梱してwinamp対応とか考えてたんですが、影響がでかそうなので0.3.x系とtrunkに分岐して、とりあえず今起きてる不具合を修正して0.3.2としてリリースです。

でかい不具合としてAmazonのレスポンスが文字化けするという問題を修正しました。どうも、Yahoo Widget Engine側の修正の影響で発生するようになったようです。

結局、根本原因を調べるのはあきらめたんですが、調べてわかったことを書きます。

Yahoo! WidgetにおけるAWS(Amazon Web Service)文字化け問題
要因1:AWSにおいてResponseGroupをつけるとxml属性のencodingが省略される
http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=0F49XFHPQYWX91XK4K82&Operation=ItemLookup&ItemId=B0000AKI8I&ResponseGroup=Large
ただし、HTTPのレスポンスヘッダには
Content-Type:text/xml;charset=UTF-8
が入ってる。

ResponseGroupがないと何故かencoding属性は返ってくる。

http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=0F49XFHPQYWX91XK4K82&Operation=ItemLookup&ItemId=B0000AKI8I
&Versionで古いのを指定してもだめ。というかAmazonが突然仕様を返るとは考えにくい。

要因2:encodingが省略されるとXMLHttpRequestのresponseText/responseXMLが文字化けする
encodingが省略されるときにどの文字コードで処理しようとしてるのかはわからない。。。文字化けしたbyteコードを調べればわかったかもしれないが、どの文字コードで処理してるのではなくどうしたら文字化けしないのかばかり調べてたから。。。

要因3:SongWidetはレビューとかを取るためにReponseGroupを指定する
ResponseGroupを指定しなければencoding属性がついて結果として文字化けしないんだけど、SongWidgetではAmazonのレビューとかを取得するためにResponseGroupを省略するという選択肢がない。。。

最終的な対応
とりあえずforumになんかないかと思って調べてみたものの有用な情報は見つからなかった。こういう問題のときの英語圏のforumほど切ないものはないよ。。。

仕方がないので今度は日本のYahoo! WidgetでAmazon関連のwidgetを探してみたところ、文字化けを修正していた人がいたのでそれを参考にさせてもらった。

参考にしたWidget:
今日の新刊情報
# いぬさんありがとうございました!
結論から言うと、GETではなくPOSTを使い、リクエストをpostBodyに突っ込めばとencodingが返ってきて文字化けしない。

SongWidgetの場合、prototype.jsを経由しているの参考にならないが・・・対応コード

    var ajax = new Ajax.Request(url, {
method:'post',
postBody: postBody,
onComplete:this.onAjaxFetchContentComplete.bind(this),
onFailure:this.onAjaxFetchContentFailure.bind(this),
}
);

タイミング的にはYWE(Yahoo Widget Engine) 4.5で挙動が変わったと考えるのが自然なんだけど・・・確かYahoo.comで4.5がリリースされたときに動作確認した気がするんだけど・・・(YWEはなんか知らないがいつも日本はUSからかなり遅れてリリースされる)、それは気のせいなのか、日本のYWEだけ起きるのか今となってはわからないし、もうどっちでもいい。それが分かったところでYWEを直せないからさー。

続)Yahoo Widgetsから放置プレイを食らっていることについて

一ヶ月以上経過、前回のYahoo!からのメールの返事も一週間以上来ない。

さて、いい加減「もうお前んとこでWidgetつくんの辞める。」メールをyahoo.comに投げようかと思ったりもするのですが、そうしたところでお互いにマイナスでしかないので踏みとどまっています。

この憤りはエレドラにぶつけるしかないのか。

Yahoo Widgetsから放置プレイを食らっていることについて

USのYahoo Widgetsから放置プレイを食らっています。

2月の終わりにwidgetを投稿しました。セキュリティ問題で公開停止を食らっていたのでそれを修正したのですが、一行に公開されません。過去の経験上、新規だろうが、バージョンアップだろうが数日で公開されていました。また問題があって公開できない時でも、ここ直してね。という返事がちゃんと来たものです。

ところが今回はなかなか投稿したwidgetが表示されませんし、修正依頼も来ません。

そこで2週間たってからクレームのメールを出しました。

返事はすぐに来て、「たくさんのwidgetsがあるので投稿順に順番にチェックしてます、まってくださいね。」という内容でした。

なんかtemplateくさい回答だったのですが、とりあえず黙って1週間待ちました。

3週間経ちました。まだ表示されません。順番待ちとはいえwidgetの公開に3週間かかるというのはサービスとして機能しているとは言い難いです。バグがあって直しても3週間待たされるとしたら滅多なことじゃバージョンアップできなくなります。

で、2度目のクレーム。今度はtemplateで返されないように注意して、「3週間経ちましたが、まだ公開されません。過去に投稿したときはいつも数日で公開されていました。たくさんwidgetのチェックがあって忙しいのは理解しています。しかしながら、今はチェックに3週間もかかるのでしょうか。私のwidgetに問題があるのであればお知らせください。」
すぐに回答が来て、「submitしたファイル名を教えてください。ファイル名でログを追ってみます」とのこと。すぐにこちらもファイル名を折り返す。またすぐに回答がきて「すぐに調べて回答します」と来ました。

が、それからさらに一週間が経とうとしていて、とうとう4週間。つまりほぼ一ヶ月放置プレイです。これは「token流メール送信奥義・返事が来ないので全く同じ内容のメールをそのまま送る」を応用してもう一回submitした方が良いのでしょうか・・・

はてなTrends 1.4.0リリースしますた

こんばんみ。起きて時計に目をやったら13時を過ぎていて、おかしいなと思って別の時計を見たらそれも13時を過ぎていて、今日って平日だっけ?としばし考えた結果、その状態で準備をして会社に行く気がおきなかったので会社を休んで二度寝に走ったkwです。

ま、昨日会社を出たのが朝の3時で、寝たのは確か朝の5時だったので許してください。

さて久しぶりにYahoo! Widgetの開発を再開しました。前回更新が4月だったので半年近く放置してました。なんかいろいろ英語のメールが来てたのですが全部無視してたらいつの間にか自分のWidgetがダウンロードできなくなってました。

Yahoo! Widgetのglobal functionにはopenURLという関数があり、引数にurlを渡してあげるとデフォルトブラウザで開いてくれます。はてなTrendsでははてなのRSSを読み込んでキーワードごとにリンクを張っていたのですが、リンクをクリックされたときにこのopenURLを呼び出していました。

外部のサイトのurlを開くということは攻撃対象になるおそれがあり外部から取得したurlはサニタイズすべしというおふれが出ていました。というわけでサニタイズしました。

tracにプロジェクトページを作成したのでリンクをはっときますhttp://makotokw.com/ja/portfolio/yahoowidget/hatenatrends
Yahoo! Widget Gallaryにも投稿済みなので近日中にアップされるでしょう。

ちなみに追加機能はないのですでにご利用な方が無理にバージョンをあげる必要はありません。はてなから変なurlを含んだRSSが配信されるとは思えませんし・・・はてなを偽装してわざわざはてなTrendsを攻撃してくるような特異な人もいないかと・・・ですが今回下回りのライブラリを全部書き直したので個人的には試していただきたいです。

今後Vista GadgetやGoogle Gadget、あるいはAIR、Silverlightに展開できるようにWidget Engineに依存しないで開発するためのWidget Abstact Layerという階層をでっちあげていたのですが、名ばかりで実際にはこの上の階層でも普通にYahoo! Widgetの関数を直接読んでいました。。。

今回Yahoo! Widgetに機能があるのにわざわざprototype.jsを導入して全く同じ関数をwapperとして作成したりしています。一応UI部分だけ作り替えれば他のWidgetにも展開可能になった・・・と思っています。まだやってないので何ともいえませんが。。。とりあえずVista GadgetのはてなTrendsも作ろうかと思っています。

その前にMy OUtlook TodayとSongWidgetの開発再開が先ですが。。。

Widget/Gadget Feedback Aggregatorをリリース

このところめっきり、Yahoo! Widgetの更新をさぼっています。なかなかコメントをいただいてもそれを読んでいる時間がありません。すみません。

そもそも自分のWidgetにもらったコメントを作者が見るというのはなかなか敷居が高いものであると前から考えています。何故かというと
1) よほどの人気のWidget/Gadgetでない限り毎日コメントはこない
-> コメントが不定期だと毎日チェックするモチベーションを失う
-> 定期的にチェックする習慣をつければ良いが、サンデープログラマには高い要求(!?)
2) コメントはWidget/Gadgetごとにつく
-> 複数のWidgetをつくっているとそれだけの数のページをチェックしないといけない
-> Yahoo!のように地域によってサービスが異なると、Widgetの数x地域数分するはめになる
3) コメントに対する通知機構がない
-> コメントがあったら作者にメールされるような仕組みが何故かない
-> そのため作者が能動的に各ページをチェックしにいかないといけない
上記理由が重なってコメントをチェックできなくなるわけですね。

(たんなる言い訳ですが)
言い訳ばかりしていてもしょうがないので、コメントを集めてRSSにするコードを書くことにしました。最初は各WidgetのページのURLをハードコーディングして集めていたのですが、Yahoo!の場合は作者のWidget一覧ページがあるので、そこから各Widgetのページを収集するとWidgetが増えてもコードを書き換えなくて済むと思い変更しました。

そうなると作者のIDを指定する部分を変更すれば当然他のYahoo! Widgetestな皆さんにも使えるじゃないかと気がつき、IDをパラメータにしてみました。

というわけで
Widget/Gadget Feedback Aggregator
http://labs.makotokw.com/wgfa/
というサービスでリリースします。

まだまだ問題はありますが、順次対応していきます。