0

RubyのARGV.shift or “default value”

orと||は(優先度とか)違う演算子だという事は知ってたけど、左側がARGVかArrayかでもまた動作が違うとは思ってなかった。Rubyは難しい。


or演算子でデフォルト値をセット

Rubyで、値が無い時にデフォルト値をセットするのによくor演算子を使う。

例えばコマンドラインからの引数を取り出して、何も値が無かったらデフォルト値を使うとかあると思う。

ARGVは配列なのでこうやろうと思った

user = ARGV.shift or "shokai"

引数なしだとARGVは空配列になるから、or演算子の右側のデフォルト値が左辺に渡されると思ったけど、そんなことはなかった。


Array#shift or “default value”ってできないんだっけ?と思ってARGVじゃなくてArrayで試した。こっちはできる。


or のかわりに || を使ったら、空のARGVをshiftした時にorの右側が取り出せた。


念のため確認したけどARGVはArrayを継承してる。でもorと||で挙動が違う・・


結論

orの方が好きだけどこう書く。
arg1 = ARGV.shift || "defalut value"

0

socket.io-client-simple gemをsocket.io 1.1.0に対応した

socket.io 1.1.xに対応した、socket.io-client-simple gem 1.1.2を今朝リリースした。
これを使うとrubyでsocket.ioサーバーに接続できる。

https://rubygems.org/gems/socket.io-client-simple
Comparing v1.0.0…v1.1.2 · shokai/ruby-socket.io-client-simple

1.1.2のクライアントでsocket.ioサーバー1.0系に日本語を送ると文字化けするので注意してほしい。「ああ」が「BB」になったり「はい」が「oD」に化ける。


socket.io 1.1.0


1.0→1.1での変更
Socket.IO — Socket.IO 1.1.0


だいたいbug修正じゃね?と思ってたら、マルチバイト文字列のエンコーディング方法が修正された。

これにより、1.0系のsocket.io-clientから1.1系のサーバーに日本語などのマルチバイト文字を送ると文字化けするし、1.1系のクライアントから1.0系のサーバー通信しても文字化けする。

サーバーとクライアントのバージョンを合わせるか、URLエンコードするかすればいいと思う。


あと、websocket proxy(herokuやnginxなど)を前に建てたsocket.ioサーバーと接続している時に、proxyが生きているけどサーバーが再起動した時などに切断を検知できるようになった

0

socket.io-client-simple gemをsocket.io 1.0.x対応した

5月末にでたSocket.IO 1.0に、socket.io-client-simpleを対応させた。

1.0対応は2週間ぐらい前にだいたいできてたんだけど、切断の検知と自動再接続する処理のあたりがうまくいかなくてリリースできてなかった。rubyのthreadの闇は深い。


うまく動くようになったのでどうぞ

% gem install socket.io-client-simple

変なところあったらgithubにissue立てたり、@shokaiにお知らせください


経緯


socket.io meetupに行ったら意識が高まったので、プレゼンとか聞きながらデバッグしてたらできてきて、意識高まりすぎて寿司とビールスルーして帰って電車の中でgem pushした。


socket.io 0.9 → 1.0の変更点メモ

ソースを読んだりして挙動を調べた。
研究室のwikiに書いたのメモのコピペで、たぶんgeta6とかnekobatoが書いてくれた情報も含まれる

クライアント作者としてはping-pongがサーバー→クライアントだったのがクライアント→サーバーになったおかげで切断検知しやすくなってうれしい感じした。


engine.io 1.1 -> 1.2に上がった

むしろこっちの変更の方が多いような気もする、あんまりちゃんと追えてない


初期化プロセスが変わった

最初に接続可能なプロトコル一覧を取るところから違う
xhr(comet?)で最初つないで、websocket使えるならwsに移行する

ということはrubyのsocket.ioクライアントはwebsocketだけのシンプル実装じゃだめ?
と思ったけど、いきなり/socket.io/?transport=websocket にwebsocket接続すればokだった。transportオプションがキモ

node.jsでもクラスターを取るとupgradeリクエストの後で400を返してしまう
クライアントの接続オプションにtransports: [‘websocket’, ‘polling’]を渡して以前と同じ挙動にできる
io.connect window.location.host, {transports: [‘websocket’, ‘polling’]}

failするユーザが高速につなげるようにするためにxhr-pollingを先行させている
開発するもののターゲットにレガシーブラウザが入っていなければwsを先行していいと思う

バージョンが混ざったらやばい

1.0のクライアントを0.9のサーバーに接続させようとするとサーバーで大量の”unhandled socket.io url”エラーが出る


通信データの格納方法が違う

server/client両方で環境変数 DEBUG=* を付けて通信させてみるとわかりやすい
頭に数字(制御コード)が付いたjsonをやりとりする。v0.9までは、”数字:::JSON” だった

