simple webirc integration, debug mode

This commit is contained in:
Evert Prants 2016-09-25 16:09:55 +03:00
parent be6151be6b
commit 2d22402cb0
9 changed files with 126 additions and 22 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/node_modules/ /node_modules/
/build/ /build/
/client.config.toml /client.config.toml
/webirc.data.json

View File

@ -10,10 +10,13 @@ This application requires [node.js](https://nodejs.org/) to be installed.
The client will be accessible at http://localhost:8080/ The client will be accessible at http://localhost:8080/
### WebIRC
The server will look for passwords in `webirc.data.json`. The format is: `"server-ip-address": "server webirc password"`
###The (non-complete) TODO List (of things left to do) ###The (non-complete) TODO List (of things left to do)
* [HIGH] Settings menu * [HIGH] Settings menu
* [HIGH] WebIRC protocol integration
* [MEDIUM] Theme engine * [MEDIUM] Theme engine
* [NORMAL] CAP negotiation * [NORMAL] CAP negotiation
* [LOW] Better input * [LOW] Better input

View File

@ -1,5 +1,6 @@
[server] [server]
port=8080 port=8080
debug=true
[client] [client]
username="teemant" username="teemant"

View File

@ -180,7 +180,7 @@ body {
bottom: 46px; bottom: 46px;
} }
.ircclient #chat .ircwrapper .chatarea .smsc-nicklistbtn { .ircclient #chat .ircwrapper .chatarea .smsc-nicklistbtn {
background-image: url("/image/users.svg"); background-image: url("image/users.svg");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
width: 46px; width: 46px;
@ -313,7 +313,7 @@ body {
box-shadow: inset 4px 4px 8px #d8d8d8; box-shadow: inset 4px 4px 8px #d8d8d8;
} }
.ircclient #chat .ircwrapper .input .sendbutton { .ircclient #chat .ircwrapper .input .sendbutton {
background-image: url("/image/send.svg"); background-image: url("image/send.svg");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
width: 32px; width: 32px;

View File

@ -602,7 +602,8 @@ class Buffer {
appendMessage(meta) { appendMessage(meta) {
let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type); let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type);
if((meta.type == "privmsg" || meta.type == "notice") && meta.message.indexOf(irc.serverData[this.server].my_nick) != -1) if((meta.type == "privmsg" || meta.type == "notice" || meta.type == "action") &&
meta.message.indexOf(irc.serverData[this.server].my_nick) != -1)
addClass(mesgConstr, "mentioned"); addClass(mesgConstr, "mentioned");
clientdom.letterbox.appendChild(mesgConstr); clientdom.letterbox.appendChild(mesgConstr);
@ -630,7 +631,8 @@ class Buffer {
this.appendMessage(mesg); this.appendMessage(mesg);
} else { } else {
this.unreadCount += 1; this.unreadCount += 1;
if((type == "privmsg" || type == "notice") && message.indexOf(irc.serverData[this.server].my_nick) != -1) if((type == "privmsg" || type == "notice" || type == "action") &&
message.indexOf(irc.serverData[this.server].my_nick) != -1)
console.log("TODO: notify user of mentioned"); console.log("TODO: notify user of mentioned");
} }

View File

