-
Notifications
You must be signed in to change notification settings - Fork 0
/
control.rb
123 lines (117 loc) · 4.19 KB
/
control.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
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
117
118
119
120
121
122
123
require 'date'
require 'erb'
require 'glorify'
require 'oj'
require 'rack'
require 'sinatra'
require 'sinatra-websocket'
require 'uri'
require_relative 'command.rb'
# Pretty sure this is 'websocket' as SHA256.
set :session_secret, '7ce54cbababdd64826b853179905315617306f430e5154177ddbed04c282b7da'
set :session_provider, 'sinatra' # 'rack'
set :server, 'thin'
set :bind, '0.0.0.0'
# This behemoth provides the user session.
if settings.session_provider == 'rack'
use Rack::Session::Cookie,
secret: settings.session_secret
else
enable :sessions
end
# Sockets are stored as a hash so I can lookup through name.
set :sockets, {}
set :logs, []
# Login section.
get '/' do
if not session['name'].nil?
redirect '/chat'
else
erb :index, locals: { error: nil }
end
end
post '/' do
if params.include? 'name'
response = erb :index, locals: { error: 'Incorrect password.' }
name = unxss(params['name']).gsub(' ', '_')
password = digest(params['password'])
all_clear = true
with_user(name) do |user|
if user.key? 'password'
if user['password'] != password
all_clear = false
end
end
end
if all_clear
if not params['password'].empty?
session['password'] = password
end
session['name'] = name
response = redirect '/chat'
end
response
else
redirect '/'
end
end
# Chat section.
get '/chat' do
if session['name'].nil? # User isn't logged in.
redirect '/'
else
if request.websocket?
request.websocket do |socket|
socket.onopen do
# Send them the GPL notice and any helpful commands.
socket.send(erb(:message_of_the_day))
# Add them to the userlist and notify everyone.
settings.sockets[session['name']] = socket
settings.sockets.each do |user, sockets|
sockets.send(erb(:message_user_join, locals: { name: session['name'] }))
end
with_user(session['name']) do |user|
user['password'] = session['password']
user['lastSeen'] = timestamp
if user.key? 'notes'
user['notes'].each do |hash|
hash.each do |name, note|
settings.sockets[session['name']].send(erb(:message_yell_command, locals: { name: name, text: note }))
end
end
end
user['notes'] = []
end
end
socket.onclose do
# Delete the socket connection so we don't crash.
settings.sockets.tap do |key|
key.delete(session['name'])
end
# Notify everyone that the user left.
settings.sockets.each do |user, socket|
socket.send(erb(:message_user_left, locals: { name: session['name'] }))
end
end
socket.onmessage do |message|
message = unxss(message)
if can_send? message, settings.sockets, session['name']
settings.sockets.each do |user, socket|
socket.send(erb(:message_user_public, locals: { name: session['name'], message: message, stamp: timestamp }))
settings.logs.push({ name: session['name'], message: message, stamp: timestamp })
settings.logs.uniq!
if settings.logs.length > 10
settings.logs.shift
end
end
end
with_user(session['name']) do |user|
user['lastSeen'] = timestamp
end
end
end
else
erb :chatroom
end
end
end