web_socket_chat_server 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +2 -0
- data/lib/web_socket_chat_server/version.rb +3 -0
- data/lib/web_socket_chat_server.rb +414 -0
- data/web_socket_chat_server.gemspec +25 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 908c10e8b6e1d6907c83b755b5698882957ecd97
|
4
|
+
data.tar.gz: 2b8c2ff2b5beb46cc2bb995c36901193b25b5e94
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a1cebe92b3d42bfdaae20a4c8f47f5f33cb544e0009fe16eb0a38269a05b2ef13ed05f83db39d38f5d7a0fc33ab442313106338208370282e40473607dd184ad
|
7
|
+
data.tar.gz: 8b410fa05463db45710a2676f0e653df42dec982b8e04f05a8b7690e62fe29e6eebac47c72a9ffd0cd45715e68e736127649387c879d26728d0954e737080527
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Jone Samra
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# WebSocketChatServer
|
2
|
+
|
3
|
+
A wrapper class for em-websocket (https://github.com/igrigorik/em-websocket) implementing a custom chat server protocol.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'web_socket_chat_server'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install web_socket_chat_server
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
An example on how to run the server:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require "web_socket_chat_server.rb"
|
27
|
+
|
28
|
+
admin1 = WebSocketChatServer::ChatUser.new(:username => "admin", :password => "secret")
|
29
|
+
admin2 = WebSocketChatServer::ChatUser.new(:username => "admin2", :password => "secret2")
|
30
|
+
admins = []
|
31
|
+
admins << admin1
|
32
|
+
admins << admin2
|
33
|
+
|
34
|
+
chat = WebSocketChatServer::ChatServer.new(:host=> "0.0.0.0", :port => "8080", :admins => admins)
|
35
|
+
|
36
|
+
chat.start_server do |response|
|
37
|
+
puts response
|
38
|
+
end
|
39
|
+
|
40
|
+
['TERM', 'INT'].each do |signal|
|
41
|
+
trap(signal){
|
42
|
+
chat.stop_server()
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
wait = gets
|
47
|
+
```
|
48
|
+
|
49
|
+
The code above creates an array consisting of two admins (ChatUser objects) and passes them to initialize(). The server will listen on IP 0.0.0.0 and the port 8080 (Required parameters).
|
50
|
+
|
51
|
+
By running the code above, you do not need to do any other things. The class takes care of the of itself by handling the connections and the logic of the server’s custom protocol. You still though have the opportunity to print out the commands generated by the server by passing a block to the start_server() function as it has been done above.
|
52
|
+
|
53
|
+
On the client side, use the HTML WebSocket API to connect to the server. An example on a fully working Chat client will be attached to this repo (CHAT_CLIENT_EXAMPLE).
|
54
|
+
|
55
|
+
To explain how to connect to the server briefly:
|
56
|
+
|
57
|
+
You have to pass the query parameters username & password to the socket client when connecting.
|
58
|
+
|
59
|
+
On successful connection, you can send a JSON hash of the format {command: ”…”, data: ”…}
|
60
|
+
|
61
|
+
### Available commands are:
|
62
|
+
{command: ”chat_message”, data: ”your message”}
|
63
|
+
|
64
|
+
{command: ”private_message”, data: {to_user: ”chuck_norris”, message: ”Private message”}}
|
65
|
+
|
66
|
+
{command: ”ban_user”, data: ”chuck_norris”}
|
67
|
+
|
68
|
+
|
69
|
+
The server will respond with a JSON hash of the format {command: ”…”, data: ”…”, information: ”…”}
|
70
|
+
|
71
|
+
### Available responses are:
|
72
|
+
{command: ”failed_connection”, data: nil, information: ”Some details”}
|
73
|
+
|
74
|
+
{command: ”successful_connection”, data: array_of_connected_users, information: ”Some details”}
|
75
|
+
|
76
|
+
{command: ”new_connection”, data: username, information: ”A new connected user”}
|
77
|
+
|
78
|
+
{command: ”chat_message”, data: {from_user: ”chuck_norris”, message: ”The message”}, information: ”Some details.”}
|
79
|
+
|
80
|
+
{command: ”ban_user”, data: TRUE or FALSE, information: ”Some details.”}
|
81
|
+
|
82
|
+
{command: ”private_message”, data: {from_user: ”chuck_norris”, message: ”The message”}, information: ”Some details.”}
|
83
|
+
|
84
|
+
{command: ”system_information”, data: ”Issue”, information: ”Some details.”}
|
85
|
+
|
86
|
+
{command: ”user_disconnected”, data: ”username”, information: ”Some details.”}
|
87
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,414 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require "em-websocket"
|
3
|
+
require "json"
|
4
|
+
module WebSocketChatServer
|
5
|
+
|
6
|
+
# A wrapper class for em-websocket (https://github.com/igrigorik/em-websocket) implementing a custom chat server protocol.
|
7
|
+
|
8
|
+
class ChatServer
|
9
|
+
# An array of string containing the banned usernames.
|
10
|
+
attr_accessor :banned_usernames
|
11
|
+
|
12
|
+
# The max number of allowed client connections.
|
13
|
+
attr_accessor :max_connections
|
14
|
+
|
15
|
+
# An array of ChatUser objects representing the admins of the chat.
|
16
|
+
attr_reader :admins
|
17
|
+
|
18
|
+
# A hash containing the connected users. The key contains of the user's username and the value is a ChatUser object.
|
19
|
+
attr_reader :connected_users
|
20
|
+
|
21
|
+
# The host address.
|
22
|
+
attr_reader :host
|
23
|
+
|
24
|
+
# The socket port to be used.
|
25
|
+
attr_reader :port
|
26
|
+
|
27
|
+
# The class initializer
|
28
|
+
# ==== args
|
29
|
+
# * +:server+ (Required) - The host of the chat server to run on.
|
30
|
+
# * +:port+ (Required) - The port of the server.
|
31
|
+
# * +:max_connections+ (Optional) - The max client connections allowed. If not passed, the default is 100.
|
32
|
+
# * +:secure+ (Optional) - In case of using Secure Servers, pass true as allowed by em-websocket (https://github.com/igrigorik/em-websocket#secure-server).
|
33
|
+
# * +:tls-options+ (Optional) - The TLS options as allowed by em-websocket (https://github.com/igrigorik/em-websocket#secure-server).
|
34
|
+
# * +:secure_proxy+ (Optional) - When ruinng behind a SSL proxy (https://github.com/igrigorik/em-websocket#running-behind-an-ssl-proxyterminator-like-stunnel).
|
35
|
+
# * +:admins+ (Optional) - In order to have admins (for banning users). Pass an array of ChatUser objects to this key. The ChatUser object contains of username and password attributes. The username must consist of at least 3 alphanumeric characters. The password must at least consist of 6 alphanumeric characters.
|
36
|
+
def initialize(args = {:host => "0.0.0.0", :port => 8080})
|
37
|
+
raise ArgumentError, "The :host parameter is required" unless args.has_key?(:host)
|
38
|
+
raise ArgumentError, "The :port parameter is required" unless args.has_key?(:port)
|
39
|
+
raise ArgumentError, "The port value is not valid" unless valid_port?( args[:port])
|
40
|
+
@max_connections = args[:max_connections].to_s.to_i
|
41
|
+
@max_connections = 100 if @max_connections == 0
|
42
|
+
@host = args[:host]
|
43
|
+
@port = args[:port]
|
44
|
+
@server_started = false
|
45
|
+
@admins = []
|
46
|
+
@banned_usernames = []
|
47
|
+
@connected_users = Hash.new
|
48
|
+
|
49
|
+
@server_options = Hash.new
|
50
|
+
@server_options[:host] = @host
|
51
|
+
@server_options[:port] = @port.to_i
|
52
|
+
@server_options[:secure] = args[:secure] if args.has_key?(:secure)
|
53
|
+
@server_options[:tls_options] = args[:tls_options] if args.has_key?(:tls_options)
|
54
|
+
@server_options[:secure_proxy] = args[:secure_proxy] if args.has_key?(:secure_proxy)
|
55
|
+
|
56
|
+
|
57
|
+
if args.has_key?(:admins)
|
58
|
+
if args[:admins].class == Array
|
59
|
+
args[:admins].each { |chat_user|
|
60
|
+
if chat_user.class == ChatUser
|
61
|
+
raise RuntimeError, "The admin's username has to be at least 3 alphanumeric characters, and the password at least 6 alphanumeric characters" unless user_credentials_valid?(chat_user.username, chat_user.password)
|
62
|
+
@admins << chat_user unless @admins.include?(chat_user)
|
63
|
+
end
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# To start the server, call this method. It will return true if successful, false if it is already started. Otherwise, RuntimeError will be raised on errors. If giving a <b>block</b>, A hash <b>{command: "...", data: "...", information: "..."}</b> is yield.
|
70
|
+
def start_server()
|
71
|
+
return false if @server_started
|
72
|
+
|
73
|
+
begin
|
74
|
+
Thread.new {run_server() do |response|
|
75
|
+
yield response if block_given?
|
76
|
+
end
|
77
|
+
}
|
78
|
+
rescue Exception => e
|
79
|
+
@server_started = false
|
80
|
+
raise RuntimeError, e.message
|
81
|
+
end
|
82
|
+
|
83
|
+
until @server_started
|
84
|
+
next
|
85
|
+
end
|
86
|
+
|
87
|
+
@server_started
|
88
|
+
end
|
89
|
+
|
90
|
+
# To stop the server, call this method. True if the server is stopped, false if it is already stopped. Otherwise, RuntimeError is raised on errors.
|
91
|
+
def stop_server()
|
92
|
+
return false unless @server_started
|
93
|
+
@server_started = false
|
94
|
+
@banned_usernames.clear if @banned_usernames.count > 0
|
95
|
+
@admins.clear if @admins.count > 0
|
96
|
+
@connected_users.clear if @connected_users.count > 0
|
97
|
+
begin
|
98
|
+
EM::WebSocket.stop()
|
99
|
+
rescue Exception => e
|
100
|
+
raise RuntimeError, e.message
|
101
|
+
end
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns true if the server is started, otherwise false.
|
106
|
+
def started?()
|
107
|
+
@server_started
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
# This method will fire the eventmachine and the containing em-socket.
|
112
|
+
def run_server()
|
113
|
+
@server_started = true
|
114
|
+
|
115
|
+
EM.run do
|
116
|
+
EM::WebSocket.run(@server_options) do |ws|
|
117
|
+
ws.onopen { |handshake|
|
118
|
+
begin
|
119
|
+
response = nil
|
120
|
+
if (@connected_users.count + 1) > @max_connections
|
121
|
+
response = create_response_json("failed_connection", nil, "The max connections limit is reached.")
|
122
|
+
yield response if block_given?
|
123
|
+
ws.send(response)
|
124
|
+
ws.close
|
125
|
+
break
|
126
|
+
end
|
127
|
+
|
128
|
+
username = handshake.query["username"]
|
129
|
+
password = handshake.query["password"]
|
130
|
+
client_ip = Socket.unpack_sockaddr_in(ws.get_peername)[1]
|
131
|
+
user = ChatUser.new({:username => username, :password => password, :ip => client_ip})
|
132
|
+
|
133
|
+
if username.nil? || password.nil?
|
134
|
+
response = create_response_json("failed_connection", nil, "The username & password have to be passed in the query string.")
|
135
|
+
yield response if block_given?
|
136
|
+
ws.send(response)
|
137
|
+
ws.close
|
138
|
+
break
|
139
|
+
end
|
140
|
+
|
141
|
+
if admin_credentials_invalid?(username, password)
|
142
|
+
response = create_response_json("failed_connection", nil, "Invalid credentials.")
|
143
|
+
yield response if block_given?
|
144
|
+
ws.send(response)
|
145
|
+
ws.close
|
146
|
+
break
|
147
|
+
end
|
148
|
+
|
149
|
+
if user_credentials_valid?(username, password) == false
|
150
|
+
response = create_response_json("failed_connection", nil, "Invalid user creadentials. The username has to be at least 3 alphanumeric characters, and the password at least 6 alphanumeric characters.")
|
151
|
+
yield response if block_given?
|
152
|
+
ws.send(response)
|
153
|
+
ws.close
|
154
|
+
break
|
155
|
+
end
|
156
|
+
|
157
|
+
if user_banned?(user)
|
158
|
+
response = create_response_json("failed_connection", nil, "The user is banned")
|
159
|
+
yield response if block_given?
|
160
|
+
ws.send(response)
|
161
|
+
ws.close
|
162
|
+
break
|
163
|
+
end
|
164
|
+
|
165
|
+
number_of_tries = 0
|
166
|
+
while user_exists?(user)
|
167
|
+
number_of_tries = number_of_tries + 1
|
168
|
+
user.username = user.username + Random.rand(1..9999).to_s
|
169
|
+
|
170
|
+
if number_of_tries > 15
|
171
|
+
response = create_response_json("failed_connection", nil, "The username exists already.")
|
172
|
+
yield response if block_given?
|
173
|
+
ws.send(response)
|
174
|
+
ws.close
|
175
|
+
break
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
user.connection = ws
|
180
|
+
|
181
|
+
response = create_response_json("successful_connection", connected_users_to_array, "Connection accepted")
|
182
|
+
yield response if block_given?
|
183
|
+
ws.send(response)
|
184
|
+
|
185
|
+
@connected_users[user.username] = user
|
186
|
+
response = create_response_json("new_connection", user.username, "A new user is connected.")
|
187
|
+
yield response if block_given?
|
188
|
+
broadcast_message(response)
|
189
|
+
end while false
|
190
|
+
}
|
191
|
+
ws.onmessage { |msg|
|
192
|
+
json_data = nil
|
193
|
+
command = ""
|
194
|
+
data = ""
|
195
|
+
user = nil
|
196
|
+
begin
|
197
|
+
user = get_user_by_connection(ws)
|
198
|
+
|
199
|
+
if user.nil?
|
200
|
+
ws.close
|
201
|
+
break
|
202
|
+
end
|
203
|
+
|
204
|
+
begin
|
205
|
+
json_data = JSON.parse(msg)
|
206
|
+
command = json_data["command"]
|
207
|
+
data = json_data["data"]
|
208
|
+
rescue
|
209
|
+
break
|
210
|
+
end
|
211
|
+
|
212
|
+
case command
|
213
|
+
when "chat_message"
|
214
|
+
break if data == ""
|
215
|
+
response = create_response_json("chat_message", {"from_user" => user.username, "message" => data}, "A chat message.")
|
216
|
+
yield response if block_given?
|
217
|
+
broadcast_message(response)
|
218
|
+
break
|
219
|
+
|
220
|
+
when "ban_user"
|
221
|
+
break if data == ""
|
222
|
+
unless user_admin?(user)
|
223
|
+
ws.close
|
224
|
+
break
|
225
|
+
end
|
226
|
+
|
227
|
+
user_to_ban = get_user_by_username(data)
|
228
|
+
if user_to_ban.nil?
|
229
|
+
response = create_response_json("ban_user", false, "The user to ban did not exist.")
|
230
|
+
yield response if block_given?
|
231
|
+
ws.send(response)
|
232
|
+
break
|
233
|
+
end
|
234
|
+
|
235
|
+
if user_admin?(user_to_ban)
|
236
|
+
response = create_response_json("ban_user", false, "An admin user can not be banned.")
|
237
|
+
yield response if block_given?
|
238
|
+
ws.send(response)
|
239
|
+
break
|
240
|
+
end
|
241
|
+
|
242
|
+
@banned_usernames << user_to_ban.username
|
243
|
+
response = create_response_json("ban_user", true, "The user #{user_to_ban.username} has been banned.")
|
244
|
+
yield response if block_given?
|
245
|
+
ws.send(response)
|
246
|
+
user_to_ban.connection.close
|
247
|
+
break
|
248
|
+
|
249
|
+
when "private_message"
|
250
|
+
break unless data.is_a? Hash
|
251
|
+
break if data["to_user"].nil?
|
252
|
+
break if data["message"].nil?
|
253
|
+
|
254
|
+
user_to_receive = get_user_by_username(data["to_user"])
|
255
|
+
break if user_to_receive.nil?
|
256
|
+
|
257
|
+
response = create_response_json("private_message", {"from_user" => user.username, "message" => data["message"]}, "A private message.")
|
258
|
+
yield response if block_given?
|
259
|
+
user_to_receive.connection.send(response)
|
260
|
+
break
|
261
|
+
|
262
|
+
else
|
263
|
+
ws.send(create_response_json("system_information", "Unknown command", "Please make sure that you are sending the right command."))
|
264
|
+
ws.close
|
265
|
+
break
|
266
|
+
end
|
267
|
+
end while false
|
268
|
+
}
|
269
|
+
ws.onclose {
|
270
|
+
begin
|
271
|
+
break unless @server_started
|
272
|
+
deleted = nil
|
273
|
+
@connected_users.values.each do |u|
|
274
|
+
if u.connection == ws
|
275
|
+
name = u.username
|
276
|
+
deleted = @connected_users.delete(name)
|
277
|
+
response = create_response_json("user_disconnected", deleted.username, "The user is diconnected.")
|
278
|
+
yield response if block_given?
|
279
|
+
broadcast_message(response)
|
280
|
+
break unless deleted.nil?
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end while false
|
284
|
+
}
|
285
|
+
ws.onerror { |e|
|
286
|
+
|
287
|
+
unless e.kind_of?(EM::WebSocket::WebSocketError)
|
288
|
+
ws.close
|
289
|
+
end
|
290
|
+
|
291
|
+
}
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# This method is used privately. It will check if the passwed username belongs to an admin and that the password matches.
|
297
|
+
def admin_credentials_invalid?(username = "", password = "")
|
298
|
+
@admins.each do |admin|
|
299
|
+
return true if admin.username == username && admin.password != password
|
300
|
+
end
|
301
|
+
|
302
|
+
false
|
303
|
+
end
|
304
|
+
|
305
|
+
# This method is used privately to check if the username and password are valid. The username has to be at least 3 alphanumeric characters and the password 6 alphanumeric characters.
|
306
|
+
# It returns true if the credentials are valid, otherwise false.
|
307
|
+
def user_credentials_valid?(username = "", password = "")
|
308
|
+
return false if /\A\p{Alnum}{3,}\Z/.match(username).nil?
|
309
|
+
return false if /\A\p{Alnum}{6,}\Z/.match(password).nil?
|
310
|
+
|
311
|
+
true
|
312
|
+
end
|
313
|
+
|
314
|
+
# Returns true if the port number is valid.
|
315
|
+
def valid_port?(value)
|
316
|
+
return false if /\A[0-9]{1,6}\Z/.match(value).nil?
|
317
|
+
true
|
318
|
+
end
|
319
|
+
|
320
|
+
# Returns true if the user is banned.
|
321
|
+
def user_banned?(user)
|
322
|
+
if user.class == ChatUser
|
323
|
+
return @banned_usernames.include?(user.username)
|
324
|
+
end
|
325
|
+
|
326
|
+
@banned_usernames.include?(user)
|
327
|
+
end
|
328
|
+
|
329
|
+
# Returns true if the username is already added to the connected users.
|
330
|
+
def user_exists?(user)
|
331
|
+
@connected_users.include?(user.username)
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns true is the user is admin.
|
335
|
+
def user_admin?(user)
|
336
|
+
@admins.include?(user)
|
337
|
+
end
|
338
|
+
|
339
|
+
# Sends text/json to the connected clients.
|
340
|
+
def broadcast_message(message)
|
341
|
+
return false if @connected_users.count == 0
|
342
|
+
|
343
|
+
@connected_users.values.each do |u|
|
344
|
+
begin
|
345
|
+
u.connection.send(message) unless u.connection.nil?
|
346
|
+
rescue
|
347
|
+
next
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# Returns the ChatUser object bound to the socket connection.
|
353
|
+
def get_user_by_connection(connection)
|
354
|
+
return nil if @connected_users.count == 0
|
355
|
+
@connected_users.values.each do |user|
|
356
|
+
return user if user.connection == connection
|
357
|
+
end
|
358
|
+
|
359
|
+
nil
|
360
|
+
end
|
361
|
+
|
362
|
+
# Returns the ChatUser object by the username.
|
363
|
+
def get_user_by_username(username)
|
364
|
+
@connected_users[username]
|
365
|
+
end
|
366
|
+
|
367
|
+
# Creates the json object to be sent to the clients.
|
368
|
+
def create_response_json(command = "", data = nil, message = "")
|
369
|
+
{"command" => command, "data" => data, "information" => message}.to_json
|
370
|
+
end
|
371
|
+
|
372
|
+
def connected_users_to_array()
|
373
|
+
usernames = []
|
374
|
+
@connected_users.values.each do |u|
|
375
|
+
usernames << u.username
|
376
|
+
end
|
377
|
+
|
378
|
+
usernames
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|
382
|
+
|
383
|
+
|
384
|
+
class ChatUser
|
385
|
+
attr_accessor :username, :password, :connection, :ip
|
386
|
+
def initialize(args = {})
|
387
|
+
raise RuntimeError, "The username is not given" unless args.has_key?(:username)
|
388
|
+
raise RuntimeError, "The password is not given" unless args.has_key?(:password)
|
389
|
+
|
390
|
+
@connection = nil
|
391
|
+
@connection = args[:connection] if args.has_key?(:connection)
|
392
|
+
@ip = args[:ip] if args.has_key?(:ip)
|
393
|
+
@username = args[:username]
|
394
|
+
@password = args[:password]
|
395
|
+
end
|
396
|
+
|
397
|
+
def admin?()
|
398
|
+
@is_admin
|
399
|
+
end
|
400
|
+
|
401
|
+
def ==(object)
|
402
|
+
return false unless object.class == ChatUser
|
403
|
+
return username == object.username
|
404
|
+
end
|
405
|
+
|
406
|
+
def to_json(options = {})
|
407
|
+
{"user" => @username}.to_json
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'web_socket_chat_server/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "web_socket_chat_server"
|
8
|
+
spec.version = WebSocketChatServer::VERSION
|
9
|
+
spec.authors = ["Jone Samra"]
|
10
|
+
spec.email = ["jonemob@gmail.com"]
|
11
|
+
spec.summary = %q{A wrapper class for em-websocket (https://github.com/igrigorik/em-websocket) implementing a custom chat server protocol.}
|
12
|
+
spec.description = %q{For more details, please read the documentation at http://abulewis.com/doc/WebSocketChatServer.html}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
spec.required_ruby_version = ">= 2.0.0"
|
21
|
+
|
22
|
+
spec.add_runtime_dependency "em-websocket", "~> 0.5.1"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: web_socket_chat_server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jone Samra
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: em-websocket
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description: For more details, please read the documentation at http://abulewis.com/doc/WebSocketChatServer.html
|
56
|
+
email:
|
57
|
+
- jonemob@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- lib/web_socket_chat_server.rb
|
68
|
+
- lib/web_socket_chat_server/version.rb
|
69
|
+
- web_socket_chat_server.gemspec
|
70
|
+
homepage: ''
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.0.0
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.4.5
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: A wrapper class for em-websocket (https://github.com/igrigorik/em-websocket)
|
94
|
+
implementing a custom chat server protocol.
|
95
|
+
test_files: []
|