public
Last active

  • Download Gist
chat.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
#!/usr/bin/env ruby -I ../lib -I lib
# coding: utf-8
require 'rtoken'
require 'json'
 
require 'sinatra/base'
require 'thin'
 
class Chat < Sinatra::Base
 
enable :inline_templates
 
@@connections = {}
 
def self.start_timers
# send alive signal
EM.add_periodic_timer(5) do
@@connections.each_pair do |k, v|
h = {alive: true, conn_id: k}
v[:connection] << "data: #{h.to_json}\n\n"
end
end
 
# clear dead connections
EM.add_periodic_timer(10) do
now = Time.now
@@connections.each_pair do |k, v|
if now - v[:last_activity] >= 10
v[:connection].close
@@connections.delete(k)
end
end
end
end
 
get '/' do
halt erb(:login) unless params[:user]
erb :chat, :locals => { :user => params[:user].gsub(/\W/, '') }
end
 
get '/stream', :provides => 'text/event-stream' do
stream :keep_open do |out|
conn_id = RToken.rtoken(size: 8, lowercase: true)
@@connections[conn_id] = {
:connection => out,
:last_activity => Time.now
}
out.callback { @@connections.delete(conn_id) }
end
end
 
post '/' do
if params[:alive]
conn_id = params[:alive]
conn = @@connections[conn_id]
conn[:last_activity] = Time.now if conn
else
json = {msg: params[:msg]}.to_json
@@connections.each_pair do |k, v|
v[:connection] << "data: #{json}\n\n"
end
end
204 # response without entity body
end
end
 
EM.run do
Thin::Server.start Chat, 'localhost', 4567
Chat.start_timers
end
 
__END__
 
@@ layout
<html>
<head>
<title>Super Simple Chat with Sinatra</title>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body><%= yield %></body>
</html>
 
@@ login
<form action='/'>
<label for='user'>User Name:</label>
<input name='user' value='' />
<input type='submit' value="GO!" />
</form>
 
@@ chat
<pre id='chat'></pre>
<form>
<input id='msg' placeholder='type message here...' />
</form>
 
<script>
// reading
var es = new EventSource('/stream');
es.onmessage = function(e) {
// ask if the connection is alive
data = JSON.parse(e.data)
if(data.alive) {
$.post('/', {alive: data.conn_id});
} else {
$('#chat').append(data.msg + "\n")
}
};
 
// writing
$("form").on('submit',function(e) {
$.post('/', {msg: "<%= user %>: " + $('#msg').val()});
$('#msg').val(''); $('#msg').focus();
e.preventDefault();
});
</script>

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.