more frontend work

This commit is contained in:
Evert Prants 2016-09-23 15:36:56 +03:00
parent d2da0ecbad
commit 5e1ac8134c
5 changed files with 270 additions and 96 deletions

View File

@ -228,7 +228,7 @@ body {
width: 100%; width: 100%;
background-color: #00c7e0; background-color: #00c7e0;
} }
.ircclient #chat .ircwrapper .input .nickname { .ircclient #chat .ircwrapper .input .my_nickname {
background-color: #00efef; background-color: #00efef;
margin: 5px; margin: 5px;
padding: 7px; padding: 7px;
@ -256,7 +256,6 @@ body {
box-shadow: inset 4px 4px 8px #d8d8d8; box-shadow: inset 4px 4px 8px #d8d8d8;
} }
.message.type_simple .timestamp { .message.type_simple .timestamp {
margin-right: 5px;
color: #696969; color: #696969;
} }
.message.type_simple .timestamp:before { .message.type_simple .timestamp:before {
@ -268,7 +267,6 @@ body {
content: "]"; content: "]";
} }
.message.type_simple .sender { .message.type_simple .sender {
margin-right: 5px;
color: #3f51b5; color: #3f51b5;
} }
.message.type_simple .sender:before { .message.type_simple .sender:before {
@ -277,3 +275,14 @@ body {
.message.type_simple .sender:after { .message.type_simple .sender:after {
content: ">"; content: ">";
} }
.m_topic .content {
color: #03a9f4;
font-weight: bold;
}
.m_nick .content {
color: #ff9800;
font-weight: bold;
}
.m_action .actionee {
color: #3f51b5;
}

View File

@ -44,7 +44,7 @@
<div class="nicklist"></div> <div class="nicklist"></div>
</div> </div>
<div class="input"> <div class="input">
<div class="nickname">Test</div> <div class="my_nickname">Test</div>
<div class="inputwrapper"> <div class="inputwrapper">
<input type="text" id="input"> <input type="text" id="input">
</div> </div>

View File

@ -3,14 +3,11 @@ window.irc = {
primaryFrame: null, primaryFrame: null,
timestamps: true, timestamps: true,
timestampFormat: "HH:mm:ss", timestampFormat: "HH:mm:ss",
supportedPrefixes: "@%+", serverData: {}
modeTranslation: {
"o": "@",
"h": "%",
"v": "+"
}
}; };
window.clientdom = {connector: {}};
/*********************\ /*********************\
|** **| |** **|
|** UTILITIES **| |** UTILITIES **|
@ -147,21 +144,21 @@ function addClass(element, cl) {
\*********************/ \*********************/
class Nicklist { class Nicklist {
constructor(buffer, frame) { constructor(buffer) {
this.buffer = buffer; this.buffer = buffer;
this.frame = frame;
this.nicks = []; this.nicks = [];
} }
sort() { sort() {
let spfx = irc.serverData[this.buffer.server].supportedPrefixes
this.nicks.sort(function (a,b) { this.nicks.sort(function (a,b) {
let rex = new RegExp('^['+irc.supportedPrefixes+']'); let rex = new RegExp('^['+spfx+']');
let nicks = [a.prefix.replace(rex,'').toLowerCase(), b.prefix.replace(rex,'').toLowerCase()]; let nicks = [a.prefix.replace(rex,'').toLowerCase(), b.prefix.replace(rex,'').toLowerCase()];
let prefix = []; let prefix = [];
if (rex.test(a.prefix)) prefix.push(irc.supportedPrefixes.indexOf(a.prefix[0])); if (rex.test(a.prefix)) prefix.push(spfx.indexOf(a.prefix[0]));
else prefix.push(irc.supportedPrefixes.length+1); else prefix.push(spfx.length+1);
if (rex.test(b.prefix)) prefix.push(irc.supportedPrefixes.indexOf(b.prefix[0])); if (rex.test(b.prefix)) prefix.push(spfx.indexOf(b.prefix[0]));
else prefix.push(irc.supportedPrefixes.length+1); else prefix.push(spfx.length+1);
if (prefix[0] < prefix[1]) return -1; if (prefix[0] < prefix[1]) return -1;
if (prefix[0] > prefix[1]) return 1; if (prefix[0] > prefix[1]) return 1;
if (nicks[0] > nicks[1]) return 1; if (nicks[0] > nicks[1]) return 1;
@ -177,13 +174,21 @@ class Nicklist {
let str = document.createElement("div"); let str = document.createElement("div");
str.className = "nick"; str.className = "nick";
str.setAttribute('id', 'nick-'+nick.nickname); str.setAttribute('id', 'nick-'+nick.nickname);
let construct = "<span class='prefix'>"+nick.prefix+"</span><span class='nickname'>"+nick.nickname+"</span>"; let construct = "";
if(nick.prefix != "")
construct += "<span class='prefix'>"+nick.prefix+"</span>";
else
construct += "<span class='no-prefix'>&nbsp;</span>";
construct += "<span class='nickname'>"+nick.nickname+"</span>";
str.innerHTML = construct; str.innerHTML = construct;
this.frame.appendChild(str); clientdom.nicklist.appendChild(str);
} }
render() { render() {
this.frame.innerHTML = ""; clientdom.nicklist.innerHTML = "";
this.sort();
for(let n in this.nicks) { for(let n in this.nicks) {
let nick = this.nicks[n]; let nick = this.nicks[n];
this.appendToList(nick); this.appendToList(nick);
@ -196,6 +201,10 @@ class Nicklist {
this.render(); this.render();
} }
nickAddObject(obj) {
this.nicks.push(obj);
}
nickRemove(nickname) { nickRemove(nickname) {
let nickIndex = this.getNickIndex(nickname); let nickIndex = this.getNickIndex(nickname);
@ -268,21 +277,33 @@ class Tab {
constructor(buffer) { constructor(buffer) {
this.buffer = buffer; this.buffer = buffer;
this.element = null; this.element = null;
this.closeRequested = false;
} }
// Create a tab element // Create a tab element
renderTab(frame) { renderTab() {
let internals = "<span id='title'>"+ this.buffer.title +"</span><span id='unread'></span><span id='close'>x</span>"; let internals = "<span id='title'>"+ this.buffer.title +"</span><span id='unread' class='none'></span>";
let ttt = document.createElement('div'); let ttt = document.createElement('div');
ttt.innerHTML = internals; ttt.innerHTML = internals;
ttt.className = "tab"; ttt.className = "tab";
ttt.setAttribute('id', 'tab-'+this.name); ttt.setAttribute('id', 'tab-'+this.name);
frame.appendChild(ttt); clientdom.tabby.appendChild(ttt);
this.element = ttt; this.element = ttt;
if(this.buffer.type != "server") {
ttt.innerHTML += "<span id='close'>x</span>"
ttt.querySelector('#close').addEventListener('click', () => {
this.close();
}, false);
}
ttt.addEventListener('click', () => { ttt.addEventListener('click', () => {
if(this.closeRequested) return;
if(this.buffer.active) if(this.buffer.active)
return; return;
irc.chat.render(this.buffer); irc.chat.render(this.buffer);
}, false); }, false);
} }
@ -309,7 +330,8 @@ class Tab {
} }
close() { close() {
console.log('close requested for '+this.buffer.title); this.closeRequested = true;
this.buffer.closeBuffer();
} }
} }
@ -326,20 +348,13 @@ class Buffer {
this.name = buffername; this.name = buffername;
this.title = tabname; this.title = tabname;
this.type = type; this.type = type;
this.nicklistDisplayed = false;
this.active = false; this.active = false;
this.tab = new Tab(this); this.tab = new Tab(this);
this.tab.renderTab(irc.primaryFrame.querySelector('.tabby')); this.tab.renderTab(clientdom.tabby);
if(type == "channel") { if(type == "channel")
this.nicklistDisplayed = true; this.nicklist = new Nicklist(this, clientdom.nicklist);
this.nicklist = new Nicklist(this);
}
this.frame = irc.primaryFrame.querySelector('#chat');
this.letterbox = this.frame.querySelector('.letterbox');
} }
render() { render() {
@ -348,31 +363,30 @@ class Buffer {
this.unreadCount = 0; this.unreadCount = 0;
this.tab.setUnreadCount(0); this.tab.setUnreadCount(0);
let chat = this.frame.querySelector('.chatarea'); clientdom.chat.className = "chatarea";
let topicbar = chat.querySelector('.topicbar'); clientdom.nicklist.innerHTML = "";
let nicklist = chat.querySelector('.nicklist'); clientdom.topicbar.innerHTML = "";
chat.className = "chatarea"; if(this.nicklist) {
nicklist.innerHTML = ""; addClass(clientdom.chat, 'vnicks');
topicbar.innerHTML = ""; this.nicklist.render();
if(this.nicklistDisplayed) {
addClass(chat, 'vnicks');
} }
if(this.topic != null && this.topic != "") { if(this.topic != null && this.topic != "") {
addClass(chat, 'vtopic'); addClass(clientdom.chat, 'vtopic');
topicbar.innerHTML = this.topic; clientdom.topicbar.innerHTML = this.topic;
} }
this.renderMessages(); this.renderMessages();
this.letterbox.scrollTop = this.lastscroll; clientdom.letterbox.scrollTop = this.lastscroll;
clientdom.currentNickname.innerHTML = irc.serverData[this.server].my_nick;
} }
renderMessages() { renderMessages() {
if(!this.active) return; if(!this.active) return;
this.letterbox.innerHTML = ""; clientdom.letterbox.innerHTML = "";
for(let t in this.messages) { for(let t in this.messages) {
let mesg = this.messages[t]; let mesg = this.messages[t];
@ -386,21 +400,36 @@ class Buffer {
let construct = ""; let construct = "";
if(irc.timestamps) if(irc.timestamps)
construct += "<span class='timestamp'>"+meta.time.format(irc.timestampFormat)+"</span>"; construct += "<span class='timestamp'>"+meta.time.format(irc.timestampFormat)+"</span>&nbsp;";
if(meta.sender != null) if(meta.sender != null && meta.type != "action") {
construct += "<span class='sender'>"+meta.sender+"</span>"; construct += "<span class='sender'>"+meta.sender+"</span>&nbsp;";
else } else {
construct += "<span class='asterisk'>*</span>&nbsp;";
addClass(mesgConstr, "no_sender"); addClass(mesgConstr, "no_sender");
}
if(meta.type == "action")
construct += "<span class='actionee'>"+meta.sender+"</span>&nbsp;<span class='content'>"+meta.message+"</span>";
else
construct += "<span class='content'>"+meta.message+"</span>"; construct += "<span class='content'>"+meta.message+"</span>";
mesgConstr.innerHTML = construct; mesgConstr.innerHTML = construct;
this.letterbox.appendChild(mesgConstr); clientdom.letterbox.appendChild(mesgConstr);
let lFactor = this.letterbox.offsetHeight + this.letterbox.scrollTop let lFactor = clientdom.letterbox.offsetHeight + clientdom.letterbox.scrollTop
if(lFactor > this.letterbox.scrollHeight - 100) if(lFactor > clientdom.letterbox.scrollHeight - 100)
this.letterbox.scrollTop = this.letterbox.scrollHeight; clientdom.letterbox.scrollTop = clientdom.letterbox.scrollHeight;
}
topicChange(topic) {
if(this.active) {
clientdom.topicbar.innerHTML = topic;
if(this.topic == null)
addClass(clientdom.chat, "vtopic");
}
this.topic = topic;
} }
addMessage(message, sender, type) { addMessage(message, sender, type) {
@ -417,28 +446,20 @@ class Buffer {
switchOff() { switchOff() {
this.tab.setActive(false); this.tab.setActive(false);
this.lastscroll = this.letterbox.scrollTop; this.lastscroll = clientdom.letterbox.scrollTop;
this.active = false; this.active = false;
} }
close() { closeBuffer() {
irc.chat.closeBuffer(this);
} }
} }
class IRCConnector { class IRCConnector {
constructor(frame) { constructor() {
this.frame = frame;
this.messenger = frame.querySelector('#connmsg');
this.f_form = frame.querySelector('#IRCConnector');
this.f_nickname = this.f_form.querySelector('#nickname');
this.f_channel = this.f_form.querySelector('#channel');
this.f_server = this.f_form.querySelector('#server');
this.f_port = this.f_form.querySelector('#port');
this.formLocked = false; this.formLocked = false;
this.f_form.onsubmit = (e) => { clientdom.connector.form.onsubmit = (e) => {
if(this.formLocked) { if(this.formLocked) {
e.preventDefault(); e.preventDefault();
return false; return false;
@ -456,10 +477,10 @@ class IRCConnector {
validateForm(event) { validateForm(event) {
event.preventDefault(); event.preventDefault();
let nickname = this.f_nickname.value; let nickname = clientdom.connector.nickname.value;
let channel = this.f_channel.value; let channel = clientdom.connector.channel.value;
let server = this.f_server.value; let server = clientdom.connector.server.value;
let port = this.f_port.value; let port = clientdom.connector.port.value;
if (!window.validators.nickname(nickname)) { if (!window.validators.nickname(nickname)) {
this.authMessage("Erroneous nickname!", true); this.authMessage("Erroneous nickname!", true);
@ -515,20 +536,19 @@ class IRCConnector {
} }
authMessage(message, error) { authMessage(message, error) {
this.messenger.innerHTML = "<span class='msg"+(error?" error":"")+"'>"+message+"</span>"; clientdom.connector.messenger.innerHTML = "<span class='msg"+(error?" error":"")+"'>"+message+"</span>";
} }
authComplete() { authComplete() {
this.frame.style.display = "none"; clientdom.connector.frame.style.display = "none";
this.formLocked = false; this.formLocked = false;
} }
} }
class IRCChatWindow { class IRCChatWindow {
constructor(frame) { constructor() {
this.frame = frame;
this.buffers = []; this.buffers = [];
this.frame.style.display = "none"; clientdom.frame.style.display = "none";
this.firstServer = true; this.firstServer = true;
this.currentBuffer = null; this.currentBuffer = null;
} }
@ -563,7 +583,7 @@ class IRCChatWindow {
return result; return result;
} }
getBufferByNameServer(server, channel) { getBufferByServerName(server, channel) {
let result = null; let result = null;
for (let t in this.buffers) { for (let t in this.buffers) {
let buf = this.buffers[t]; let buf = this.buffers[t];
@ -585,7 +605,20 @@ class IRCChatWindow {
newServerBuffer(serverinfo) { newServerBuffer(serverinfo) {
if(this.firstServer) { if(this.firstServer) {
this.frame.style.display = "block"; clientdom.frame.style.display = "block";
}
let prefixes = "";
for(let v in serverinfo.supportedModes) {
prefixes += serverinfo.supportedModes[v];
}
irc.serverData[serverinfo.address] = {
modeTranslation: serverinfo.supportedModes,
supportedPrefixes: prefixes,
network: serverinfo.network,
my_nick: serverinfo.nickname
} }
let newServer = new Buffer(serverinfo.address, serverinfo.address, serverinfo.network, "server"); let newServer = new Buffer(serverinfo.address, serverinfo.address, serverinfo.network, "server");
@ -595,7 +628,7 @@ class IRCChatWindow {
} }
createBuffer(server, name, type, autoswitch) { createBuffer(server, name, type, autoswitch) {
let buf = this.getBufferByNameServer(server, name); let buf = this.getBufferByServerName(server, name);
if(buf) { if(buf) {
if(autoswitch) if(autoswitch)
this.render(buf); this.render(buf);
@ -610,11 +643,27 @@ class IRCChatWindow {
} }
closeBuffer(buffer) { closeBuffer(buffer) {
// todo: close if(buffer.type == "server") return; // Don't close server buffers, lol
if(buffer.type == "channel") console.log("TODO: PART");
let bufIndex = this.buffers.indexOf(buffer);
if(buffer.active) {
console.log(bufIndex);
if (bufIndex == 0) {
if(this.buffers[bufIndex+1]) {
this.render(this.buffers[bufIndex+1]);
}
} else {
this.render(this.buffers[bufIndex-1]);
}
}
buffer.tab.element.remove();
this.buffers.splice(bufIndex, 1);
} }
messageBuffer(name, server, message) { messageBuffer(name, server, message) {
let buf = this.getBufferByNameServer(server, name); let buf = this.getBufferByServerName(server, name);
if(buf == null) if(buf == null)
buf = this.createBuffer(server, name, "message", false); buf = this.createBuffer(server, name, "message", false);
@ -622,6 +671,65 @@ class IRCChatWindow {
buf.addMessage(message.message, message.from, message.type); buf.addMessage(message.message, message.from, message.type);
} }
buildNicklist(channel, server, nicks) {
let buf = this.getBufferByServerName(server, channel);
if(buf == null)
return;
for(let n in nicks) {
let nick = {nickname: "", prefix: ""};
if(irc.serverData[buf.server].supportedPrefixes.split('').indexOf(nicks[n].substring(0, 1)) != -1) {
nick.prefix = nicks[n].substring(0, 1);
nick.nickname = nicks[n].substring(1);
} else {
nick.nickname = nicks[n];
}
buf.nicklist.nickAddObject(nick);
}
if(buf.active)
buf.nicklist.render();
}
nickChange(server, oldNick, newNick) {
let buffers = this.getBuffersByServer(server);
if(irc.serverData[server].my_nick == oldNick) {
irc.serverData[server].my_nick = newNick;
let activeBuf = this.getActiveBuffer();
if(activeBuf.server == server) {
activeBuf.my_nickname.innerHTML = newNick;
}
}
for(let i in buffers) {
let buffer = buffers[i];
if(buffer.type != "channel") continue;
if(buffer.nicklist.getNickIndex(oldNick) == null) continue;
buffer.nicklist.nickChange(oldNick, newNick);
buffer.addMessage(oldNick+" is now known as "+newNick, null, "nick");
}
}
topicChange(channel, server, topic, changer) {
let buf = this.getBufferByServerName(server, channel);
if (!buf) return;
buf.topicChange(topic);
if(changer)
buf.addMessage(changer+" set the topic of "+channel+ " to \""+topic+"\"", null, "topic");
else
buf.addMessage("Topic of "+channel+ " is \""+topic+"\"", null, "topic");
}
render(buffer) { render(buffer) {
let activeNow = this.getActiveBuffer(); let activeNow = this.getActiveBuffer();
@ -639,11 +747,27 @@ class IRCChatWindow {
\**************************/ \**************************/
window.onload = function() { window.onload = function() {
irc.primaryFrame = document.querySelector('.ircclient');
clientdom.connector['frame'] = irc.primaryFrame.querySelector('#authdialog');
clientdom.connector['messenger'] = clientdom.connector.frame.querySelector('#connmsg');
clientdom.connector['form'] = clientdom.connector.frame.querySelector('#IRCConnector');
clientdom.connector['nickname'] = clientdom.connector.form.querySelector('#nickname');
clientdom.connector['channel'] = clientdom.connector.form.querySelector('#channel');
clientdom.connector['server'] = clientdom.connector.form.querySelector('#server');
clientdom.connector['port'] = clientdom.connector.form.querySelector('#port');
clientdom['tabby'] = irc.primaryFrame.querySelector('.tabby')
clientdom['frame'] = irc.primaryFrame.querySelector('#chat');
clientdom['chat'] = clientdom.frame.querySelector('.chatarea');
clientdom['letterbox'] = clientdom.frame.querySelector('.letterbox');
clientdom['nicklist'] = clientdom.frame.querySelector('.nicklist');
clientdom['currentNickname'] = clientdom.frame.querySelector('.my_nickname');
clientdom['topicbar'] = clientdom.chat.querySelector('.topicbar');
irc.socket = io.connect('http://localhost:8080'); irc.socket = io.connect('http://localhost:8080');
irc.primaryFrame = document.querySelector('.ircclient'); irc.auther = new IRCConnector();
irc.auther = new IRCConnector(irc.primaryFrame.querySelector("#authdialog")); irc.chat = new IRCChatWindow();
irc.chat = new IRCChatWindow(irc.primaryFrame.querySelector("#chat"));
irc.socket.on('connect', function (data) { irc.socket.on('connect', function (data) {
irc.socketUp = true; irc.socketUp = true;
@ -664,9 +788,26 @@ window.onload = function() {
case "event_join_channel": case "event_join_channel":
irc.chat.createBuffer(data.server, data.name, "channel", true); irc.chat.createBuffer(data.server, data.name, "channel", true);
break; break;
case "server_message": case "message":
irc.chat.messageBuffer(data.to, data.server, {message: data.message, type: data.messageType, from: data.from}); irc.chat.messageBuffer(data.to, data.server, {message: data.message, type: data.messageType, from: data.from});
break; break;
case "channel_nicks":
irc.chat.buildNicklist(data.channel, data.server, data.nicks);
break;
case "channel_topic":
if(data['topic'] && data['set_by'])
irc.chat.topicChange(data.channel, data.server, data.topic, data['set_by']);
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});
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});
break;
case "connect_message": case "connect_message":
irc.auther.authMessage(data.data, data.error); irc.auther.authMessage(data.data, data.error);
break; break;

View File

@ -202,7 +202,7 @@ body
height: 46px; height: 46px;
width: 100%; width: 100%;
background-color: #00c7e0; background-color: #00c7e0;
.nickname .my_nickname
background-color: #00efef; background-color: #00efef;
margin: 5px; margin: 5px;
padding: 7px; padding: 7px;
@ -230,7 +230,6 @@ body
.message.type_simple .message.type_simple
.timestamp .timestamp
margin-right: 5px;
color: #696969; color: #696969;
&:before &:before
color: #607D8B; color: #607D8B;
@ -239,9 +238,19 @@ body
color: #607D8B; color: #607D8B;
content: "]"; content: "]";
.sender .sender
margin-right: 5px;
color: #3F51B5; color: #3F51B5;
&:before &:before
content: "<"; content: "<";
&:after &:after
content: ">"; content: ">";
.m_topic .content
color: #03A9F4;
font-weight: bold;
.m_nick .content
color: #FF9800;
font-weight: bold;
.m_action .actionee
color: #3f51b5;

View File

@ -38,17 +38,32 @@ io.sockets.on('connection', function (socket) {
setTimeout(function() { setTimeout(function() {
console.log("fake connect"); console.log("fake connect");
socket.emit('act_client', {type: 'event_connect', address: connectiondata.server, network: "IcyNet", raw: connectiondata}); 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, to: connectiondata.server, from: null, message: "Connection established"}); socket.emit('act_client', {type: 'server_message', messageType: "notice", server: connectiondata.server, message: "Connection established"});
}, 2000); }, 2000);
setTimeout(function() { setTimeout(function() {
console.log("fake channel"); console.log("fake channel");
socket.emit('act_client', {type: 'event_join_channel', server: connectiondata.server, name: "#channel"}); socket.emit('act_client', {type: 'event_join_channel', server: connectiondata.server, name: "#channel"});
// Spam the client with messages (for testing) socket.emit('act_client', {type: 'channel_nicks', channel: "#channel", server: connectiondata.server, nicks: ["+horse", "@scoper", "@aspire", "+random", "lol"]});
setInterval(function() { socket.emit('act_client', {type: 'channel_topic', channel: "#channel", server: connectiondata.server, topic: "This channel is the best."});
socket.emit('act_client', {type: 'server_message', messageType: "privmsg", server: connectiondata.server, to: "#channel", from: "horse", message: "I like ponies"}); socket.emit('act_client', {type: 'channel_topic', channel: "#channel", server: connectiondata.server, set_by: "horse", time: Date.now()});
}, 1000); socket.emit('act_client', {type: 'message', messageType: "privmsg", server: connectiondata.server, to: "#channel", from: "horse", message: "I like ponies"});
setTimeout(function() {
socket.emit('act_client', {type: 'nick_change', server: connectiondata.server, nick: "horse", newNick: "pony"});
}, 2000)
setTimeout(function() {
socket.emit('act_client', {type: 'message', messageType: "action", server: connectiondata.server, to: "#channel", from: "pony", message: "Is the greatest pony fan"});
}, 3000)
setTimeout(function() {
socket.emit('act_client', {type: 'event_join_channel', server: connectiondata.server, name: "#poni"});
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)
}, 4000); }, 4000);
}); });
}); });