“0” – 接続時にsession idなどを通知
0{"sid":"tOqSjGeyyhBo5x3vAAAA","upgrades":[],"pingInterval":25000,"pingTimeout":60000}

“41” – 切断
サーバーで明示的にsocket.disconnect()した時にクライアントに送られてくる
ただ “41” だけが送られてくる。


“42” – data
サーバーでemit(‘chat’, {msg: “hello”}, {foo: “bar”})した場合
42["chat",{"msg":"hello"},{"foo":"bar"}]
が送られてくる
送信時も42を付けて配列のJSONで送る


“1:6” – fast upgrade
はやくwebsocketにupgradeしろって指示をサーバーからクライアントに送る


“2” – ping
clientからserverへのping


“3” – pong
pingを受けての、serverからclientへのpong。これがすぐ返ってこなかったら、前段のnginxか何かにsocketがつながっているだけで、バックエンドのsocket.ioサーバーが息してないと判断できる


“2probe” – ajax ping
“3probe” – ajax pong

“5” – upgrade
ajax-pollingからwebsocketにupgradeする時にクライアントからサーバーに送る


heartbeatの手順が変わった

v0.9まで
サーバーが “2::” を送ってくるので、clientはすぐに”2::”を返す

v1.0以降
clientが”2″を送るとサーバーがすぐに”3″を返す
clientは接続してからすぐにサーバーに2を送らないと数秒で切られる

接続時の”0″で指定されたpingIntetrval(ミリ秒)毎に”2″を送ればok

この変更はすごく良い。普通TCP socketだとクライアントはなにかパケットを送ってみないと切断を検知できないので、今まで切断検知の為だけにnull送ってて無駄だった。

サーバーは何もしなくてももともと切断検知できるできる


io.configureが無くなった

log levelの設定はdebug npmを使う


io.connected

クライアントライブラリ側で接続状態を確認するio.socket.connectedがio.connectedに移動してた


シングルトン

client libは複数インスタンスを作っても、同じサーバーへの接続ならコネクションが共有される(単にキャッシュされた同じインスタンスが返ってくる)


client npmのIPアドレスが取得できない

socket.io-client npmからの接続のみ、サーバー側でクライアントのIPアドレスが取得できない
v0.9ではsocket.handshake.address.addressに入っていた
ブラウザjsからの場合、socket.handshake.address.address に入っている
client npmからだとaddressがnull


encoding

全体がUTF-8でエンコーディングされるようになった

0

twitterでエゴサーチしてslackに流す

https://github.com/shokai/twitter-egosearch-slack




こういう設定ファイル書いておくとtweetをslackのchannelに流してくれる

twitter:
user: shokai

slack:
team: "your-tean-name"
channel: "#general"
token: "your-slackbot-token"

words:
- "shokai.org"
- "橋本商会"
- "github.com/shokai"
- "shokai.github"

ignore:
users:
- bot
- shokai_twit
- shokai_bot
- shokai_log
- end_0606_shokai
- kirakira
- rurourafale
- YADAYOOOOOO
- aine0120
- K_T_Hotel_Annex
- sho1nco
- koyoshokai
words:
- shokai_bot
- shopping.yahoo
- キラキラ商会
- kirakira
- ビリケン

0

IRKitで一番2ch実況が盛り上がってるテレビチャンネルを追跡する

IRKitと、10行ぐらいのRubyでこんなに簡単にテレビ視聴が自動化できる。
見たい番組とか考えなくていいじゃないかみんなが実況してる番組は多分面白い。

手順

必要なgemをインストールし
% gem install irkit httparty nokogiri


irkitコマンドで各テレビ局の名前で赤外線データを学習しておいて
% irkit -get テレビ東京
% irkit -get NHK総合
% irkit -get NHK教育


実況勢い観測 – 現在の勢いからスクレイピングしてきて、一番盛り上がってるチャンネルに合わせる。

irkit-2ch-tv.rb
require 'irkit'
require 'nokogiri'
require 'httparty'

page = Nokogiri.parse HTTParty.get("http://bc2ch.net/").body

td = page.xpath('//table[@class="sitetotal"]//td[@class="station"]')
channels = td.map{|i| i.text }
ch = channels.first # 一番盛り上がってるチャンネル

irkit = IRKit::Device.find.first
ir_data = IRKit::App::Data["IR"][ch] # 局名に対応した赤外線データ

irkit.post_messages ir_data # 赤外線発射

このスクリプトをcrontabとかに追加して、5分ごととか定期的に実行すれば自動的に一番盛り上がってる番組を追える。

% crontab -e
*/10 * * * * cd /path/to/irkit-2ch-tv/ && bundle exec ruby irkit-2ch-tv.rb > /dev/null 2>&1


若干エラーハンドリングなどを追加したバージョンをgithubに置いておいた。
https://github.com/shokai/irkit-2ch-tv

あとはテレビを買うだけだ・・・(大学にはある)