155 lines
4.9 KiB
JavaScript
155 lines
4.9 KiB
JavaScript
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": `<pre>${escapeHTML(body)}</pre>\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; |