This repository has been archived on 2022-10-14. You can view files and clone it, but cannot push or open issues/pull-requests.
fookat-jpdld-bridge/index.js

167 lines
6.7 KiB
JavaScript

(async function (){
require('dotenv').config()
global.RocketChat = require('@rocket.chat/sdk');
global.driver = RocketChat.driver;
global.api = RocketChat.api;
global.methodCache = RocketChat.methodCache;
await driver.connect();
await driver.login(); // using environment variables
await driver.subscribeToMessages();
global.Discord = require("discord.js");
global.dClient = new Discord.Client({disableEveryone: true});
await dClient.login(process.env.DISCORD_TOKEN);
dClient.on("error", console.error);
const JPDLD_GUILD_ID = "357038384121905152";
// fookat rocket to jpdld discord
var receivedRcMsgIDs = [];
await driver.reactToMessages(async function(e, m, mo){
if (e) return console.error(e);
if (receivedRcMsgIDs.includes(m._id)) return; // apparently the server re-sends messages with the same id to add url information for embeds; so we need to collect the msg IDs to ignore those
else receivedRcMsgIDs.push(m._id);
if (m.u._id == driver.userId) return;
if (!m.mentions && !m.channels) return; // ignore user join/leave messages and whatever else; TODO any better way to differentiate them?
var roomName = mo && mo.roomName || await driver.getRoomId(m.rid);
if (!roomName.startsWith("jpdld_")) return;
var dcname = roomName.substr("jpdld_".length);
var jpdldGuild = dClient.guilds.get(JPDLD_GUILD_ID);
if (!jpdldGuild) return console.warn("Can't find JPDLD guild!");
var dc = jpdldGuild.channels.find(c => c.name == dcname);
if (!dc) return console.warn(`Couldn't find JPDLD Discord channel ${dcname} to bridge to RC channel ${roomName}`); // TODO add reaction
if (!dc.wh) {
console.log("Attaching webhook to dc", dc.name);
try {
if (dcname in require("./webhooks")) {
let wh = require("./webhooks")[dcname];
dc.wh = new Discord.WebhookClient(wh.id, wh.token);
} else {
let whs = await dc.fetchWebhooks();
let wh = whs.find(w => w.name == "fookat bridge");
if (wh) dc.wh = wh;
else {
dc.wh = await dc.createWebhook("fookat bridge", undefined, "Automatically created webhook to bridge to fookat.tk");
}
}
} catch(e) {
console.error(`Couldn't get webhook for ${dcname}:`, e.message);
await fallbackSend();
return;
}
}
try {
await dc.wh.send(m.msg,{
username: `${m.u.username} @ fookat.tk`.substr(0,32),
avatarURL: `https://fookat.tk/avatar/${m.u.username}?${process.pid}`,
split: true,
disableEveryone: true,
embeds: m.attachments ? m.attachments.map(a => ({
title: a.title,
url: a.title_link ? "https://fookat.tk" + a.title_link : undefined,
description: a.description,
image: a.image_url ? {url: "https://fookat.tk" + a.image_url} : undefined
})) : undefined
});
} catch(e) {
console.error(`JPDLD webhook send failure:`, e.message);
await fallbackSend();
}
async function fallbackSend() {
await dc.send(`**${m.u.username}:** ${m.msg}`, {
split: true,
embeds: m.attachments ? m.attachments.map(a => ({
title: a.title,
url: a.title_link ? "https://fookat.tk" + a.title_link : undefined,
description: a.description,
image: a.image_url ? {url: "https://fookat.tk" + a.image_url} : undefined
})) : undefined
}).catch(e => console.error(`Couldn't send fallback message to JPDLD channel ${dcname} (${e.message})`));
}
});
// TODO synchronize message deletes
// jpdld discord to fookat rocket
//var rcroomBlacklist = [];
dClient.on("message", async function(message){
if (!message.guild || message.guild.id != JPDLD_GUILD_ID) return;
if (message.author.id == dClient.user.id || (message.channel.wh && message.channel.wh.id == message.author.id)) return;
var rcroom = "jpdld_" + message.channel.name;
//if (rcroomBlacklist.includes(rcroom)) return;
async function sendrcmsg(rid) {
var rcmsg = driver.prepareMessage();
rcmsg.rid = rid || await driver.getRoomId(rcroom);
rcmsg.msg = message.cleanContent;
rcmsg.alias = message.member && message.member.displayName || message.author.username;
rcmsg.avatar = message.author.avatarURL || message.author.defaultAvatarURL;
rcmsg.attachments = message.attachments.array().map(attachment => ({
title: attachment.filename,
title_link: attachment.url,
title_link_download: true,
image_url: attachment.width ? attachment.url : undefined,
audio_url: [".ogg", ".mp3", ".wav", ".flac"].some(ext=>attachment.filename.endsWith(ext)) ? attachment.url : undefined,
video_url: [".mp4", ".webm", ".mov", ".avi"].some(ext=>attachment.filename.endsWith(ext)) ? attachment.url : undefined
})).concat(message.embeds.map(embed => embed.type == "rich" ? {
author_name: embed.author && embed.author.name,
author_link: embed.author && embed.author.url,
author_icon: embed.author && embed.author.iconURL,
title: embed.title,
title_link: embed.url,
title_link_download: false,
color: embed.hexColor,
text: embed.description,
image_url: embed.image && embed.image.url,
thumb_url: embed.thumbnail && embed.thumbnail.url,
fields: embed.fields && embed.fields.map(f => ({title: f.name, value: f.value, short: f.inline})),
ts: embed.timestamp
} : undefined)).filter(x=>x);
message.rcmsg = await driver.sendMessage(rcmsg);
}
try {
await sendrcmsg();
} catch (e) {
console.warn(`Failed to send message from JPDLD guild to fookat room ${rcroom}; attempting to create room and send again. (${e.message})`);
let res = await api.post("channels.create", {name: rcroom});
if (!res.success) return console.error("Failed to create rc channel", rcroom);
await driver.subscribe("stream-room-messages", res.channel._id);
try {
await sendrcmsg(res.channel._id);
methodCache.reset("getRoomIdByNameOrId", rcroom);
return;
} catch(e) {
console.error(e.message);
}
/*try {
//await new Promise(r => setTimeout(r, 3000));
await sendrcmsg();
} catch(e) {
console.warn(`Failed to send JPDLD message to fookat room ${rcroom} after creating room; adding to blacklist. (${e.message})`);
rcroomBlacklist.push(rcroom);
}*/
}
});
// synchronize message edits and deletes too, from discord to rocket
dClient.on("messageUpdate", async function (oldMessage, newMessage) {
if (newMessage.rcmsg) {
await api.post('chat.update', {
roomId: newMessage.rcmsg.rid,
msgId: newMessage.rcmsg._id,
text: newMessage.cleanContent
}).catch(e => console.error("Failed to synchronize message edit from discord to rocket:", e.message));
}
});
dClient.on("messageDelete", async function (message) {
if (message.rcmsg) {
await api.post('chat.delete', {
roomId: message.rcmsg.rid,
msgId: message.rcmsg._id,
//asUser: true // ??
}).catch(e => console.error("Failed to syncrhonize message delete from discord to rocket:", e.message));
}
});
})();