simple webirc integration, debug mode
This commit is contained in:
parent
be6151be6b
commit
2d22402cb0
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/node_modules/
|
/node_modules/
|
||||||
/build/
|
/build/
|
||||||
/client.config.toml
|
/client.config.toml
|
||||||
|
/webirc.data.json
|
||||||
|
@ -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
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[server]
|
[server]
|
||||||
port=8080
|
port=8080
|
||||||
|
debug=true
|
||||||
|
|
||||||
[client]
|
[client]
|
||||||
username="teemant"
|
username="teemant"
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
45
server/webirc.js
Normal 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();
|
65
teemant.js
65
teemant.js
@ -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();
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user