Google に買われつつも微妙に奮わない Jaiku の API を使ってケータイ版を作ってみた.
Jaiku のケータイ版といえば既に m.jaiku.com が official で提供されているが,例によって Cookie が使えない端末では (当然) ログインもできず,割と昔から Cookie に対応している au に至っても "domain=.jaiku.com" を解釈できないのか,サブドメインが異なるユーザページでセッションが切れてしまいやはり使いものにならない.
まぁ,こういうのは往々にして Cookie に対応していない端末の方が悪いわけで,小賢しい小手先の対策に労力を割くのは本質的ではないし,何よりセッション回りでの「制限回避」は安全性を犠牲にしかねない.
しかし自分の au 端末でも Jaiku したいという矛盾と戦いつつ,まぁ,その,なんだ.とりあえず作ってしまった.あはは.
特徴
- 日本のケータイ特有の絵文字を使ってアイコンを表示・投稿できる (m.jaiku.com にはない feature)
- API 提供されていないコメント投稿機能がある (Jaiku API 使いには公然っぽいけど)
- contacts の add/remove が可能 (6/17 追加)
利用手順
- Yaiku を利用する Jaiku ユーザ名を決める
- Jaiku ユーザ用の API Key を Jaiku から取得する
- Yaiku のトップページに PC でアクセスして,ユーザ名と API Key を入力してケータイ用 URL を得る (要 javascript)
- URL にケータイでアクセスし,ブックマークする
- 以降はブックマーク経由でアクセスする
Yaiku では Jaiku の API を利用しているので,ユーザ毎に提供される API Key が必要となる.事前に Jaiku にログインした状態で http://api.jaiku.com/key から API Key を取得しておく.
続いて http://phoneme.homelinux.org/yaiku/ にアクセスして,フォームにユーザ名と API Key を入力すると,しばらくした後にそのユーザ専用の Yaiku URL が生成・表示される.
得られた URL でケータイからアクセスできる.簡単 ! (でもない)
諸注意
- Yaiku が取得した username と API Key は *.jaiku.com への API リクエストのために用いられる.
- API 応答以外 (HTML 内) の情報を取得するために用いる場合もある
- API Key はサーバ内のデータベースに暗号化して保存される (管理者が casual に閲覧することはない)
Yaiku URL は自分だけのものなので慎重に管理されたい.これが盗まれてしまうと他人が Yaiku 上で貴方に成り代わって発言できてしまう (場合によってはそれ以上の操作が可能になる可能性がある).これが,前述の「制限回避」による避けられない代償となるのでリスクを理解した上で利用されたい.
- Yaiku 上で可能な全ての操作を行われる
- URL から API Key を得ることはできない
- URL から Jaiku のパスワードを得ることはできない (そもそも Yaiku は Jaiku のパスワードを取得していない)
Yaiku URL は生成される度に異なり,古い URL は都度破棄されるので,現在の URL に危険を感じた場合は URL を再取得して頂きたい.
また,ケータイからアクセスして,設定メニューから「Yaiku URL を無効にする」にチェックを入れて "Logout" することでサーバ上からユーザ情報を完全に削除できる (現時点では未実装 (えー
※ 6/12 追記 - Logout を実装した
所感
Jaiku の API がひどい.使って貰おうという気が全く感じられない.これじゃ誰もアプリ作らないし流行るはずもないと痛感する.
Twitter の API ドキュメント と Jaiku のそれを見比べると泣けてくる.だいたい devku.org って何だよ.これ本当に official なのか?
ドキュメント通りに組んでも投稿できないし,コメント投稿 API は見当たらないし overview も取得できないし (API 見つけたけど),ユーザ情報取得したら friends がダラダラくっついて来るし,あーもう.
Jaiku ちゃんとしろ!!
その他
fixdap でタスク管理をしているので,意見・要望等はこちらからどうぞ.
みんなもっと Jaiku やるといいよ!!
よく分かってないけど一応メモ.
環境:
- AquaSKK-3.6
- CarbonEmacs-Tiger-20080120 (バイナリパッケージ版)
問題:
- C-j の入力が AquaSkk に食われてしまい,C-q C-j 等が効かなくて不便.
- (setq mac-pass-control-to-system nil) とすると一応 C-j を Emacs に渡せるが,今度は AquaSkk による変換中の C-g や C-h まで Emacs に食われてしまい使いものにならない :-(
- ddskk とやらを使えば (setq mac-pass-control-to-system nil) で AquaSkk を完全にスルーして上記の問題を解決できる? ようだが要コンパイルとか困る (ヘタレ).
そもそも自分は native な SKK 使いではないので入力モードの切り替えは Cmd + SPC で十分なのだから,単に AquaSkk の C-j だけを殺せればそれで事足りるはず.カスタマイズ方法を調べてみた.
というわけで皆がやっている通り ~/Library/AquaSkk/config を用意してみたが,単に無効にすることはできないようで,kakutei-key "" などと記述しても意図通りの挙動にならない.ではどこか別のキーに割り当てれば良いのだが,できるだけ他に影響のないキーにしたい.で,元々 toggle-input-method がバインドされていた C-¥ に (何となく) 割り当ててみた.何となくというだけあって,何か効いていないような感じだ (今まで通り toggle してしまう) が,とりあえず C-j は Emacs に渡るようになり,変換中の C-h 等も問題ないのでこれで良しとしよう.
toggle-kana-key "q"
toggle-katakana-key "¥C-q"
-kana-mode-key "¥C-j"
+kana-mode-key "¥C-¥¥"
latin-mode-key "l"
jisx0208-latin-mode-key "L"
前回の続き.
これでいけた.
class Proxy:
def __init__(self, obj):
self.__dict__['_obj'] = objdef __getattr__(self, name):
return getattr(self._obj, name)def __setattr__(self, name, value):
setattr(self._obj, name, value)
a = Proxy(10)
str(a) #=> '10'
repr(a) #=> '10'
a + 3 #=> 13
long(a) #=> 10Lb = Proxy([])
b.append(10)
b.append(20)
b.pop() #=> 20
repr(b) #=> '[10]'
len(b) #=> 1class A(object):
def __len__(self):
return 3
c = Proxy(A())
len(c) #=> 3
Proxy(10) + 3 とかも効くのは凄い.
というか 6.5 章でズバリ解説されていた (死亡).
古い形式の class って推奨していいのかなー.
べ,別に GAE やら何とかのために Python やってるんじゃないんだからね!! ///
Python クックブック 9.1 章 (weaving) を試していて困った/疑問を持った話.
とりあえず 9.1 章のような継承 (name-mangling) は考えずに,再現する最小のコードをば.
class Proxy(object):
def __init__(self, obj):
object.__setattr__(self, 'obj', obj)def __getattribute__(self, name):
return object.__getattribute__(self, 'obj').__getattribute__(name)
すると,こんな感じで動く.
a = Proxy(10)
str(a) #=> '<__main__.Proxy object at 0x677d0>'
repr(a) #=> '<__main__.Proxy object at 0x677d0>'
a.__str__() #=> '10'
a.__repr__() #=> '10'
ううむ,若干期待と異なる挙動を見せる (全て '10' が返って欲しい).
更に.
b = Proxy([])
b.append(10)
b.pop() #=> 10
repr(b) #=> '<__main__.Proxy object at 0x67910>'
b.__repr__() #=> '[]'
len(b) #=> TypeError: object of type 'Proxy' has no len()
b.__len__() #-> 0
hasattr(b, '__len__') #=> True
うは,__len__ がある (見える) のに len 使えないのかー><
別に,組み込みオブジェクトを使ったからというわけではなく,通常のオブジェクトを使っても同じ挙動を見せる.
class A(object):
def __len__(self):
return 3c = A()
len(c) #=> 3d = Proxy(c)
len(d) #=> TypeError: object of type 'Proxy' has no len()
d.__len__() #=> 3
hasattr(d, '__len__') #=> True
単に __len__ の有無を見ているわけじゃなさそうだなぁ.
ちなみに,9.1 章に載っている inspect を用いたコードだと,組み込みオジェクトの殆どのメソッドを ismethod で inspect できずに b.append すらも失敗する.
これだったら普通に SynchronizeList とか欲しいなぁ.
IBM PC/AT 由来のキーボード (以下「PC キーボード」) には大抵 "Z" と "X" の下側に ALT キーが付いていて,装飾キーの一つとして機能する.Windows では ALT + F4 や CTRL + ALT + DEL を使わない日は無いし,メニューバーへのアクセスにも使えるので個人的には大変重宝している.
端末エミュレータや Emacs 系のアプリケーションでは ALT キーを META キーとして機能させることができる (あるいはデフォルトでそのように設定されている).Windows では ALT + F 等の入力がメニューに奪われてしまうため意図通りに機能しないこともあったり特別な設定を要することもあるが,TeraTerm や xyzzy, Eclipse 等は通常の ALT キーとのコンビネーションを META として解釈し,単独で ALT を押し離すとメニューバーにキーボードフォーカスが移るという気の効いた仕組みになっている.Putty の場合はそもそもメニューバーが存在しない.
META キーとは Sun 由来のキーボードに付いている装飾キーらしく,位置も PC キーボードの ALT と同じ場所なので PC キーボードに於ける META キーを ALT キーとして扱うのは妥当と言えるだろう (Sun キーボードには META の外側に ALT が付いているのだが,どのような用途で使われていたのかは知らない).そもそも昔は他に当てるキーがなかったわけだし,ALT キーの外側に Windows キーが付くようになっても,それらを META キーとして使う習慣のある人を見たことがない (というか Windows キーは ALT よりも更にシステムグローバルな機能が最初から割り当てられているし,おいそれと使うものではないという印象).
ここで強調しておきたいのは ALT キーの位置で,冒頭で述べた通り "Z" と "X" の下にあるキーが ALT であり META であるべきだ.Windows キーの位置にあるキーは利用頻度の高い装飾キーとしては使いづらい.
ややこしいのが Sun 由来の HHK で,やはり内側に META,外側に ALT と書かれたキーが配置されている.PC に繋ぐと外側の ALT と書かれた方のキーを ALT として認識する上に,HHK Lite 以前のモデルは外側の ALT の挙動をカスタマイズできないときた.泣ける.Sun の文化は知らないが,IBM PC の世界では ALT とは (以下略).PC で HHK を使う連中は内側を ALT/META として使っていると信じて疑っていないのだがどうだろう.
大体,端末エミュレータや Emacs 系アプリを使っている時に Mac 由来の Cmd 系ショートカトを必要とすることなどまずない (いや,実は Cmd + V だけ微妙に要るかも…).そういうアプリの利用時は Mac を Mac として使っているわけではないからだ.にも関わらず Terminal も iTerm も Eclipse も本来の Cmd バインドを優先して META を Option に追い遣ることしか考えていない.VMware Fusion が最悪で,ゲストで Windows を操作しているにも関わらず Option に Alt をマップしやがる!! 正気か?
一方,Carbon Emacs がデフォルトで Cmd を META に割り当てていて非常に助かっている.Cmd + V 問題は Kill-Ring をクリップボードと連動させることで回避していた.素晴らしい.そういえば Chicken of the VNC も Windows を操作する際に Cmd が Alt にマップされていたと記憶している.
META を Cmd に割り当てるべく iTerm をリビルドして使っている人もいるようだが,個人的には任意のアプリで Cmd と Option を入れ替えるようなユーティリティがあれば全て解決すると思う.どなたかご存知ないだろうか.
きっかけは MyMiniCity というサービスで,アクセス数に応じて自分の街が発展するという性質から Twitter 上にやたらと MyMiniCity へのリンクが貼られるようになった.個人的には興味がないのでスルーしていたが,そのうち巧妙な釣り文句と共に TinyURL を噛ませたリンクが貼られるようになって,迂闊に踏んでしまうとどうも悔しい.悔しいので対策することにした.
TinyURL のリンクを自動 decode している人は多いと思うが,自分も 自作 decoder を利用しているので,別途ページ中のリンクを走査して MyMiniCity らしきリンクをどうにかする Greasemonkey script を書けば解決するだろう.サクっと書いた.
// myminicity link detector
// (毎回 RegExp をコンパイルしているのは見逃して><)
var anchors = node.getElementsByTagName('a');
for (var n = 0, len = anchors.length; n < len; ++n) {
var anchor = anchors[n];
if (anchor.href.match(/^http:\/\/[^\.]+\.myminicity\.com\b/))
anchor.textContent = '<MyMiniCity Link>';
}
こいつを decoder script の後に動くようにしておけば偽装 MyMiniCity リンクもイチコロだぜ!! と思いきや,どうもうまく動かない.それもそのはずで,TinyURL decoder は tinyurl.com に対して decode 要求を行う際に GM_xmlhttpRequest による非同期通信を利用しており,decoder script が終了して更に myminicity link detector が終了してから実際の decode が行われる可能性もある.後続の処理を確実に動かすためには GM_xmlhttpRequest の onload ハンドラ内で行うしかないが,TinyURL decoder 内部に MyMiniCity 依存の処理を加えるのは気が引ける.
ところで,TinyURL 以外の URL 短縮サービスで MyMiniCity リンクが貼られることもあって,できればこれらも対応したい.最近は xrl.us という URL をよく見かける.他にも urltea.com, qurl.com, z.la など数えるとキリがないが,これらの中には明示的な decode 手段を用意していないものが多い.encode 用 API は用意されているが,decode はブラウザ任せとういか,実際に短縮 URL にリクエストしてみてリダイレクト時の location レスポンスヘッダを参照するしかない場合がある.GM_xmlhttpRequest は (自分の知る限り) リダイレクトに自動追随してしまうのでリダイレクト時の location レスポンスヘッダを参照することは恐らくできない.困ったものだ.
というか,decode API はともかく URL 短縮サービスは TinyURL のような Preview Mode を必ず備えているべきだと思うのだがどうよ.危なくね?
閑話休題,他の URL 短縮サービスに対応するとしても,要はどれもページ内のリンクを走査して何かを処理するというところは同じなので,その部分をうまく plugin 化できないものだろうか.AutoPagerize.addFilter のようにハンドラを登録して順次処理してくれる感じで.問題は前述の通り非同期処理を挟む可能性があるので単純にループでハンドラを回すだけでは目的は達成できない.
ハンドラが 3 つある場合は,このような処理をしたいわけだ:
if (should_do_1) {
GM_xmlhttpRequest({
onload: function(r) {
do_1();
if (should_do_2) {
GM_xmlhttpRequest({
onload: function(r) {
do_2();
if (should_do_3) {
GM_xmlhttpRequest({
onload: function(r) {
do_3();
else の場合も同様に次のハンドラへ処理を渡す.
というわけで,できた.
ページ内のリンクを走査し,登録されたハンドラ群に処理を渡すだけの Link Manipulator と,Link Manipulator の plugin として動作する TinyURL decoder と xrl.us decoder (これらは一つにまとめた),そして MyMiniCity のリンクを検出してアンカーテキストを置き換える detector を作った.detector は Twitter/Favotter 上で動作し,アンカーテキストを置き換えずに post そのものを非表示にすることもできる (今のところ要ソース修正 ;-).decoder は xrl.us → TinyURL といった二重 decode にも一応対応した.もちろん AutoPagerize 対応.
- Link Manipulator (管理用 script. 必須)
- Shorten URL Expander (各種短縮 URL 展開 plugin)
- Anti MyMiniCity (MyMiniCity リンク検出 plugin)
非同期処理が前提なので,スクリプトの実行順序に対して sensitive なのが玉に瑕.AutoPagerize → Link Manipulator → plugin scripts の順で並んでいないと意図通りに動かない (間に別のスクリプトが入るのは問題ないが).MyMiniCity のリンクをどうにかする場合は,事前に decoders を動かしておく必要がある.
TODO:
- decode 結果のキャッシュとクリア
- plugin 毎に処理するノードをカスタマイズできないか
- TinyURL, xrl.us 以外の短縮 URL 展開対応 → z.la に対応した (12/23)
というか,いまさら TinyURL ネタかよ :-(
install すると,favotter 上の各 post の下に星が出てきてクリックすると fav れる.既 fav かどうかは調べていないので,とりあえず全て白い星が表示される.fav った後は unfav もできる.
ついでに Twitter 上への permalink も設置する.
install: favotter-favor.user.js
なんか,自分が AutoPagerize をインストールした数日後 (7/10) に新しいバージョンがリリースされていて,あまつさえ addFilter なんつー機能が増えているジャマイカ.なんてことに二ヶ月くらい気付かなかった.
ので de-tinyurl も追随しました.
- AutoPagerize.addFilter を利用して,力技対応をやめた.
- query string 付き URL の decode がおかしかったのを修正 (なぜ気付かない?
Ustream.tv が流行っている.bulknews.net や bulkneets.net が特殊な需要を喚起し,新ジャンル「他宅警備員」まで生まれる始末.周囲の Twitterist も,利権的にナニなものを垂れ流したり勤務中の姿を晒したりひたすらキーボードを打つ手元が映されたり (パスワードとか打ったらヤバくね!?),今後の動向から目が離せない.
まぁそれはさて置き,自分でも Ustream 向けの何か作ってみたくて手を動かしてみた.自分の Watchlist (の 1 ページ目) を他宅警備する Greasemonkey Script. インストールすると,ログイン中の Ustream に "Watchlist View" というメニューが表示されるので,押すと GM_xmlhttpRequest を使って自分の Watchlist ID 群を拾ってその場で Flash を並べる.
ustream.watchlist-view.user.js
GM_xmlhttpRequest を使用しているので (いや,使用不使用に関わらず),ソース熟読の上で利用されたい :P
といった矢先,Ustream のリニューアルと同時にアクセス制限が施された (というか,作成中にリニューアルされたので class や id 属性がいきなり変わってビビった).今のところ,単一 IP アドレスから 4~5 streams しか開けないようだ.ちぇー.いきなり無意味になったし :-(.
いつぞやの Twitter のように劇的な負荷対策劇と共に制限を取っ払って欲しいと願ってやまない.ユーザは勝手なものだなぁ.
TODO
- スライダー付けたい
- 制限食らった Flash は内蔵リロードボタンが効かないので別途リロードボタンを付けたい
- "Live!" な show だけ表示するとか
前回の続き.「初心者向け Javascript 勉強会」の Greasemonkey に関する資料が公開されているブログエントリのコメント欄にて補足的なやりとりが見られる.どうやら Greasemonkey から提供された window オブジェクトはスクリプト間で共有されるらしい.確認してみよう.ようやく Firebug の "console" を覚えたのでソレで.
console.log('script a');
a = 10
window.b = 11;
if (typeof a != 'undefined') console.log(a);
if (typeof b != 'undefined') console.log(b);
if (typeof c != 'undefined') console.log(c);
if (typeof d != 'undefined') console.log(d);
もう一つ.
console.log('script b');
c = 20;
window.d = 21;
if (typeof a != 'undefined') console.log(a);
if (typeof b != 'undefined') console.log(b);
if (typeof c != 'undefined') console.log(c);
if (typeof d != 'undefined') console.log(d);
コンソールには "script 1" → "10" → "11" → "script 2" → "11" → "20" → "21" の順で表示された.window オブジェクトに定義したプロパティが引き継がれていることが分かる.script 2 側で "10" が表示されていないことから,Global オブジェクト != window オブジェクトであることも分かる (スコープチェイン中で a が未定義であることが前提).
で,ひとつ重要な事柄が.どうやら Opera の UserJS というもので Greasemonkey と似たようなことができるらしく,こちらでは機能が設けられた目的の違いから Greasemonkey のような保護が効かないようだ.つまり,スクリプトを Opera 対応させたい場合は匿名関数で wrap した方が良い,ということになる (その他,様々な cross browser hack も必要になるのだろう).恐らく,スピーカの方もこの件を伝えたかったのだと思う.
以上,今朝 Twitter で「グリモンスクリプト中の匿名関数は時代遅れのバッドノウハウ」と,やや刺激的に紹介されてしまったのでビビって補足している次第 (まぁでも間違ってないよな).ぶはは ;D
on Carbon Emacs + AquaSkk + C-j + etc.