app.rb
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
#!/usr/bin/env ruby -I ../lib -I lib # coding: utf-8 require 'sinatra' set :server, 'thin' connections = [] set :bind, '0.0.0.0' 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| connections << out out.callback { connections.delete(out) } end end post '/' do connections.each { |out| out << "data: #{params[:msg]}\n\n" } 204 # response without entity body end __END__ @@ layout <html> <head> <title>shitchat</title> <meta charset="utf-8" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <style> body { color: #c5c8c6; font: monospace; text-align: left; overflow-y: hidden; background-color: #241e1e; } #chat { height: 50vh; overflow-y: hidden; display: flex; flex-direction: column-reverse; } #msg { width: 100% }; </style> </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) { $('#chat').prepend('<span>' + e.data + '<span>' ) }; // writing $("form").on('submit', function(e) { $.post('/', {msg: "<%= user %>: " + $('#msg').val()}); $('#msg').val(''); $('#msg').focus(); e.preventDefault(); }); </script>