Last active
March 28, 2018 22:57
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment