m2O

2007/02/13 (火)

Auto Commit del.icio.us を更新しました

|  Auto Commit del.icio.us を更新しました - m2O を含むブックマーク

Auto Commit del.icio.us
http://orera.g.hatena.ne.jp/miya2000/20070205/p0

タイトルが未設定の場合ははてなブックマークエントリー情報取得APIからタイトルを取得するようにしました。あと menu.ini も加えています。

昨日の wget を使ったやつでも十分なんですが、こちらは外部プログラムに依存しないこととブックマークの様子が見て取れるのが嬉しいかなと思います。

利用する場合は必ず ackey (←別にこの名前じゃなくてもいい)を変更するよう、お願いします。

トラックバック - http://orera.g.hatena.ne.jp/miya2000/20070213

2007/02/12 (月)

del.icio.us API のフロントエンドに wget を使う

|  del.icio.us API のフロントエンドに wget を使う - m2O を含むブックマーク

先日から試行錯誤してる「あとで読むタグだけつけてdel.icio.us」を、wgetapi.del.icio.usリクエストを投げる方法でやってみた。

[deliciousadd.js](JScript)

// <user settings> //
var wget = '\\path\\to\\wget.exe';
var username = 'delicious_userid';
var password = 'delicious_password';
// </user settings> //

var args = WScript.Arguments;
var url   = (args.length>=1) ? args.item(0) : null;
if ( ! url ) WScript.quit();
var title = (args.length>=2) ? args.item(1) : url;

var delicious = 'https://api.del.icio.us/v1/posts/add?'
var target = delicious + 
            'url=' + encodeURIComponent(url) + 
            '&description=' + encodeURIComponent(title) + 
            '&tags=' + encodeURIComponent('あとで読む');
var cmd = [
    '"' + wget + '"',
    '"' + target + '"',
    '--http-user=' + username,
    '--http-passwd=' + password,
    '--spider'
];
var shell = new ActiveXObject('WScript.Shell');
shell.Run(cmd.join(' '), 0 );

これをコンテキストメニューから呼び出す。

[menu.ini]

[Link Popup Menu]
Item, リンクをdel.icio.usに追加=Execute program, "\path\to\deliciousadd.js","%l %t"

[Document Popup Menu]
Item, del.icio.usに追加=Execute program, "\path\to\deliciousadd.js","%u %t"

マウスジェスチャーにも。

[mouse.ini]

[Application]
GestureUp=Execute program, "\path\to\deliciousadd.js","%l %t"

--

タイトルがもっと簡単につけられるといいんだけどなぁ。
deliciousadd.js 内で ActiveXObject('Msxml2.XMLHTTP') を使えばとってこれるかな? 面倒だからやらないけど↓やっちゃった

--

はてブAPIからタイトルとってくるのは意外と簡単だった。

function getHatebuTitle(url) {
    var http = new ActiveXObject('Msxml2.XMLHTTP');
    http.open('get', 'http://b.hatena.ne.jp/entry/json/' + url, false);
    http.send();
    var matches = /"title":"([^"]*)"/.exec(http.responseText);
    if ( matches ) {
        var title = unescape(matches[1].replace(/\\/g,'%'));
        return title;
    }
    return null;
}
WScript.echo('['+getHatebuTitle('http://www.hatena.ne.jp/')+']');

これを上の deliciousadd.js に仕込めばはてなブックマークのタイトルを自動で設定できる。

トラックバック - http://orera.g.hatena.ne.jp/miya2000/20070212

2007/02/08 (木)

del.icio.us に簡単に post するアイデアのメモ

|  del.icio.us に簡単に post するアイデアのメモ - m2O を含むブックマーク

ここ数日 del.icio.us に簡単に post することばっかり考えていて、そのアイデアメモ。「もっといいアイデアあるよ」とか「それ既にあるよ」とか「それPla」とかあれば教えてください。
ブラウザから api.del.icio.us は使わない方向で考えてます。

  1. Auto Commit del.icio.us拡張
    TODO に書いてる実装。これは多分やります。JScript かなにかを Execute program で呼び出す。ワンタイムパスワードはなんでもいいんだけど JavaScriptMD5 ライブラリがあったのでそれで。最終的にM2フィードリーダーリンクからマウスジェスチャーで呼び出す予定。
  2. Opera Widget
    Widget についてはまだ詳しく調べてないのだけど、確かクロスドメインアクセスができたはず。ブラウザとの連携、例えば現在開いているページのアドレス等の取得、は出来なかったんじゃないかと思うけど未確認(情報ください)。出来たらOK、出来なくても多分テキストエリアを用意しといてそこにリンクドラッグ&ドロップはできると思う。マウスジェスチャーより少し手間だけど、導入はしやすいんじゃなかろうか。
    でも面倒だから多分やらない。
  3. Googleで「あとで読む+url」と検索すると del.icio.us に届くようにする
    ぜったいやらない
    が、たぶん api.del.icio.us ってこういうブラウザ以外からアクセスする用途のためにあるんだろうな。

--

あ、widget って Cookie 送ってくれるんだろうか? それも確認しなければ。

