bridgecord/WatchedGuild.js

103 lines
3.3 KiB
JavaScript

import { EventEmitter } from "events";
import { wait } from "./common.js";
class WatchedGuild extends EventEmitter {
constructor() {
super();
this.knownWebhooks = new Map();
this.upstreamGuildId = null;
}
pushEvent(e) {
this.emit("pushed", e);
}
holdForEvent(timeout) {
return new Promise((outerResolve, outerReject) => {
let handler;
Promise.race([
new Promise((resolve, reject) => {
// potential memory leak here when too many promises are created and waiting
handler = (event) => {
resolve(event);
};
this.once("pushed", handler);
}),
wait(timeout, true)
]).then((result) => {
if (handler)
this.removeListener("pushed", handler);
outerResolve(result);
}).catch(() => {
if (handler)
this.removeListener("pushed", handler);
outerResolve(null);
});
});
}
discordConnect(bot) {
this.bot = bot;
this.guildObject = this.bot.guilds.find(e => e.id === this.upstreamGuildId);
if (!this.guildObject) {
throw new Error("Could not find guild object from bot cache by id (is the upstreamGuildId valid and does the bot have access to it?)");
}
this.bot.on("GUILD_CREATE", (guild) => {
if (guild.id === this.upstreamGuildId)
this.guildObject = guild;
});
this.bot.on("GUILD_UPDATE", (guild) => {
if (guild.id === this.upstreamGuildId)
this.guildObject = guild;
});
this.bot.on("MESSAGE_CREATE", (message) => {
if (message.guild_id !== this.upstreamGuildId)
return;
const maybeKnownWebhook = this.knownWebhooks.get(message.channel_id);
if (maybeKnownWebhook && maybeKnownWebhook.id === message.webhook_id)
return; // ignore messages coming from our webhook
this.pushEvent({
eventType: "MESSAGE_CREATE",
message: message
});
});
}
userFacingChannelList() {
return this.guildObject.channels.map(channel => ({ id: channel.id, name: channel.name, position: channel.position, type: channel.type, nsfw: channel.nsfw }));
}
async discordSendMessage(content, channelId, username, avatarURL=undefined) {
let webhook = this.knownWebhooks.get(channelId);
if (!webhook) {
webhook = (await this.bot.api(["GET", `/channels/${channelId}/webhooks`]))
.find(e => e.name === "well_known__bridge");
if (!webhook)
webhook = await this.bot.api(["POST", `/channels/${channelId}/webhooks`], {
name: "well_known__bridge"
});
this.knownWebhooks.set(channelId, webhook);
}
await this.bot.api(["POST", `/webhooks/${webhook.id}/${webhook.token}?wait=true`], {
content,
username,
avatar_url: avatarURL,
tts: false,
allowed_mentions: {
parse: ["users"]
}
});
}
}
export default WatchedGuild;