Hatena::ブログ(Diary)

Hell o world (foo)

ブログを移転したため、このブログの更新予定はありません。 移転先は、電卓片手に になります。

October 19(Sun), 2008

ブログ移転

ブログを移転します。

電卓片手に

いつも見てくださっている方ありがとうございます。

October 16(Thu), 2008

CUIDropbox

あったよあった。CUIからでもDropbox使う方法。

Linux CLI in python

どうやら、この python スクリプト使って、X システムが無いCUIオンリーの環境でも、Dropboxインストール・実行できるよってことらしい。

使ってみた。

$ wget https://dl.getdropbox.com/u/43645/dbcli.py
$ python dbcli.py 
Usage: dbcli.py <command> [options] ... <command> [options]
Available commands:
   status - Get overall status for the daemon.
   copypublic <file> - Copies the url to the clipboard (? I guess)
   install <x86/x86_64> - Tries to download the daemon and install it in your home directory.
   browse <folder> - Browse the specified folder in your browser.
   copygallery - Copies the gallery url to the clipboard.
   share <file> - Open the browser and shows share-information.
   file <file> - Get information about a file/folder.
   folder <folder> - Get information about a file/folder.
   help - Gives this.
   revisions <file> - Opens the revisions page in your browser for the specified file.

なるほどー取りあえず install コマンド使えば良い感じ?

