matrix-irc-relaybot/forwarder.js

158 lines
4.1 KiB
JavaScript

var NickMap = require("./nickmap");
module.exports = class Forwarder {
constructor(clientIRC, clientMatrix, mappingI2M, mappingM2I) {
this.clientIRC = clientIRC;
this.clientMatrix = clientMatrix;
this.mappingI2M = mappingI2M;
this.mappingM2I = mappingM2I;
this.nickMap = new NickMap("./nickmap.json");
}
joinIRCRooms() {
console.log("Joining IRC Rooms...");
for (const room of Object.keys(this.mappingI2M)) {
this.clientIRC.say("ChanServ", "INVITE " + room);
this.clientIRC.join(room);
}
}
start() {
this.joinIRCRooms();
console.log("Starting relay");
this.clientIRC.on("registered", this.onReconnect.bind(this));
this.clientIRC.on("message", this.onIRCMessage.bind(this));
this.clientMatrix.on("Room.timeline", this.onMatrixMessage.bind(this));
}
onReconnect() {
console.log("IRC client reconnected");
this.joinIRCRooms();
}
onIRCMessage(event) {
if (!event.target) {
// Not something we care about
return;
}
if (!this.mappingI2M[event.target]) {
// Not a mapped channel
return;
}
let content = null;
if (event.type == "action") {
content = {
msgtype: "m.text",
body: `* ${event.nick} ${event.message}`
}
} else {
content = {
msgtype: "m.text",
body: `[${event.nick}] ${event.message}`
}
}
this.clientMatrix.sendMessage(this.mappingI2M[event.target], content);
}
stripMatrixName(name) {
if (name.length < 16) {
return name;
} else {
return name.slice(0, 16);
}
}
isMatrixCommand(msg) {
return msg.startsWith("!");
}
handleMatrixCommand(sender, msg) {
let splitted = msg.split(" ");
let cmd = splitted[0].slice(1);
switch (cmd) {
case "nick":
if (splitted.length < 2) {
this.nickMap.set(sender.userId, null);
this.clientMatrix.sendMessage(sender.roomId, {
msgtype: "m.text",
body: `Nickname of '${sender.name}' cleared`
});
} else if (splitted.length >= 3 || splitted[1].length > 16) {
this.clientMatrix.sendMessage(sender.roomId, {
msgtype: "m.text",
body: "Invalid nickname format (too long or contains space)"
});
} else {
this.nickMap.set(sender.userId, splitted[1]);
this.clientMatrix.sendMessage(sender.roomId, {
msgtype: "m.text",
body: `Nickname of '${sender.name}' changed to '${splitted[1]}'`
});
}
return true;
default:
return false;
}
}
onMatrixMessage(event, room, toStartOfTimeline) {
if (toStartOfTimeline) {
return; // Ignore pagniation
}
if (!this.mappingM2I[room.roomId]) {
return; // Unmapped room
}
if (event.sender.userId == this.clientMatrix.getUserId()) {
return; // Prevent loop
}
let content = event.getContent();
if (event.getType() == "m.room.message" && this.isMatrixCommand(content.body)) {
if (this.handleMatrixCommand(event.sender, content.body)) {
return;
}
}
let msgTxt = null;
switch (event.getType()) {
case "m.sticker":
msgTxt = `${content.body} ${this.clientMatrix.mxcUrlToHttp(content.url)}`;
break;
case "m.room.message":
switch (content.msgtype) {
case "m.image":
case "m.audio":
case "m.file":
case "m.video":
msgTxt = `${content.body} ${this.clientMatrix.mxcUrlToHttp(content.url)}`;
break;
default:
msgTxt = content.body;
break;
}
break;
}
if (msgTxt != null) {
let name = this.stripMatrixName(event.sender.name);
let mappedName = this.nickMap.get(event.sender.userId);
if (mappedName) {
name = mappedName;
}
if (content.msgtype == "m.emote") {
// Special format for emote
this.clientIRC.say(this.mappingM2I[room.roomId], `* ${name} ${msgTxt}`);
} else {
this.clientIRC.say(this.mappingM2I[room.roomId], `[${name}] ${msgTxt}`);
}
}
}
}