diff --git a/.gitignore b/.gitignore
index d49756d..48936ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/node_modules/
/build/
+/client.config.toml
diff --git a/client.config.example.toml b/client.config.example.toml
new file mode 100644
index 0000000..99398af
--- /dev/null
+++ b/client.config.example.toml
@@ -0,0 +1,9 @@
+[server]
+ port=8080
+
+[client]
+ username="teemant"
+ realname="A Teemant User"
+ default_quit_msg="Teemant IRC"
+ default_part_msg="Bye!"
+ secure_by_default=false
diff --git a/package.json b/package.json
index 15d685a..b12259c 100644
--- a/package.json
+++ b/package.json
@@ -13,9 +13,9 @@
"license": "MIT",
"dependencies": {
"express": "^4.14.0",
- "jade": "^1.11.0",
"morgan": "^1.7.0",
- "socketio": "^1.0.0"
+ "socketio": "^1.0.0",
+ "toml": "^2.3.0"
},
"repository": {
"type": "git",
diff --git a/public/css/main.css b/public/css/main.css
index 8edb0cf..41ec308 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -376,7 +376,11 @@ body {
color: #03a9f4;
font-weight: bold;
}
-.message.m_nick .content {
+.message.m_motd .content {
+ font-family: monospace;
+}
+.message.m_nick .content,
+.message.m_notice .content {
color: #ff9800;
font-weight: bold;
}
diff --git a/public/image/settings.svg b/public/image/settings.svg
index 07405f0..bbe7c2b 100644
--- a/public/image/settings.svg
+++ b/public/image/settings.svg
@@ -27,4 +27,5 @@
+
diff --git a/public/js/main.js b/public/js/main.js
index a5fbae3..ff87060 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -4,6 +4,7 @@ window.irc = {
timestamps: true,
timestampFormat: "HH:mm:ss",
serverData: {},
+ serverChatQueue: {},
chatType: "simple"
};
@@ -125,6 +126,20 @@ Date.prototype.format = function (format, utc){
return format;
};
+function linkify(text) {
+ // see http://daringfireball.net/2010/07/improved_regex_for_matching_urls
+ let re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/gi;
+ let parsed = text.replace(re, function(url) {
+ // turn into a link
+ let href = url;
+ if (url.indexOf('http') !== 0) {
+ href = 'http://' + url;
+ }
+ return '' + url + '';
+ });
+ return parsed;
+}
+
function removeClass(element, cl) {
let classList = element.className.split(" ");
remove_str(classList, cl);
@@ -154,6 +169,8 @@ let composer = {
if(irc.timestamps)
element.innerHTML += ""+time.format(irc.timestampFormat)+" ";
+ message = linkify(message);
+
switch(type) {
case "action":
element.innerHTML += "* "+sender+" ";
@@ -250,6 +267,7 @@ class Nicklist {
}
nickAddObject(obj) {
+ if(this.getNickIndex(obj.nickname) != null) return;
this.nicks.push(obj);
}
@@ -424,7 +442,7 @@ class Buffer {
if(this.topic != null && this.topic != "") {
addClass(clientdom.chat, 'vtopic');
- clientdom.topicbar.innerHTML = this.topic;
+ clientdom.topicbar.innerHTML = linkify(this.topic);
}
this.renderMessages();
@@ -455,7 +473,7 @@ class Buffer {
topicChange(topic) {
if(this.active) {
- clientdom.topicbar.innerHTML = topic;
+ clientdom.topicbar.innerHTML = linkify(topic);
if(this.topic == null)
addClass(clientdom.chat, "vtopic");
@@ -463,8 +481,8 @@ class Buffer {
this.topic = topic;
}
- addMessage(message, sender, type) {
- let mesg = {message: message, sender: sender, type: type, time: new Date()}
+ addMessage(message, sender, type, time) {
+ let mesg = {message: message, sender: sender, type: type, time: time || new Date()}
this.messages.push(mesg);
if(this.active)
@@ -689,6 +707,15 @@ class IRCChatWindow {
this.buffers.push(newServer);
this.render(newServer);
this.firstServer = false;
+
+ if(irc.serverChatQueue[serverinfo.address]) {
+ for(let a in irc.serverChatQueue[serverinfo.address]) {
+ let mesg = irc.serverChatQueue[serverinfo.address][a];
+ newServer.addMessage(mesg.message, mesg.from, mesg.type, mesg.time);
+ }
+ delete irc.serverChatQueue[serverinfo.address];
+ }
+
}
createBuffer(server, name, type, autoswitch) {
@@ -918,16 +945,24 @@ window.onload = function() {
else if(data['topic'])
irc.chat.topicChange(data.channel, data.server, data.topic, null);
else if(data['set_by'])
- irc.chat.messageBuffer(data.channel, data.server, {message: "Topic set by "+data.set_by+" on "+new Date(data.time), type: "topic", from: null});
+ irc.chat.messageBuffer(data.channel, data.server, {message: "Topic set by "+data.set_by+" on "+new Date(data.time*1000), type: "topic", from: null});
break;
case "nick_change":
irc.chat.nickChange(data.server, data.nick, data.newNick);
break;
case "server_message":
- irc.chat.messageBuffer(data.server, data.server, {message: data.message, type: data.messageType, from: null});
+ if(irc.chat.getBuffersByServer(data.server).length == 0) {
+ if(!irc.serverChatQueue[data.server]) {
+ irc.serverChatQueue[data.server] = [];
+ } else {
+ irc.serverChatQueue[data.server].push({type: data.messageType, message: data.message, from: data.from || null, time: new Date()});
+ }
+ } else {
+ irc.chat.messageBuffer(data.server, data.server, {message: data.message, type: data.messageType, from: data.from || null});
+ }
break;
case "connect_message":
- irc.auther.authMessage(data.data, data.error);
+ irc.auther.authMessage(data.message, data.error);
break;
}
});
diff --git a/public/main.styl b/public/main.styl
index e4f3442..607d462 100644
--- a/public/main.styl
+++ b/public/main.styl
@@ -322,7 +322,9 @@ body
&.m_topic .content
color: #03A9F4;
font-weight: bold;
- &.m_nick .content
+ &.m_motd .content
+ font-family: monospace;
+ &.m_nick .content, &.m_notice .content
color: #FF9800;
font-weight: bold;
&.m_action .actionee
diff --git a/server/config.js b/server/config.js
new file mode 100644
index 0000000..10656d9
--- /dev/null
+++ b/server/config.js
@@ -0,0 +1,14 @@
+let fs = require('fs');
+let toml = require('toml');
+let filename = __dirname+'/../client.config.toml';
+
+let config;
+
+try {
+ config = toml.parse(fs.readFileSync(filename));
+} catch (e) {
+ throw 'config.toml parse error: ' + e;
+ console.error(e.stack);
+}
+
+module.exports = config;
diff --git a/server/irc.js b/server/irc.js
new file mode 100644
index 0000000..9593eb3
--- /dev/null
+++ b/server/irc.js
@@ -0,0 +1,284 @@
+let EventEmitter = require('events').EventEmitter;
+let net = require('net');
+let configuration = require(__dirname+"/config");
+let parse = require(__dirname+"/parser");
+
+let defaultConfig = {
+ nickname: "teemant",
+ username: configuration.client.username,
+ realname: configuration.client.realname,
+ server: "localhost",
+ port: 6667,
+ autojoin: [],
+ secure: configuration.client.secure_by_default,
+ password: "",
+ address: "0.0.0.0"
+}
+
+if (!String.prototype.format) {
+ String.prototype.format = function() {
+ var args = arguments;
+ return this.replace(/{(\d+)}/g, function(match, number) {
+ return typeof args[number] != undefined ? args[number] : match;
+ });
+ };
+}
+
+class ConfigPatcher {
+ constructor(provided, defaults) {
+ this.result = defaults;
+ this.patches = provided;
+ }
+
+ patch() {
+ for(let a in this.patches) {
+ this.result[a] = this.patches[a];
+ }
+ return this.result;
+ }
+}
+
+class IRCConnectionHandler {
+ constructor(connection) {
+ this.conn = connection;
+ }
+
+ handleServerLine(line) {
+ console.log(line);
+ if(this.conn.queue["supportsmsg"] && line.command != "005") {
+
+ delete this.conn.queue["supportsmsg"];
+
+ if(this.conn.config.autojoin.length > 0)
+ for(let t in this.conn.config.autojoin)
+ this.conn.socket.write('JOIN {0}\r\n'.format(this.conn.config.autojoin[t]));
+
+ this.conn.emit('authenticated', {});
+ }
+
+ let serverName = this.conn.config.server;
+ let realServerName = this.conn.data.actualServer;
+
+ switch(line.command) {
+ case "error":
+ this.conn.emit("error", {type: "irc_error", raw: line.raw});
+ break;
+ case "001":
+ this.conn.data.actualServer = line.user.host;
+ break
+ case "005":
+ if(!this.conn.queue["supportsmsg"])
+ this.conn.queue["supportsmsg"] = true;
+
+ let argv = line.arguments.slice(1);
+ for(let a in argv) {
+ let t = argv[a];
+ if(t.indexOf('=') != -1) {
+ t = t.split('=');
+ if(t[0] === 'PREFIX') {
+ let d = t[1].match(/\((\w+)\)(.*)/);
+ let r = d[1].split('');
+ let aa = d[2].split('');
+ for(let b in r)
+ this.conn.data.supportedModes[r[b]] = aa[b];
+ } else if(t[0] === 'NETWORK') {
+ this.conn.data.network = t[1];
+ }
+
+ this.conn.data.serverSupports[t[0]] = t[1];
+ } else {
+ this.conn.data.serverSupports[t] = true;
+ }
+ }
+ break;
+ case "JOIN":
+ this.conn.emit('pass_to_client', {type: "event_join_channel", user: line.user, channel: line.trailing, server: serverName });
+ break;
+ case "PART":
+ this.conn.emit('pass_to_client', {type: "event_part_channel", user: line.user, channel: line.arguments[0], reason: line.trailing, server: serverName });
+ break;
+ case "QUIT":
+ this.conn.emit('pass_to_client', {type: "event_quit", user: line.user, reason: line.trailing, server: serverName });
+ break;
+ case "353":
+ if(!this.conn.queue["names"])
+ this.conn.queue['names'] = {};
+
+ let splittrail = line.trailing.split(' ');
+ for(let a in splittrail) {
+ let nick = splittrail[a];
+ if(nick.trim() == "") continue;
+ if(this.conn.queue["names"][line.arguments[2]])
+ this.conn.queue["names"][line.arguments[2]].push(nick);
+ else
+ this.conn.queue["names"][line.arguments[2]] = [nick];
+ }
+
+ break;
+ case "366":
+ if(!this.conn.queue["names"]) break;
+ if(this.conn.queue["names"][line.arguments[1]]) {
+ this.conn.emit('pass_to_client', {type: "channel_nicks", channel: line.arguments[1], nicks: this.conn.queue["names"][line.arguments[1]], server: serverName});
+ delete this.conn.queue["names"][line.arguments[1]];
+ }
+
+ if(Object.keys(this.conn.queue["names"]).length == 0)
+ delete this.conn.queue["names"];
+ break;
+ case "PRIVMSG":
+ let type = "privmsg";
+
+ if(line.trailing.indexOf('\x01ACTION') == 0) {
+ line.trailing = line.trailing.substring(8);
+ line.trailing.substring(0, line.trailing.length-1);
+ type = "action";
+ }
+
+ if(line.user.nickname != "")
+ this.conn.emit('pass_to_client', {type: "message", messageType: type, to: line.arguments[0],
+ user: line.user, message: line.trailing, server: serverName});
+ else
+ this.conn.emit('pass_to_client', {type: "server_message", messageType: type, message: line.trailing, server: serverName, from: realServerName});
+ break;
+ case "NOTICE":
+ if(line.user.nickname != "")
+ this.conn.emit('pass_to_client', {type: "message", messageType: "notice", to: line.arguments[0],
+ user: line.user, message: line.trailing, server: serverName});
+ else
+ this.conn.emit('pass_to_client', {type: "server_message", messageType: "notice", message: line.trailing, server: serverName, from: realServerName});
+ break;
+ case "NICK":
+ this.conn.emit('pass_to_client', {type: "nick_change", nick: line.user.nickname, newNick: line.arguments[0], server: serverName});
+ break;
+ case "KICK":
+ this.conn.emit('pass_to_client', {type: "event_kick_channel", user: line.user, channel: line.arguments[0], kickee: line.arguments[1], server: serverName});
+ break;
+ case "TOPIC":
+ this.conn.emit('pass_to_client', {type: "channel_topic", channel: line.arguments[0], set_by: line.user.nickname, topic: line.trailing, server: serverName});
+ break;
+ case "332":
+ this.conn.emit('pass_to_client', {type: "channel_topic", channel: line.arguments[1], topic: line.trailing, server: serverName});
+ break;
+ case "333":
+ this.conn.emit('pass_to_client', {type: "channel_topic", channel: line.arguments[1], set_by: line.arguments[2], time: line.arguments[3], server: serverName});
+ break;
+ case "375":
+ case "372":
+ case "376":
+ this.conn.emit('pass_to_client', {type: "server_message", messageType: "motd", message: line.trailing, server: serverName, from: realServerName});
+ break;
+ case "251":
+ case "255":
+ this.conn.emit('pass_to_client', {type: "server_message", messageType: "regular", message: line.trailing, server: serverName, from: realServerName});
+ break;
+ case "252":
+ case "254":
+ case "042":
+ this.conn.emit('pass_to_client', {type: "server_message", messageType: "regular", message: line.arguments[1] +" "+ line.trailing, server: serverName, from: realServerName});
+ break;
+ }
+ }
+}
+
+class IRCConnection extends EventEmitter {
+ constructor(providedInfo) {
+ super();
+ let config_u = new ConfigPatcher(providedInfo, defaultConfig);
+
+ this.config = config_u.patch();
+ this.socket = null;
+ this.connected = false;
+ this.authenticated = false;
+
+ this.handler = new IRCConnectionHandler(this);
+
+ this.data = {
+ serverSupports: {},
+ network: this.config.server,
+ actualServer: this.config.server,
+ supportedModes: {}
+ };
+ this.queue = {};
+ }
+
+ on(...args) {
+ return super.on(...args)
+ }
+
+ emit(...args) {
+ return super.emit(...args);
+ }
+
+ connect() {
+ this.socket = net.createConnection(this.config.port, this.config.server, () => {
+ this.connected = true;
+ this.authenticate();
+ });
+
+ this.socket.setEncoding('utf8');
+ this.socket.setTimeout(3000);
+
+ this.socket.on('error', (data) => {
+ this.emit('error', {type: "sock_error", message: "A socket error occured.", raw: data});
+ });
+
+ this.socket.on('lookup', (err, address, family, host) => {
+ if(err) {
+ this.emit('error', {type: "resolve_error", message: "Failed to resolve host."});
+ } else {
+ this.emit('lookup', {address: address, family: address, host: host});
+ this.config.address = address;
+ }
+ });
+
+ let buffer = "";
+ this.socket.on('data', (chunk) => {
+ buffer += chunk;
+ let data = buffer.split('\r\n');
+ buffer = data.pop();
+ data.forEach((line) => {
+ if(line.indexOf('PING') === 0) {
+ this.socket.write('PONG'+line.substring(4)+'\r\n');
+ return
+ }
+ this.emit('raw', line);
+ let parsed = parse(line);
+ this.emit('line', parsed);
+ this.handler.handleServerLine(parsed);
+ });
+ });
+
+ this.socket.on('close', (data) => {
+ if(this.queue['close'])
+ this.emit('closed', {type: "sock_closed_success", raw: data, message: "Connection closed."});
+ else
+ this.emit('closed', {type: "sock_closed", raw: data, message: "Connection closed."});
+
+ this.connected = false;
+ this.authenticated = false;
+ })
+ }
+
+ authenticate() {
+ if (this.config.password)
+ this.socket.write('PASS {0}\r\n'.format(this.config.password));
+
+ // TODO: WebIRC
+ this.socket.write('USER {0} 8 * :{1}\r\n'.format(this.config.username, this.config.realname));
+ this.socket.write('NICK {0}\r\n'.format(this.config.nickname));
+ }
+
+ disconnect(message) {
+ if(!this.connected) {
+ this.emit('error', {type: "sock_closed", message: "Connection already closed."});
+ return;
+ }
+
+ this.queue['close'] = true;
+ this.socket.write('QUIT :{0}\r\n'.format(message != null ? message : configuration.client.default_quit_msg));
+ }
+
+
+}
+
+module.exports = IRCConnection;
diff --git a/server/parser.js b/server/parser.js
new file mode 100644
index 0000000..dff41fc
--- /dev/null
+++ b/server/parser.js
@@ -0,0 +1,44 @@
+
+// :nickname!username@hostname command arg ume nts :trailing
+// or
+// :hostname command arg ume nts :trailing
+
+module.exports = function(rawline) {
+ let final = {
+ user: {
+ nickname: "",
+ username: "",
+ hostname: ""
+ },
+ command: "error",
+ arguments: [],
+ trailing: "",
+ raw: rawline
+ }
+
+ let pass1 = (rawline.indexOf(':') == 0 ? rawline.substring(1).split(" ") : rawline.split(" "));
+ if (pass1[0] === "ERROR")
+ return final;
+
+ if(pass1[0].indexOf("!") != -1) {
+ let nickuser = pass1[0].split('!');
+ final.user.nickname = nickuser[0];
+ let userhost = nickuser[1].split('@');
+ final.user.username = userhost[0];
+ final.user.hostname = userhost[1];
+ } else {
+ final.user.hostname = pass1[0];
+ }
+
+ final.command = pass1[1];
+
+ let pass2 = pass1.slice(2).join(" ");
+ if(pass2.indexOf(":") != -1) {
+ final.arguments = pass2.substring(0, pass2.indexOf(' :')).split(" ");
+ final.trailing = pass2.substring(pass2.indexOf(':')+1);
+ } else {
+ final.arguments = pass2.split(" ");
+ }
+
+ return final;
+}
diff --git a/teemant.js b/teemant.js
index 8cd3bf5..24073b0 100755
--- a/teemant.js
+++ b/teemant.js
@@ -2,10 +2,15 @@
'use strict';
let express = require("express");
let path = require("path");
-let sockio = require('socket.io');
+let sockio = require("socket.io");
+let dns = require("dns");
let app = express();
+
let pubdir = path.join(__dirname+"/public");
-let port = 8080;
+let config = require(__dirname+'/server/config');
+let ircclient = require(__dirname+'/server/irc');
+
+let port = config.server.port || 8080;
let connections = {}
@@ -19,6 +24,16 @@ let io = sockio.listen(app.listen(port, function() {
console.log("*** Listening on port " + port);
}));
+function resolveHostname(hostname) {
+ let promise = new Promise(function(resolve, reject) {
+ dns.lookup(hostname, function(err, address, family) {
+ if(err != null) return reject(err);
+ resolve(address);
+ });
+ });
+ return promise;
+}
+
io.sockets.on('connection', function (socket) {
console.log('clientID: '+socket.id+' connection: ', socket.request.connection._peername);
connections[socket.id] = {}
@@ -28,52 +43,69 @@ io.sockets.on('connection', function (socket) {
})
socket.on('disconnect', function() {
- for (let d in connections[socket.id]) d.disconnect("Client exited");
+ for (let d in connections[socket.id])
+ connections[socket.id][d].disconnect();
delete connections[socket.id];
console.log('clientID: '+socket.id+' disconnect');
});
+ socket.on('error', (e) => {
+ console.log(e);
+ })
+
socket.on('irc_create', function(connectiondata) {
console.log(socket.id+" created irc connection: ", connectiondata);
+ socket.emit('act_client', {type: 'connect_message', message: "Connecting to server..", error: false});
- socket.emit('act_client', {type: 'connect_message', data: "Attempting connection..", error: false});
+ let newConnection = new ircclient(connectiondata);
+ newConnection.connect();
- setTimeout(function() {
- console.log("fake connect");
- socket.emit('act_client', {type: 'event_connect', address: connectiondata.server, network: "IcyNet", supportedModes: {"o": "@", "h": "%", "v": "+"}, nickname: connectiondata.nickname, raw: connectiondata});
- socket.emit('act_client', {type: 'server_message', messageType: "notice", server: connectiondata.server, message: "Connection established"});
- }, 2000);
+ connections[socket.id][connectiondata.server] = newConnection;
- setTimeout(function() {
- console.log("fake channel");
- socket.emit('act_client', {type: 'event_join_channel', server: connectiondata.server, channel: "#channel", user: {nickname: connectiondata.nickname, username: "teemant", hostname: socket.request.connection._peername.address}});
- socket.emit('act_client', {type: 'channel_nicks', channel: "#channel", server: connectiondata.server, nicks: ["+horse", "@scoper", "@aspire", "+random", "lol"]});
- socket.emit('act_client', {type: 'channel_topic', channel: "#channel", server: connectiondata.server, topic: "This channel is the best."});
- socket.emit('act_client', {type: 'channel_topic', channel: "#channel", server: connectiondata.server, set_by: "horse", time: Date.now()});
- socket.emit('act_client', {type: 'message', messageType: "privmsg", server: connectiondata.server, to: "#channel", user: {nickname: "horse"}, message: "I like ponies"});
+ newConnection.on('authenticated', () => {
+ console.log("******** AUTH DONE **********");
+ console.log("******** AUTH DONE **********");
+ console.log("******** AUTH DONE **********");
+ console.log("******** AUTH DONE **********");
+ console.log("******** AUTH DONE **********");
+ socket.emit('act_client', {type: "event_connect", address: connectiondata.server, network: newConnection.data.network,
+ supportedModes: newConnection.data.supportedModes, nickname: newConnection.config.nickname});
+ });
- setTimeout(function() {
- socket.emit('act_client', {type: 'nick_change', server: connectiondata.server, nick: "horse", newNick: "pony"});
- }, 2000)
+ newConnection.on('error', (data) => {
+ let message = "An error occured";
+ let inconnect = false;
- setTimeout(function() {
- socket.emit('act_client', {type: 'message', messageType: "action", server: connectiondata.server, to: "#channel", user: {nickname: "pony"}, message: "Is the greatest pony fan"});
- }, 3000)
+ if(!newConnection.authenticated) {
+ message = "Failed to connect to the server!";
+ inconnect = true;
+ }
- setTimeout(function() {
- socket.emit('act_client', {type: 'event_join_channel', server: connectiondata.server, channel: "#poni", user: {nickname: connectiondata.nickname, username: "teemant", hostname: socket.request.connection._peername.address}});
- socket.emit('act_client', {type: 'channel_nicks', channel: "#poni", server: connectiondata.server, nicks: ["+horse", "@Diamond", "@aspire", "+random", "lol"]});
- socket.emit('act_client', {type: 'channel_topic', channel: "#poni", server: connectiondata.server, topic: "This channel is the second best."});
- socket.emit('act_client', {type: 'channel_topic', channel: "#poni", server: connectiondata.server, set_by: "Diamond", time: Date.now()});
- }, 5000)
+ socket.emit('act_client', {type: (inconnect ? 'server_message' : 'connect_message'), message: message, type: 'error', error: true});
+ });
- setTimeout(function() {
- socket.emit('act_client', {type: 'event_kick_channel', server: connectiondata.server, channel: "#channel", user: {nickname: "scoper", username: "teemant", hostname: socket.request.connection._peername.address}, kickee: "random", reason: "Get out."});
- socket.emit('act_client', {type: 'event_quit', server: connectiondata.server, user: {nickname: "lol", username: "teemant", hostname: socket.request.connection._peername.address}, reason: "Sleep."});
- socket.emit('act_client', {type: 'event_part_channel', server: connectiondata.server, channel: "#poni", user: {nickname: "aspire", username: "teemant", hostname: socket.request.connection._peername.address}, reason: "Bye, lol."});
- }, 6000);
- }, 4000);
+ newConnection.on('pass_to_client', (data) => {
+ socket.emit('act_client', data);
+ });
+
+ newConnection.on('closed', (data) => {
+ let message = "Connection closed";
+ let inconnect = false;
+
+ switch(data.type) {
+ case "sock_closed_success":
+ inconnect = true;
+ break;
+ }
+
+ if(!newConnection.authenticated) {
+ message = "Failed to connect to the server!";
+ inconnect = true;
+ }
+
+ socket.emit('act_client', {type: (inconnect ? 'server_message' : 'connect_message'), message: message, type: 'error', error: true});
+ });
});
});