Skip to content

Update #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ bouncerShack: ping ack timeout
bouncerDefaultOpmode: auto op/voice/hop mode default (can be turned on per client using /jbnc)
bouncerTimeout: how long until after no clients connected will the user stay connected
bufferMaxSize: maximum # of bytes a client buffer can hold before its terminated or 0 for unlimited
MsgRedistribution: If enabled, will override the entire old system installed by default, and it will
save the last 300 lines for both privmsgs and notices (except ctcp) and all separately by channel and by
recipient. It records everything even if the client is logged into JBNC or not.
As soon as the client reconnects to JBNC, it will send all privmsgs / notices to the client. The
IRC client should sort the msgids by checking if they are already received, if they are not received then
the client updates the new messages. Once the client has updated all the new messages, then it should
automatically send "/jbnc logclear" to remove the entire "privmsgnotice" array from the client
connected to the JBNC.
```

3. Run
Expand Down
142 changes: 123 additions & 19 deletions bouncer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// jbnc v0.5
// jbnc v0.7
// Copyright (C) 2020 Andrew Lee <andrew@imperialfamily.com>
// All Rights Reserved.
const tls = require('tls');
Expand Down Expand Up @@ -39,6 +39,7 @@ const SERVER_TLS_CERT = config.tlsCert?config.tlsCert:'fullchain.pem';
const SERVER_PORT = BOUNCER_MODE=='gateway'?(config.serverPort?config.serverPort:0):0;
const INGRESSWEBIRC = config.ingresswebircPassword?config.ingresswebircPassword:'';
const SERVER = BOUNCER_MODE=='gateway'?(config.server?config.server:''):'';
const MSG_REDISTRIBUTION = config.MsgRedistribution?true:false;
const DEBUG = config.debug?config.debug:false;


Expand Down Expand Up @@ -249,15 +250,15 @@ server = doServer(tlsOptions,function(socket) {
}
else if(commands[1]) {
this.irc.nick=commands[1].trim();
/*if(this.irc.user) {
this.hash=hash(this.irc.nick+this.irc.user+this.irc.password+this.irc.server+this.irc.port.toString());
if(this.irc.user) {
this.hash=hash(this.irc.nick+this.irc.password+this.irc.server+this.irc.port.toString());
if(connections[socket.hash]) {
clientReconnect(this);
}
else {
clientConnect(this);
}
}*/
}
}
break;
case 'USER':
Expand Down Expand Up @@ -422,6 +423,17 @@ server = doServer(tlsOptions,function(socket) {
this.write(":*jbnc NOTICE * :"+connections[this.hash].parents[x].clientbuffer+" ("+connections[this.hash].parents[x].remoteAddress+")\n");
}
break;
case 'LOGCLEAR':
if (connections[this.hash] && connections[this.hash].buffers) {
for(key in connections[this.hash].buffers) {
if(connections[this.hash].buffers.hasOwnProperty(key)) {
if(connections[this.hash].buffers[key] && connections[this.hash].buffers[key].privmsgnotice && connections[this.hash].buffers[key].privmsgnotice.length>0) {
connections[this.hash].buffers[key].privmsgnotice.length=0;
}
}
}
}
break;
case 'BUFFERS':
totalbuffers = 0;
for(key in connections[this.hash].buffers) {
Expand Down Expand Up @@ -506,10 +518,10 @@ server = doServer(tlsOptions,function(socket) {
}
break;
default:
if(typeof connections[this.hash] === 'undefined' )
continue;
/*if(typeof connections[this.hash] === 'undefined' )
continue;*/
// supress joins of channels we are already in because some clients dont react properly.
if(input[i].toString().substr(0,4)=="JOIN") {
if(input[i] && connections[this.hash] && input[i].toString().substr(0,4)=="JOIN") {
command=input[i].toString().trim().split(" ");
if(!command[1])
break;
Expand Down Expand Up @@ -618,7 +630,7 @@ function clientReconnect(socket) {
socket.connected=true;
newdevice=false;
if(!connection.buffers[socket.clientbuffer]) {
connection.buffers[socket.clientbuffer]={data:'',connected:true};
connection.buffers[socket.clientbuffer]={data:'',connected:true,privmsgnotice:[]};
newdevice=true;
}
else
Expand All @@ -644,7 +656,13 @@ function clientReconnect(socket) {
if(connection.channels.hasOwnProperty(key)) {
_channel=connection.channels[key];

socket.write("@time=2020-07-26T09:20:54.103Z;msgid=null :"+connection.nick+"!"+connection.ircuser+"@"+connection.host+" JOIN :"+_channel.name+"\n");
if (_channel.name != "undefined" || typeof _channel.name !== 'undefined') {
socket.write("@time="+new Date().toISOString()+";msgid=back :"+connection.nick+"!"+connection.ircuser+"@"+connection.host+" JOIN :"+_channel.name+"\n");
} else {
continue;
}


_mode_params='';

if ( typeof _channel.modes === 'undefined' )
Expand Down Expand Up @@ -703,15 +721,27 @@ function clientReconnect(socket) {

socket.write(":"+connection.nick+" MODE "+connection.nick+" :+"+connection.umode+"\n");
if(DEBUG)
console.log(":"+connection.nick+" MODE "+connection.nick+" :+"+connection.umode)
if(connection.buffers[socket.clientbuffer] && connection.buffers[socket.clientbuffer].data && connection.buffers[socket.clientbuffer].data.length>0) {
console.log(":"+connection.nick+" MODE "+connection.nick+" :+"+connection.umode);

if (MSG_REDISTRIBUTION && connection.messagetags && connection.buffers[socket.clientbuffer] && connection.buffers[socket.clientbuffer].privmsgnotice && connection.buffers[socket.clientbuffer].privmsgnotice.length>0) {
socket.write(":*jbnc PRIVMSG "+connection.nick+" :Retrieving all privmsgs/notices\n");
for(x=0; x<connection.buffers[socket.clientbuffer].privmsgnotice.length; x++) {
socket.write(connection.buffers[socket.clientbuffer].privmsgnotice[x].line);
}
socket.write(":*jbnc PRIVMSG "+connection.nick+" :End of retrieving all privmsgs/notices\n");
}
else if(!MSG_REDISTRIBUTION && connection.buffers[socket.clientbuffer] && connection.buffers[socket.clientbuffer].data && connection.buffers[socket.clientbuffer].data.length>0) {
socket.write(":*jbnc PRIVMSG "+connection.nick+" :Retrieving all messages\n");
socket.write(connection.buffers[socket.clientbuffer].data+"\n");
connection.buffers[socket.clientbuffer].data='';
socket.write(":*jbnc PRIVMSG "+connection.nick+" :End of retrieving all messages\n");
}
else
socket.write(":*jbnc PRIVMSG "+connection.nick+" :There is no new message\n");

if(connection.buffers[socket.clientbuffer] && connection.buffers[socket.clientbuffer].data && connection.buffers[socket.clientbuffer].data.length>0) {
connection.buffers[socket.clientbuffer].data='';
}
}
}

Expand Down Expand Up @@ -756,7 +786,7 @@ function clientConnect(socket) {

// client buffers
connection.buffers = {};
connection.buffers[socket.clientbuffer] = {data:'',connected:true};
connection.buffers[socket.clientbuffer] = {data:'',connected:true,privmsgnotice:[]};
socket.connected=true;

// irc server connection data
Expand Down Expand Up @@ -849,6 +879,9 @@ function clientConnect(socket) {
this.write("CAP REQ :message-tags\n");
this.messagetags=true;
}
if(lines[n].trim().indexOf("away-notify")>=0) {
this.write("CAP REQ :away-notify\n");
}
if(this.messagetags && lines[n].trim().indexOf("server-time")>=0) {
this.write("CAP REQ :server-time\n");
}
Expand Down Expand Up @@ -904,7 +937,11 @@ function clientConnect(socket) {
this.write("CAP END\n");
}
}


if(data[1]=="900") {
this.account = data[4];
}

let s = data[1];

if ( this.messagetags && (data[2]=="JOIN" || data[2]=="PART" || data[2]=="QUIT" || data[2]=="MODE" || data[2]=="PING" || data[2]=="NICK" || data[2]=="KICK") ) {
Expand Down Expand Up @@ -1065,10 +1102,10 @@ function clientConnect(socket) {
}
}
else {
_regex = new RegExp(_mode[i],"g")
_regex = new RegExp(_mode[i],"g");
if(_sender==_target && _target==this.nick || _sender=="NickServ" && _target==this.nick || _sender=="OperServ" && _target==this.nick)
this.umode=this.umode.replace(_regex,"");
else if(curchan != null && (_mode[i]!='o' && _mode[i]!='v' && _mode[i]!='h'))
else if(curchan != null && (_mode[i]!='o' && _mode[i]!='v' && _mode[i]!='h') && curchan.modes)
curchan.modes=curchan.modes.replace(_regex,"");
if((_target.indexOf("#")!=-1||_target.indexOf("&")!=-1) && (_mode[i]=='o' || _mode[i]=='k' || _mode[i]=='v' || _mode[i]=='h' || _mode[i]=='l' ||
_mode[i]=='e' || _mode[i]=='b' || _mode[i]=='I' || _mode[i]=='q' || _mode[i]=='f' ||
Expand Down Expand Up @@ -1172,13 +1209,13 @@ function clientConnect(socket) {
if(this.channels[__channel]) {
this.channels[__channel].names.push(_nick);
this.channels[__channel].userhosts.push(this.userHostInNames?_userhost:"*@*");
if(this.channels[__channel].isop && this.channels[__channel].aop.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
if(this.channels[__channel].isop && this.channels[__channel].aop && this.channels[__channel].aop.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
this.write("MODE "+this.channels[__channel].name+" +o "+_nick+"\n");
}
if((this.channels[__channel].isop || this.channels[__channel].ishop) && this.channels[__channel].aoh.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
if((this.channels[__channel].isop || this.channels[__channel].ishop) && this.channels[__channel].aoh && this.channels[__channel].aoh.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
this.write("MODE "+this.channels[__channel].name+" +h "+_nick+"\n");
}
if((this.channels[__channel].isop || this.channels[__channel].ishop) && this.channels[__channel].aov.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
if((this.channels[__channel].isop || this.channels[__channel].ishop) && this.channels[__channel].aov && this.channels[__channel].aov.indexOf(_nick+"!"+_userhost)>=0 && this.opmode) {
this.write("MODE "+this.channels[__channel].name+" +v "+_nick+"\n");
}
}
Expand Down Expand Up @@ -1319,9 +1356,76 @@ function clientConnect(socket) {
for(m=0;m<this.parents.length;m++) {
this.parents[m].write(lines[n]+"\n");
}
}

// Check the last 300 messages that will be sent on the irc web client to sort the new messages
if (MSG_REDISTRIBUTION && this.messagetags) {
if (lines[n].substr(0,1) == "@") { // only line tags
/*
result_messagetags = lines[n].split(" ")[0]; // @time=2020-12-31T05:46:20.951Z;msgid=bUxJGIgyI3Xafw42ccbHTd;account=Sympa
nick: line.split(" ")[1].substr(1).split("!")[0]
ident: line.split(" ")[1].substr(1).split("!")[1].split("@")[0]
hostname: line.split(" ")[1].substr(1).split("!")[1].split("@")[1]
cmd: line.split(" ")[2]
target: line.split(" ")[3]
message: line.split(" ").splice(4).join(' ').substr(1)
account: result_messagetags.split(";")[2].split("=")[1]
time: result_messagetags.split(";")[0].replace("@time=","")
msgid: result_messagetags.split(";")[1].split("=")[1]
*/

// Ignore CTCP request/responses
if (
(lines[n].split(" ")[2] === 'PRIVMSG' || lines[n].split(" ")[2] === 'NOTICE') &&
lines[n].split(" ").splice(4).join(' ').substr(1) && lines[n].split(" ").splice(4).join(' ').substr(1)[0] === '\x01'
) {
// We do want to log ACTIONs though
if (!lines[n].split(" ").splice(4).join(' ').substr(1).startsWith('\x01ACTION ')) {
console.log("Ignoring CTCP");
return;
}
}

if (lines[n].split(" ")[2] === "PRIVMSG" || lines[n].split(" ")[2] === "NOTICE") {
for(key in this.buffers) {
if(this.buffers.hasOwnProperty(key)) {
_n = lines[n].split(" ")[3]; //PRIVMSG <target>
_l = 1;

// Number of targets found
for(x=0; x<this.buffers[key].privmsgnotice.length; x++) {
if ( this.buffers[key].privmsgnotice[x].target === _n) {
_l++;
}
}

// If it exceeds 300, then the first is always deleted
for(x=0; x<this.buffers[key].privmsgnotice.length; x++) {
if ( this.buffers[key].privmsgnotice[x].target === _n) {
if (_l>=300) {
console.log("exceeds: %s", _l);
this.buffers[key].privmsgnotice.splice(x,1);
break;
}
}
}

// Adding all messages
this.buffers[key].privmsgnotice.push({
target: _n,
line: lines[n]+"\n"
});
}
}
}

}



}
// store clientbuf if not connected
if(lines[n].indexOf("PRIVMSG")>=0 || lines[n].indexOf("NOTICE")>=0 || lines[n].indexOf("WALLOPS")>=0 || lines[n].indexOf("GLOBOPS")>=0 || lines[n].indexOf("CHATOPS")>=0) {
else if(lines[n].indexOf("PRIVMSG")>=0 || lines[n].indexOf("NOTICE")>=0 || lines[n].indexOf("WALLOPS")>=0 || lines[n].indexOf("GLOBOPS")>=0 || lines[n].indexOf("CHATOPS")>=0) {
for(key in this.buffers) {
if(this.buffers.hasOwnProperty(key)) {
if(!this.buffers[key].connected) {
Expand Down