$ python dbcli.py install x86
error: couldn't connect to the daemond.
Trying to start the daemon.
The daemon does not exist (try dbcli.py install)
rm: cannot remove `/home/kui/.dropbox-dist/': そのようなファイルやディレクトリはありません
Starting to download dropbox-lnx.x86-0.6.382.tar.gz...
  ... 1 kB of 17149 kB
  ... 1716 kB of 17149 kB
  ... 3431 kB of 17149 kB
  ... 5146 kB of 17149 kB
  ... 6861 kB of 17149 kB
  ... 8576 kB of 17149 kB
  ... 10291 kB of 17149 kB
  ... 12006 kB of 17149 kB
  ... 13721 kB of 17149 kB
  ... 15436 kB of 17149 kB
  ... 17151 kB of 17149 kB     # この辺で「おおおこれはひょっとして、dropboxdとかダウンロードしてる!?wktk」ってなってる。
Done. Unpacking...
Trying to start the daemon.
Traceback (most recent call last):
  File "<string>", line 6, in <module>
  File "__main__.py", line 105, in <module>
  File "__main__dropbox__.py", line 174, in <module>
  File "__main__dropbox__.py", line 169, in main_startup
  File "arch/linux/startup.py", line 131, in main_thread_loop
AttributeError: 'NoneType' object has no attribute 'MainLoop'
Exception in thread CONTROL (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "threading.py", line 486, in __bootstrap_inner
  File "common_util/trace.py", line 31, in intwatched
<type 'exceptions.TypeError'>: 'NoneType' object is not callable
Unhandled exception in thread started by <bound method WatchedThread.__bootstrap of <WatchedThread(CONTROL, started)>>
Error in sys.excepthook:
TypeError: 'NoneType' object is not callable

Original exception was:
Traceback (most recent call last):
  File "threading.py", line 462, in __bootstrap
  File "threading.py", line 527, in __bootstrap_inner
AttributeError: 'NoneType' object has no attribute 'acquire'
Exception in thread AUTHENTICATE (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "threading.py", line 486, in __bootstrap_inner
  File "client_api/authenticate.py", line 207, in run
<type 'exceptions.TypeError'>: 'NoneType' object is not callable
Unhandled exception in thread started by <bound method AuthenticationThread.__bootstrap of <AuthenticationThread(AUTHENTICATE, started)>>
Error in sys.excepthook:
TypeError: 'NoneType' object is not callable

Original exception was:
Traceback (most recent call last):
  File "threading.py", line 462, in __bootstrap
  File "threading.py", line 527, in __bootstrap_inner
AttributeError: 'NoneType' object has no attribute 'acquire'
Exception in thread RTRACE (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "threading.py", line 486, in __bootstrap_inner
  File "common_util/trace.py", line 486, in run
  File "common_util/trace.py", line 412, in rtrace_thread_func
<type 'exceptions.TypeError'>: 'NoneType' object is not callable
Unhandled exception in thread started by <bound method RtraceThread.__bootstrap of <RtraceThread(RTRACE, started)>>
Error in sys.excepthook:
TypeError: 'NoneType' object is not callable

Original exception was:
Traceback (most recent call last):
  File "threading.py", line 462, in __bootstrap
  File "threading.py", line 527, in __bootstrap_inner
AttributeError: 'NoneType' object has no attribute 'acquire'

何やらダメだった。pythonはちょっとしかかじった事無いので、何が書いてあるか今イチピンとこない。どうやら lennydebian ではダメだったようだ。あとで原因追及したいな。

追記

どうやら

 :
Trying to start the daemon.
 :

から下のメッセージは、dropboxd からのメッセージみたい。直接 dropboxd を動かしてみて分かった。Ubuntu は良くても debian はダメってことかしら。残念。

October 15(Wed), 2008

Dropbox使ってみた & ssh ログイン時にDropbox使う方法

話題になってただけあって便利な感じ.気になるのは,Gnome (正確には nautilus?)を起動するようなログインをしないと自動で同期してくれない点.

実際,Linuxssh でリモートログインして使うことの多い僕には,Dropbox縁無いかなー残念かなー

と思いつつ,そもそもこれ,誰が同期してるんだろうなーと思い探し出す.

$ ps x | grep drop
19109 ?        Ssl    0:07 /home/kui/.dropbox-dist/dropboxd

それっぽい名前...

ssh ログインしてこいつを動かしてみる.

$ ~/.drop-dist/dropboxd
[プロンプト帰ってこない]

う,,ごいた?

別端末から確認してみたところうまく機能しているようです.ノーティファー無くても,同期さえしてくれていればいいのさ!って人は,これだけ動かせばいいのかもしれないですね.

これで,このデーモンのスタート&ストップスクリプトを誰かが書いてくれたら幸せになれる!

ちなみに「.drop-dist/dropboxd」でぐぐるとなにやらたくさん出てきているのでもっと便利な方法あるかもしれないです.

October 07(Tue), 2008

[][]もごもごに Autopagerize

最近になってAutopagerize使いはじめた。今まで手をつけてなかったのは、AutoPagerizeを絶賛する記事が多かったため天邪鬼根性発動していたから。

いいかんじですねー。ホイールまわすのが楽しくなってしまう。

難点は、

  • フッターを見る機会がほとんど無くなってしまうため、サイトデザイナーさん泣かせな点
  • AutopagerizeのON/OFFやりにくい
  • 調子に乗ってホイール回す → トップに戻るの大変(Homeキー押すなりすれば解決

って感じでしょうか。

でもやっぱりホイール回すの楽しい。

んでタイトルの通り、いつも遊びに行ってるもごもごautopagerizeできないので自分でsiteinfo書いた。

var SITEINFO = [

   // みんなのひろば、マイホーム
   {
        url:          'http://(www.)?mogo2.jp/(top|home(/archive_(all|res)|/res)?|(comment|keyword/search)/[1-9][0-9]*)',
        nextLink:     '//div[@id="t_all_read"]/p/a[last()]',
        pageElement:  'id("newest_comment")',
        exampleUrl:   'http://mogo2.jp/top',
    },

    // もごリンク、XXさんの部屋 (こっちの表示納得いかない)
    {
        url:          'http://(www.)?mogo2.jp/(member/(keyword/)?)?[1-9][0-9]*',
        nextLink:     '//div[@id="t_all_read"]/p/a[last()]',
        pageElement:  'id("hot_kuchikomi")',
        exampleUrl:   'http://mogo2.jp/99',
    },
]

こんな感じで書いた。

しかしなんだ、urlをあんなに気合い入れて書く必要なかった様子。もったいないからそのまま。

wedata に登録しておいた。もごもご(みんなのひろば、マイホーム)もごもご(もごリンク、XX さんの部屋)

登録してから気がついたけど、これ、もごもごで使う人いるのかなぁ。。。

なんか久しぶりにXPath書いたー

んー登録したけど上のデータを一つに纏められてしまったので,みんなのひろばでの挙動がおかしくなってしまった.何かにコミットする経験って初めてだからどうしたらいいかわからないなあ.

May 05(Mon), 2008

[][]Last.fmラジオの自作

http://code.google.com/p/thelastripper/wiki/LastFM12UnofficialDocumentation

Last.fmラジオを自分で作る際に必要な WebAPI のドキュメント.ただ...これをみて堂々とプレイヤーを公開するのは気が引けますね.再生までの簡単な手順はこんな感じ*1.最後の方に "まとめ" として簡単なRubyスクリプトも載せてみた.これくらいなら大丈夫だよね...きっと..

手順

ラジオとして機能させるにはざっくり分けると四つのステップを踏むことになります.具体的には,

Handshake
セッションIDの取得,リクエスト先のホスト名の取得
Adjusting Radio Station
ラジオの選択
Requesting an XSPF
プレイリストの取得
Play
音楽再生

となります.しかし,Handshake で取得する情報は,2回目以降でも使い回しができるみたいです.

Handshake

セッションを張る

要求

以下の URL に GET リクエストを送る.

http://ws.audioscrobbler.com/radio/handshake.php?version=1.3.1.1&username=[USERNAME]&passwordmd5=[PASSWORDMD5_HASH]
[USERNAME]
Last.fm に登録してあるアカウントのユーザ名
[PASSWORDMD5_HASH]
Last.fm に登録してあるアカウントパスワードMD5ハッシュ関数を通した文字列(md5sum コマンドとか,Rubyだったら"digest/md5"とか?)
応答

すると,ws.audioscrobbler.com からはこんな感じのが返ってくる

session=ae1eb54a11615e605d61d6e83dde71bc
stream_url=http://87.117.229.85:80/last.mp3?Session=ae1eb54a11615e605d61d6e83dde71bc
subscriber=0
framehack=0
base_url=ws.audioscrobbler.com
base_path=/radio
info_message=
fingerprint_upload_url=http://ws.audioscrobbler.com/fingerprint/upload.php

実際に必要なのは session, base_url, base_path の値だけ.

session
以降リクエストする時のセッションID
base_url
以降のリクエストを送るホスト
base_path
以降のりくs(ry

これら三つを保存しておく.


Adjusting Radio Station

ラジオ局の指定

要求

以下の URL に GET リクエストを送る.

http://[base_url][base_path]/adjust.php?session=[sessionID]&url=[LASTFMURI]
[base_url],[base_path],[sessionID]
先ほどの Handshake で取得した値
[LASTFMURI]
ラジオを選択する時のLast.fm独自のURI
Last.fm独自URI

僕が良く使うやつだけ挙げておく.他のは元のを参照してください.

lastfm://artist/$artistname
$artistname で指定されるアーティストに似た楽曲が集まった局を指定
lastfm://globaltags/$tag
$tag で指定されるタグがついた楽曲が集まった局を指定

応答

例えば, lastfm://globaltags/8bit とラジオ局を選択した時に,選択が成功するとこんな感じの応答が返ってくる.

response=OK
url=lastfm://globaltags/8bit
stationname= 8bit Tag Radio
discovery=true

ここで特に保存すべき内容は無い.

Requesting an XSPF

プレイリストを取得する.XSPF とはプレイリストのファイル形式の一つで,XML の形式をとっています.

要求

以下のように GET 要求を送る

http://[base_url][base_path]/xspf.php?sk=[SESSIONID]&desktop=1.3.1.1
[base_url],[base_path],[sessionID]
先ほどの Handshake で取得した値
応答

すると以下のXSPF形式で応答がある.(先ほどと同じ様に 8bit というタグで指定した場合)

<playlist version="1" xmlns:lastfm="http://www.audioscrobbler.net/dtd/xspf-lastfm">
<title>+8bit+Tag+Radio</title>
<creator>Last.fm</creator>
<link rel="http://www.last.fm/skipsLeft">6</link>
<trackList>
    <track>
        <location>http://play.last.fm/user/da4d7abd06d00e21b9b387b491cbf1fe.mp3</locatio
n>
        <title>Marbles</title>
        <id>36732</id>
        <album>Swarm &amp; Dither</album>
        <creator>Hrvatski</creator>
        <duration>227000</duration>
        <image>http://cdn.last.fm/coverart/130x130/7099.jpg</image>
        <lastfm:trackauth>92c11</lastfm:trackauth>
        <lastfm:albumId>7099</lastfm:albumId>
        <lastfm:artistId>2308</lastfm:artistId>
                <link rel="http://www.last.fm/artistpage">http://www.last.fm/music/Hrvat
ski</link>
        <link rel="http://www.last.fm/albumpage">http://www.last.fm/music/Hrvatski/Swarm
%2B%2526%2BDither</link>
        <link rel="http://www.last.fm/trackpage">http://www.last.fm/music/Hrvatski/_/Mar
bles</link>
        <link rel="http://www.last.fm/buyTrackURL"></link>
        <link rel="http://www.last.fm/buyAlbumURL">http://www.last.fm/affiliate_sendto.p
hp?link=catch&amp;prod=7099&amp;pos=65633c2c6d40fbe9c8bf27ce82d2ca5a</link>
        <link rel="http://www.last.fm/freeTrackURL"></link>
    </track>
    <track>
        <location>http://play.last.fm/user/f1702fa3845bec7817a62749a1fbc49a.mp3</location>
        <title>Pioneer</title>
        <id>69590509</id>
        <album>Pioneer</album>
        <creator>she</creator>
        <duration>204000</duration>
        <image>http://cdn.last.fm/coverart/130x130/3287460.jpg</image>
        <lastfm:trackauth>35a7f</lastfm:trackauth>
        <lastfm:albumId>3287460</lastfm:albumId>
        <lastfm:artistId>1083333</lastfm:artistId>
                <link rel="http://www.last.fm/artistpage">http://www.last.fm/music/she</link>
        <link rel="http://www.last.fm/albumpage">http://www.last.fm/music/she/Pioneer</link>
        <link rel="http://www.last.fm/trackpage">http://www.last.fm/music/she/_/Pioneer</link>
        <link rel="http://www.last.fm/buyTrackURL"></link>
        <link rel="http://www.last.fm/buyAlbumURL"></link>
        <link rel="http://www.last.fm/freeTrackURL">http://freedownloads.last.fm/download/69590509/Pioneer.mp3</link>
    </track>
</trackList>
</playlist>

とこんな感じ.

Play

先のレスポンスの中の,"/playlist/trackList/track/location" で指定される文字列を,mpg123 などに渡す.

まとめ

再生までの最小限のコードはこんな感じ(?)になるのかな.

続きを読む

*1:ひょっとしたら,他のトコロでも過去に取り上げられているかも知れませんが,'08年の2〜4月あたりに少しAPIの仕様が変わっているようです.この記事は'08年5月5日現在のこのAPI紹介です.