他のことをしていても投稿に気づきやすいチャット作ってみた
sinatra + websocket + webkitNotificationのなせる技。
まあ、ただのチャットですが、投稿したときにNotificationの機能を使って、ブラウザの状態に関係なくメッセージが見れるようになっています。
一応、ブログ用に必要最小限の要素にまとめたつもりです。
古橋さんのページを参考にしています。
http://d.hatena.ne.jp/viver/20100717/p1
今回はwebsocketを簡単に使うためにrev-websocketを利用させて頂いてます。
必要なパッケージをインストールしておきます。
gem install sinatra
gem install rev-websocket
あと、実行手順は
- ruby main_server.rbでサーバーを起動
- chromeでlocalhost:8080にアクセス
- Notificationを許可して、テキストボックスに何か打ち込めば以下の写真のようになるはず。Notificationはブラウザを最小化してても表示されるので、仕事中のコミュニケーションとかに使えそうです?
必要なコードは以下の3つです。
main_server.rb
#!/usr/bin/env ruby fork { load 'chat_server.rb' exit 0 } require 'rubygems' require 'sinatra' get '/' do erb :index end set :port, 8080
chat_server.rb
require 'rubygems' require 'rev/websocket' $sockets = {} # Rev::WebSocketを継承したクラスを作成 class MyConnection < Rev::WebSocket # 接続されたら呼ばれる def on_open # 接続先に追加 $sockets[self] = self # 全員に通知 $sockets.each_key do |sock| sock.send_message("join in #{peeraddr[2]}") end end # メッセージが届いたら呼ばれる def on_message(data) $sockets.each_key do |sock| sock.send_message(data) end end # 切断されたら呼ばれる def on_close # 接続先から削除 $sockets.delete(self) $sockets.each_key do |sock| sock.send_message("break away #{peeraddr[2]}") end end end ws = Rev::WebSocketServer.new('0.0.0.0', 8081, MyConnection) ws.attach(Rev::Loop.default) Rev::Loop.default.run
views/index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta content="text/css" http-equiv="content-style-type" /> <meta content="text/javascript" http-equiv="content-script-type" /> <title>Chat with notification</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script> WS_URL = "ws://localhost:8081"; SHOW_TIME = 5000; var global = this; $(document).ready(function(){ function show_message(message) { str = "<p><span class='time'>"+new Date()+"</span> "+message+"</p>" $("#message").append(str); } show_message("connecting to "+WS_URL+"..."); ws = new WebSocket(WS_URL); ws.onopen = function() { show_message("connected."); } ws.onclose = function() { show_message("disconnected..."); } ws.onerror = function(msg) { show_message("failed to connect:"+msg); } ws.onmessage = function(event) { show_message(event.data); if(!window.webkitNotifications.checkPermission()) { var notify = window.webkitNotifications; var popup = notify.createNotification("", "Pushed Message", event.data); popup.show(); setTimeout(function() { popup.cancel(); }, SHOW_TIME); } else { if(window.webkitNotifications) { show_message("failed to notify."); } } } // Notification利用の許可 $("#request-permission").click(function(e) { e.preventDefault(); if(window.webkitNotifications.checkPermission()) { window.webkitNotifications.requestPermission(function() { if(cd) { cd(window.webkitNotifications.checkPermission() == 0); } }); } }); }); </script> </head> <body> <a href="#" class="submit" id="request-permission">WebNotificationによる通知許可</a><br> <input id="input" type="text" onChange="javascript:ws.send(this.value);this.value='';"/> メッセージを入力してEnterで投稿<br> <pre> <div id="message"></div> </pre> </body>
古橋さんの作ったMessagePack-RPCとかを使って、オンラインゲームっぽいもの作ったり何だりしてますが、それは追々まとめながら投稿したいと思います・・・