e33f6f7cfd
This commit adds a websocket server that clients can connect and authenticate to. Once they're authenticated, they will start to receive relevant events. One issue is that the server does not ping for dead connections yet and the fact that new listeners for the guild are added for each connection. There is also the bug in WatchedGuild that prevents other bridge users from seeing eachother's messages.
104 lines
3.4 KiB
JavaScript
104 lines
3.4 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;
|
|
|
|
// TODOOOOOO: bridge user's wont get message events from other bridge users in the same channel
|
|
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;
|