import IRC from "irc-framework"; import "colors"; import exitHook from 'exit-hook'; import {MatrixClient, SimpleFsStorageProvider} from "@vector-im/matrix-bot-sdk"; import config from "./config.js"; var matrix = {config: config.matrix}, irc = {config: config.irc}; // matrix matrix.storage = new SimpleFsStorageProvider("matrix-data.json"); matrix.client = new MatrixClient(matrix.config.homeserver_url, matrix.config.access_token, matrix.storage); matrix.sendmsg = body => matrix.client.sendMessage(matrix.config.room_id, {body, msgtype: "m.text", "m.mentions": {}/*, "format": "org.matrix.custom.html", "formatted_body": `
${escapeHTML(body)}
\n`*/}); matrix.displaynames = new Map(); matrix.getDisplayName = async function getDisplayName(userId) { var displayname = matrix.displaynames.get(userId); if (!displayname) { try { var {displayname} = await matrix.client.getUserProfile(userId); } catch (error) { console.error(error.message); } if (!displayname) displayname = userId.match(/^@(.+):/)?.[1] || userId; matrix.displaynames.set(userId, displayname); setTimeout(() => { matrix.displaynames.delete(userId); }, 600000); } return displayname; } await matrix.client.start(); console.log("matrix ready"); // irc irc.client = new IRC.Client(); irc.client.connect(Object.assign(irc.config, { message_max_length: 450, auto_reconnect_max_retries: Infinity })); irc.channel = irc.client.channel(irc.config.channel); irc.client.on("connected", () => { console.log("irc connected"); irc.channel.join(); }); irc.client.on("raw", ({from_server, line}) => { if (from_server) { console.log(line.trim().blue); } else { console.log(line.trim().red); } }) irc.client.on('notice', function (event) { if (event.target?.toLowerCase() != irc.config.channel.toLowerCase()) return; matrix.sendmsg(`[NOTICE] <\u2063${event.nick}> ${event.message}`); }); irc.client.on('privmsg', function (event) { if (event.target?.toLowerCase() != irc.config.channel.toLowerCase()) return; if ([event.nick, event.ident].includes("Dumcord")) return; matrix.sendmsg(`<\u2063${event.nick}> ${event.message}`); }); irc.client.on('action', function (event) { if (event.target?.toLowerCase() != irc.config.channel.toLowerCase()) return; matrix.sendmsg(`* ${event.nick} ${event.message}`); }); irc.client.on("join", event => { if (event.channel?.toLowerCase() != irc.config.channel.toLowerCase()) return; if (event.nick == irc.config.nick) return; matrix.sendmsg(`${event.nick} (${event.ident}@${event.hostname}) joined`); }); irc.client.on("part", event => { if (event.channel?.toLowerCase() != irc.config.channel.toLowerCase()) return; matrix.sendmsg(`${event.nick} (${event.ident}@${event.hostname}) left: ${event.message}`); }); irc.client.on("quit", event => { //if (event.channel.toLowerCase() != irc.config.channel.toLowerCase()) return; matrix.sendmsg(`${event.nick} (${event.ident}@${event.hostname}) disconnected: ${event.message}`); }); exitHook(signal => { irc.client.quit(`${signal}`); }); process.stdin.on("data", data => { irc.channel.say(data.toString().trim()); }); // matrix matrix.client.on("room.message", async (room_id, event) => { if (room_id != matrix.config.room_id) return; if (event.sender == await matrix.client.getUserId()) return; if (event.sender == "@roboirc:matrix.org") return; if (typeof event.content?.body !== "string") return; var replied_event_id = event.content["m.relates_to"]?.["m.in_reply_to"]?.event_id; if (replied_event_id) { try { let replied_event = await matrix.client.getEvent(room_id, replied_event_id); let displayname = await matrix.getDisplayName(replied_event.sender); let msg = `> ${antimatch(displayname)}: ${replied_event.content?.body || JSON.stringify(replied_event.content || replied_event)}`; irc.channel.say(truncate(flatten(msg))); } catch(error) { console.error(error.message); irc.channel.say(`> failed to load replied message: ${error.message}`); } } let displayname = await matrix.getDisplayName(event.sender); let msg = `${antimatch(displayname)}: ${event.content.body}`; irc.channel.say(truncate(flatten(msg))); if (event.content.filename && event.content.filename != event.content.body) irc.channel.say(event.content.filename); }); function splitInHalf(string) { var sliceat = Math.floor(string.length / 2); return [string.slice(0, sliceat), string.slice(sliceat, string.length)] } function antimatch(string) { //return splitInHalf(string).join("\u2063"); return string.split("").join("\u2063"); } function flatten(txt) { return txt.replaceAll("\n", "\\n"); } function truncate(txt, len = 440) { var b = Buffer.from(txt); if (b.length > len) { return b.subarray(0, len).toString() + `…${(txt.length - len)}`; } else { return txt; } } global.matrix = matrix; global.irc = irc;