@ -161,7 +161,7 @@ body
width: 100%; width: 100%;
bottom: 46px; bottom: 46px;
.smsc-nicklistbtn .smsc-nicklistbtn
background-image: url(/image/users.svg); background-image: url(image/users.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
width: 46px; width: 46px;
@ -277,7 +277,7 @@ body
border-left: 0 border-left: 0
box-shadow: inset 4px 4px 8px #d8d8d8 box-shadow: inset 4px 4px 8px #d8d8d8
.sendbutton .sendbutton
background-image: url(/image/send.svg); background-image: url(image/send.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
width: 32px; width: 32px;

View File

@ -2,6 +2,7 @@ let EventEmitter = require('events').EventEmitter;
let net = require('net'); let net = require('net');
let configuration = require(__dirname+"/config"); let configuration = require(__dirname+"/config");
let parse = require(__dirname+"/parser"); let parse = require(__dirname+"/parser");
let webirc = require(__dirname+"/webirc");
if (!String.prototype.format) { if (!String.prototype.format) {
String.prototype.format = function() { String.prototype.format = function() {
@ -18,7 +19,6 @@ class IRCConnectionHandler {
} }
handleUserLine(data) { handleUserLine(data) {
console.log(data);
switch(data.command) { switch(data.command) {
case "kick": case "kick":
case "part": case "part":
@ -68,7 +68,6 @@ class IRCConnectionHandler {
} }
handleServerLine(line) { handleServerLine(line) {
console.log(line);
if(this.conn.queue["supportsmsg"] && line.command != "005") { if(this.conn.queue["supportsmsg"] && line.command != "005") {
delete this.conn.queue["supportsmsg"]; delete this.conn.queue["supportsmsg"];
@ -334,7 +333,7 @@ class IRCConnectionHandler {
} }
class IRCConnection extends EventEmitter { class IRCConnection extends EventEmitter {
constructor(providedInfo) { constructor(providedInfo, userInfo) {
super(); super();
this.config = { this.config = {
@ -349,6 +348,8 @@ class IRCConnection extends EventEmitter {
address: "0.0.0.0" address: "0.0.0.0"
}; };
this.userInfo = userInfo;
for(let a in providedInfo) { for(let a in providedInfo) {
this.config[a] = providedInfo[a]; this.config[a] = providedInfo[a];
} }
@ -429,7 +430,11 @@ class IRCConnection extends EventEmitter {
if (this.config.password) if (this.config.password)
this.socket.write('PASS {0}\r\n'.format(this.config.password)); this.socket.write('PASS {0}\r\n'.format(this.config.password));
// TODO: WebIRC let serverpass = webirc.get_password(this.config.address);
if(serverpass)
this.socket.write('WEBIRC {0} cgiirc {1} {2}\r\n'.format(serverpass, this.userInfo.hostname, this.userInfo.ipaddr));
this.socket.write('USER {0} 8 * :{1}\r\n'.format(this.config.username, this.config.realname)); 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)); this.socket.write('NICK {0}\r\n'.format(this.config.nickname));
} }

45
server/webirc.js Normal file
View File

@ -0,0 +1,45 @@
let dns = require("dns");
let fs = require("fs");
let path = require("path");
let config = require(__dirname+'/config');
let webirc_data_path = path.resolve(__dirname+'/../webirc.data.json');
let webirc_data = {};
function writeToFile() {
fs.writeFile(webirc_data_path, JSON.stringify(webirc_data, null, '\t'), function (err) {if (err) throw err;});
}
function reload() {
try {
fs.accessSync(webirc_data_path, fs.F_OK);
webirc_data = require(webirc_data_path);
if (require.cache && require.cache[webirc_data_path]) {
delete require.cache[webirc_data_path];
}
} catch(e) {
writeToFile();
}
}
function get_password(server_ip) {
if(webirc_data[server_ip] != null)
return webirc_data[server_ip];
return null;
}
module.exports = {
reload: reload,
get_password: get_password,
writeToFile: writeToFile
}
process.on('SIGUSR1', () => {
console.log("!!! Received SIGUSR1; Reloading webirc data.. !!!");
reload();
});
reload();

View File

@ -6,7 +6,7 @@ let sockio = require("socket.io");
let dns = require("dns"); let dns = require("dns");
let app = express(); let app = express();
let pubdir = path.join(__dirname+"/public"); let pubdir = path.join(__dirname, "public");
let config = require(__dirname+'/server/config'); let config = require(__dirname+'/server/config');
let ircclient = require(__dirname+'/server/irc'); let ircclient = require(__dirname+'/server/irc');
@ -14,6 +14,8 @@ let port = config.server.port || 8080;
let connections = {}; let connections = {};
process.stdin.resume();
app.get("/", function(req, res){ app.get("/", function(req, res){
res.sendFile(pubdir+"/index.html"); res.sendFile(pubdir+"/index.html");
}); });
@ -21,30 +23,53 @@ app.get("/", function(req, res){
app.use(express.static(__dirname + '/public')); app.use(express.static(__dirname + '/public'));
let io = sockio.listen(app.listen(port, function() { let io = sockio.listen(app.listen(port, function() {
console.log("*** Listening on port " + port); console.log("*** Listening on http://localhost:" + port + "/");
})); }));
function resolveHostname(hostname) { function resolveHostname(ipaddr) {
let promise = new Promise(function(resolve, reject) { let promise = new Promise(function(resolve, reject) {
dns.lookup(hostname, function(err, address, family) { dns.reverse(ipaddr, function(err, hostnames) {
if(err != null) return reject(err); if(err != null) return reject(err);
resolve(address); resolve(hostnames);
}); });
}); });
return promise; return promise;
} }
io.sockets.on('connection', function (socket) { io.sockets.on('connection', function (socket) {
console.log('clientID: '+socket.id+' connection: ', socket.request.connection._peername); let userip = socket.handshake.headers['x-real-ip'] || socket.handshake.headers['x-forwarded-for'] ||
connections[socket.id] = {} socket.request.connection._peername.address || "127.0.0.1";
if(config.server.debug)
console.log('clientID: '+socket.id+' from: ', userip);
// New object for connections
connections[socket.id] = {
host: {
ipaddr: userip,
hostname: "localhost"
}
}
// Get the hostname of the connecting user
let hostQuery = resolveHostname(userip);
hostQuery.then((arr) => {
if(arr.length > 0)
connections[socket.id].host.hostname = arr[0];
if(config.server.debug)
console.log("Hostname of "+socket.id+" was determined to be "+connections[socket.id].host.hostname);
}).catch((err) => { console.log("Host resolve for "+socket.id+" failed: ", err); });
socket.on('disconnect', function() { socket.on('disconnect', function() {
for (let d in connections[socket.id]) for (let d in connections[socket.id]) {
if(connections[socket.id][d].ipaddr) continue;
if(connections[socket.id][d].connected == true) if(connections[socket.id][d].connected == true)
connections[socket.id][d].disconnect(); connections[socket.id][d].disconnect();
}
delete connections[socket.id]; delete connections[socket.id];
if(config.server.debug)
console.log('clientID: '+socket.id+' disconnect'); console.log('clientID: '+socket.id+' disconnect');
}); });
@ -57,14 +82,19 @@ io.sockets.on('connection', function (socket) {
if(!serv) return; if(!serv) return;
if(serv.authenticated == false) return; if(serv.authenticated == false) return;
if(config.server.debug)
console.log("["+socket.id+"] ->", data);
serv.handler.handleUserLine(data); serv.handler.handleUserLine(data);
}) })
socket.on('irc_create', function(connectiondata) { socket.on('irc_create', function(connectiondata) {
if(config.server.debug)
console.log(socket.id+" created irc connection: ", 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', message: "Connecting to server..", error: false});
let newConnection = new ircclient(connectiondata); let newConnection = new ircclient(connectiondata, connections[socket.id].host);
newConnection.connect(); newConnection.connect();
connections[socket.id][connectiondata.server] = newConnection; connections[socket.id][connectiondata.server] = newConnection;
@ -75,6 +105,12 @@ io.sockets.on('connection', function (socket) {
max_channel_length: newConnection.data.max_channel_length}); max_channel_length: newConnection.data.max_channel_length});
}); });
if(config.server.debug) {
newConnection.on('line', function(line) {
console.log("["+socket.id+"] <-", line);
});
}
newConnection.on('connerror', (data) => { newConnection.on('connerror', (data) => {
let message = "An error occured"; let message = "An error occured";
let inconnect = true; let inconnect = true;
@ -110,3 +146,14 @@ io.sockets.on('connection', function (socket) {
}); });
}); });
}); });
process.on('SIGINT', () => {
console.log('!!! Received SIGINT; Terminating all IRC connections and exiting.. !!!');
for(let c in connections) {
for(let ircconn in connections[c]) {
if(connections[c][ircconn].ipaddr) continue;
connections[c][ircconn].disconnect();
}
}
process.exit();
});