diff --git a/.gitignore b/.gitignore index 36420af..0d9e779 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -config.json \ No newline at end of file +config.json +nickmap.json \ No newline at end of file diff --git a/forwarder.js b/forwarder.js index 5849a0b..d314ec6 100644 --- a/forwarder.js +++ b/forwarder.js @@ -1,9 +1,12 @@ +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() { @@ -62,6 +65,41 @@ module.exports = class Forwarder { } } + 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 @@ -76,6 +114,13 @@ module.exports = class Forwarder { } 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": @@ -98,6 +143,10 @@ module.exports = class Forwarder { 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}`); diff --git a/nickmap.js b/nickmap.js new file mode 100644 index 0000000..a7a2c63 --- /dev/null +++ b/nickmap.js @@ -0,0 +1,39 @@ +var fs = require("fs"); +var process = require("process"); + +module.exports = class NickMap { + constructor(filename) { + this.filename = filename; + this.map = {}; + this.modified = false; + if (fs.existsSync(this.filename)) { + this.map = JSON.parse(fs.readFileSync(this.filename).toString("utf8")); + } + setInterval(this.saveFile.bind(this), 1000); + } + + saveFile() { + if (!this.modified) return; + this.modified = false; + fs.writeFile(this.filename, JSON.stringify(this.map), (err) => { + if (err) { + console.log("Failed to save nickname map file"); + process.exit(-1); + } + }); + } + + get(uid) { + return this.map[uid]; + } + + set(uid, name) { + this.modified = true; + + if (name) { + this.map[uid] = name; + } else { + delete this.map[uid]; + } + } +} \ No newline at end of file