matrixbridge/ppfun-bridge/src/ppfunsocket.js
2022-01-16 14:56:46 +01:00

140 lines
3.2 KiB
JavaScript

"use strict";
import EventEmitter from 'events';
import WebSocket from 'ws';
class PPfunSocket extends EventEmitter {
constructor(url, apisocketkey) {
super();
this.url = url;
this.apisocketkey = apisocketkey;
this.timeConnected = null;
this.isConnected = false;
this.flagMap = new Map();
this.flagMap.set(null , 'yy');
this.ws;
this.onWsClose = this.onWsClose.bind(this);
console.log('PPfunSocket: Connecting to WebSocket')
this.on('sendChatMessage', (name, uid, msg, cid) => {
if (this.isConnected) {
const flag = (name.endsWith('berg') || name.endsWith('stein'))
? 'il' : this.getFlag(uid);
const pack = ['chat', name, uid, msg, flag, cid];
this.ws.send(JSON.stringify(pack));
}
});
}
getFlag(uid) {
let flag = this.flagMap.get(uid);
if (!flag) {
if (flag !== null) {
this.flagMap.set(uid, null);
this.ws.send(`["getflag", ${uid}]`);
}
return 'yy';
}
return flag;
}
run() {
return new Promise((resolve) => {
this.connect();
this.once('open', () => {
resolve();
})
});
}
connect() {
if (this.ws) {
console.log('PPfunSocket: WebSocket already open, not starting');
}
this.timeConnected = Date.now();
const ws = new WebSocket(this.url, {
headers: {
'authorization': `Bearer ${this.apisocketkey}`,
},
});
this.ws = ws;
ws.on('open', () => {
this.isConnected = true;
this.reqChannels();
this.emit('open');
console.log('PPfunSocket: Connected to WebSocket');
});
ws.on('message', (data, isBinary) => {
if (!isBinary) {
const message = data.toString();
this.onTextMessage(message);
}
});
ws.on('error', (e) => {
console.warn(
'PPfunSocket: Socket encountered error, closing socket',
e.toString(),
);
ws.close;
});
ws.on('close', this.onWsClose);
}
reqChannels() {
if (this.isConnected) {
this.ws.send('["sub","chat"]');
}
}
onWsClose() {
this.emit('close');
this.ws = null;
this.isConnected = false;
// reconnect in 1s if last connect was longer than 7s ago, else 5s
const timeout = this.timeConnected < Date.now() - 7000 ? 1000 : 5000;
console.warn(
`PPfunSocket: Socket is closed. Reconnect will be attempted in ${timeout} ms.`,
);
setTimeout(() => this.connect(), 5000);
}
onTextMessage(message) {
try {
const data = JSON.parse(message);
const msgEvent = data[0];
data.shift();
switch(msgEvent) {
case 'chans':
this.emit('chanList', data);
break;
case 'msg': {
const [name, uid, msg,, cid] = data;
this.emit('chatMessage', name, uid, msg, cid);
break;
}
case 'flag': {
const [uid, flag] = data;
console.log(`PPfunSocket: Got flag ${flag} for user ${uid}`);
this.flagMap.set(uid, flag);
break;
}
default:
// nothing
}
} catch (e) {
console.warn(
`PPfunSocket: An error occured while parsing websocket text message`,
e.toString(),
);
}
}
}
export default PPfunSocket;