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.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;