トラックバック - http://orera.g.hatena.ne.jp/miya2000/20070208

2007/02/05 (月)

Auto Commit del.icio.us

|  Auto Commit del.icio.us - m2O を含むブックマーク

これは何?

del.icio.us で「あとで読む」タグをつけてブックマークしたい時に、確認画面以降を自動化する bookmarklet & user.js です。

注意

user.js 内では記事タイトルが設定されていない場合、"はてなブックマークエントリー情報取得API"からタイトルを取得しています。これは http://b.hatena.ne.jp/ からダウンロードした任意の JavaScriptdel.icio.us ドメイン内で実行しているということです。このことを理解した上でご利用ください。(該当部分を削除すればこのリスクはありません)

先に方法

  1. user_id は自分のIDに置き換えます
  2. location.hash の部分は他者が知り得ない任意の値にします
    リクエストパラメータ ackey は他者が知り得ない任意の値にします利用の際は必ず変更してください。

[bookmarklet]

javascript:window.open('http://del.icio.us/user_id?ackey=qawsedrftgyhujiko&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)+'&tags='+encodeURIComponent('あとで読む')+'&v=4&jump=close','delicious','width=700,height=400').blur()

[user.js]

// ==UserScript==
// @name del.icio.us - Auto Commit del.icio.us
// @namespace http://orera.g.hatena.ne.jp/miya2000/20070205/p0
// @version 1.0.3
// @include http://del.icio.us/user_id?ackey=qawsedrftgyhujiko&url
// ==/UserScript==
(function(){
    window.focus=new Function(); // kill focus.
    window.addEventListener('load', function(){
        var d = document;
        var url   = d.getElementById('url').value;
        var title = d.getElementById('description').value;
        // <はてなからタイトル取得>
        if ( ! title ) {
            opera.tmpcallback = function (data) {
                delete opera.tmpcallback;
                d.getElementById('description').value = (data) ? data.title : url;
                d.getElementById('delForm').submit();
            };
            var s = d.createElement('script');
            s.type = 'text/javascript';
            s.src = 'http://b.hatena.ne.jp/entry/json/?callback=opera.tmpcallback&url=' + 
                    encodeURIComponent(url);
            d.body.appendChild(s);
            return;
        }
        // </はてなからタイトル取得>
        if ( ! title ) d.getElementById('description').value = url;
        d.getElementById('delForm').submit();
    }, false);
})()

[menu.ini]

[Link Popup Menu]
Item, "リンクをdeliciousに追加"=Go to page, "javascript:(function(){var url='http://del.icio.us/user_id?ackey=qawsedrftgyhujiko&url='+encodeURIComponent('%l')+'&title='+encodeURIComponent('%t')+'&tags='+encodeURIComponent('あとで読む')+'&v=4&jump=close';if(/^javascript:/.test(location.href)){location.href=url;window.blur();}else{window.open(url,'','width=700,height=400').blur();}})()"
[Document Popup Menu]
Item, "deliciousに追加"=Go to page, "javascript:(function(){var url='http://del.icio.us/user_id?ackey=qawsedrftgyhujiko&url='+encodeURIComponent('%u')+'&title='+encodeURIComponent('%t')+'&tags='+encodeURIComponent('あとで読む')+'&v=4&jump=close';window.open(url,'','width=700,height=400').blur();})()"
[Hotclick Popup Menu]
Item, "リンクをdeliciousに追加"=Go to page, "javascript:(function(){if('%l'){var url='http://del.icio.us/user_id?ackey=qawsedrftgyhujiko&url='+encodeURIComponent('%l')+'&title='+encodeURIComponent('%t')+'&tags='+encodeURIComponent('あとで読む')+'&v=4&jump=close';if(/^javascript:/.test(location.href)){location.href=url;window.blur();}else{window.open(url,'','width=700,height=400').blur();}}else{alert('リンク無し')}})()"

以下、ここまでの流れ

特にタグを入力したいわけじゃない場合は確認画面以降を自動化したい。→ただ単に user.js で submit() するだけじゃ CSRF できちゃう。 →とりあえず一番簡単な固定キーで bookmarklet からのリクエストかどうかを判定して自動 submit。

TODO

  1. Link Popup Menu 対応。このあいだのは title にも url を入れてたけど、今度は"はてなブックマークエントリー情報取得API"からタイトル取ってこよう。実装済み
  2. location.hash よりクエリの方が見栄えがいいと思う。実装済み
  3. 毎回同じパスワードを使っているようで気持ち悪い。例えばワンタイムパスワード現在時刻を別の user.js に出力しておいて上の user.jsリクエストパラメータと比較する(古いのは無効)、ってのを思いついた。ほかにあるかな?

思ったこと

UserJavaScript からしかアクセスできない共有メモリ(ドメインを超えて保持)なんかがあると便利そう。

ライセンス

好きに使っていいけど責任取らないやつ。

更新履歴

1.0.1
固定キーを保持する場所を location.hash から リクエストパラメータ(ackey)に変更。このパラメータは「http://del.icio.us/post」から「http://del.icio.us/user_id」にリダイレクトされる時に削除されるので、ユーザーIDと固定キー双方を知らないと CSRF できない。*1
1.0.2
タイトルが無い場合に"はてなブックマークエントリー情報取得API"からタイトルを取得するように変更。
menu.ini をカスタマイズしてコンテキストメニューから使えるようにしました。
menu.ini
M2のリンクから実行した時に余計なウィンドウが出ていたので出ないようにしました。
1.0.3
はてなからタイトルを取得する部分を削除しやすいようにしました。削除する場合は<はてなからタイトル取得>から</はてなからタイトル取得>までを削除してください。

*1:ユーザーIDを指定したCSRFなんて、相当な恨みを買っているとしか思えませんね

2007/01/29 (月)

Link Popup Menu から del.icio.us

|  Link Popup Menu から del.icio.us - m2O を含むブックマーク

先に方法

[menu.ini]

[Link Popup Menu]
Item, "Post link to delicious"=Go to page, "javascript:void(window.open('http://del.icio.us/post?v=3&url='+encodeURIComponent('%l')+'&title='+encodeURIComponent('%t'||'%l')+'&jump=close','delicious','width=700,height=400'));"
[Hotclick Popup Menu]
Item, "Post link to delicious"=Go to page, "javascript:if('%l'){window.open('http://del.icio.us/post?v=3&url='+encodeURIComponent('%l')+'&title='+encodeURIComponent('%t')+'&jump=close','delicious','width=700,height=400')};undefined;"

(追記:テキスト選択でタイトルがつけられるようにしました)

(追記:クエリに「&jump=close」を追加して user.js を不要にしました)

[user.js]

// ==UserScript==
// @name          del.icio.us - close "del.icio.us" popup window after saved.
// @version 1.0.0 
// @include       http://del.icio.us/*?url=
// ==/UserScript==
javascript:(function(w){if(w.opener)w.addEventListener('unload',function(){w.close();},false);})(window);

(追記:現在、この user.js は不要です)

以下、ここまでの流れ

情報収集をしているときに、今調べたいことと関係の無いページはとりあえず「後で読む」タグを付けてソーシャルブックマークしておき、その自分のブックマークを家でゆっくり RSS リーダで読む。というのをこれからやろうと思ったのがきっかけ。

別にそのページを分類したりブクマコメントしたいという用途ではないので手っ取り早くブックマークしたい。該当ページを開く必要も無く、つまりはリンクポップアップメニュー(リンク右クリックしたときに出るコンテキストメニュー)に「Add link to social bookmarks」が欲しいという訳。

んでこのブックマークは"はてブ"とは区別したかったので del.icio.us を使ってみた。のだけど、はてブでは別窓が開いてブックマークできるのに対して del.icio.us ではブックマークしたいページに del.icio.usブックマークページが読み込まるタイプ(だけなのかどうかは不明)。なので別窓で表示するように bookmarklet を書き換えて、ブックマークが終わればその窓を閉じるように user.js を加えた。

window.open の戻り値に対して addEventListener すりゃ user.js は要らないんじゃないかと思えるんだけどそれは NG。一旦別ドメインのページを開いたらその window はもうそのドメインのもので、呼び出し側から制御することはできない。

もう一歩

  • http://del.icio.us/post?」のクエリに「&tags=後で読む」を加えても反映されない。「http://del.icio.us/(userid)?」のクエリだとできるのになあ。
  • [Hotclick Popup Menu]の時、リンク上でなければ(%l がなければ) disable なんて制御はできるのかな?
  • 「Go to page,hoge,fuga,piyo,foo」の仕様ってどこで調べるんだろ?

通りすがり通りすがり2007/01/30 01:24del.icio.usではポスト時のパラメータに「jump=close」を加えておけば別窓を閉じてくれるので、user.jsは不要かと。
あと、後で読む専用のブックマークということであれば、LookLaterを試してみてはいかがでしょう。bookmarkletを起動後にリンクをクリックするだけでブックマークできます。ただし、英語以外での使用がほとんど考慮されていないので、フィードは文字化けしてしまいますけど。
http://looklater.com/

miya2000miya20002007/01/30 10:51> パラメータに「jump=close」
おおお! 確かに閉じてくれました! 情報ありがとうございます。
user.js は可能な限り減らしたいので助かりました。
> http://looklater.com/
目的そのままの名前のサービスがあったのですね。これはいい。
と思ったのですが、script読み込みタイプの bookmarklet なんですね。おそらく文字数制限のあるIEでも使えるようにした結果なんだとは思いますが、セキュリティ上、よほど信用してない限りこのタイプのは使わないようにしています。
なので bookmarklet か user.js に書き換えられないかこれから試してみます。

miya2000miya20002007/01/30 13:33せっかく教えていただいた LookLater ですが、利用を見送ることにしました。ページ内のリンクをフックするアイデアはおもしろいと思ったんですが…。
海外では CSRF ってあんまり重要視されてないんですかね?

トラックバック - http://orera.g.hatena.ne.jp/miya2000/20070129