add endpoint to poll all guilds the user has access to

This commit is contained in:
hippoz 2022-02-02 23:48:18 +02:00
parent 6850b0828b
commit ea18f74503
Signed by: hippoz
GPG key ID: 7C52899193467641
5 changed files with 59 additions and 14 deletions

View file

@ -210,7 +210,15 @@ class DiscordClient extends EventEmitter {
reason = reason.toString(); reason = reason.toString();
this.emit("close", code, reason); this.emit("close", code, reason);
console.error(`DiscordClient: on \`close\`: disconnected from gateway: code \`${code}\`, reason \`${reason}\``); console.error(`DiscordClient: on \`close\`: disconnected from gateway: code \`${code}\`, reason \`${reason}\``);
}) });
ws.on("error", (e) => {
console.error("DiscordClient: websocket error:", e);
console.log("DiscordClient: reconnecting in a couple of miliseconds");
setTimeout(() => {
this.connect();
}, 400);
});
} }
async api([method, path], body=undefined, throwOnError=true) { async api([method, path], body=undefined, throwOnError=true) {

View file

@ -60,7 +60,7 @@ class WatchedGuild extends EventEmitter {
return; return;
const maybeKnownWebhook = this.knownWebhooks.get(message.channel_id); const maybeKnownWebhook = this.knownWebhooks.get(message.channel_id);
if (maybeKnownWebhook.id === message.webhook_id) if (maybeKnownWebhook && maybeKnownWebhook.id === message.webhook_id)
return; // ignore messages coming from our webhook return; // ignore messages coming from our webhook
this.pushEvent({ this.pushEvent({

View file

@ -36,7 +36,7 @@ class APIClient {
let shouldContinue = true; let shouldContinue = true;
const poll = async () => { const poll = async () => {
this.getRequest(`/guilds/${guildId}/events/poll`) this.getRequest(guildId ? `/guilds/${guildId}/events/poll` : "/events/poll")
.then((result) => { .then((result) => {
if (result.event) { if (result.event) {
callback(result); callback(result);

View file

@ -30,18 +30,24 @@
selectedChannel = guilds[0].channels[0]; selectedChannel = guilds[0].channels[0];
} }
const { poll } = apiClient.createPollingListener(selectedGuild.id, ({ event }) => { const { poll } = apiClient.createPollingListener(null, ({ event }) => {
if (event.eventType === "MESSAGE_CREATE") { if (event.eventType === "MESSAGE_CREATE") {
if (!messageStore[selectedGuild.id]) { const guildId = event.message.guild_id;
messageStore[selectedGuild.id] = []; const channelId = event.message.channel_id;
if (!messageStore[guildId]) {
messageStore[guildId] = {};
} }
messageStore[selectedGuild.id] = [...messageStore[selectedGuild.id], event.message]; if (!messageStore[guildId][channelId]) {
messageStore[guildId][channelId] = [];
}
messageStore[guildId][channelId] = [...messageStore[guildId][channelId], event.message];
} }
}); });
poll(); poll();
}); });
$: selectedGuildMessages = selectedGuild ? (messageStore[selectedGuild.id] || []) : []; $: selectedChannelMessages = selectedGuild ? ((messageStore[selectedGuild.id] || [])[selectedChannel.id] || []) : [];
function onTextEntryMessage(event) { function onTextEntryMessage(event) {
if (!selectedGuild || !selectedChannel) { if (!selectedGuild || !selectedChannel) {
@ -49,8 +55,15 @@
} }
const nonce = Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 10)); const nonce = Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 10));
messageStore[selectedGuild.id] = [ if (!messageStore[selectedGuild.id])
...messageStore[selectedGuild.id] || [], messageStore[selectedGuild.id] = {};
// this looks horrible, however directly accessing the values without
// using a variable for readability is the only way i can get
// reactivity to work
// :(
messageStore[selectedGuild.id][selectedChannel.id] = [
...messageStore[selectedGuild.id][selectedChannel.id] || [],
{ {
channel_id: selectedChannel.id, channel_id: selectedChannel.id,
content: event.detail, content: event.detail,
@ -62,14 +75,14 @@
} }
]; ];
// we could just get the length and subtract 1 but that might introduce some race conditions // we could just get the length and subtract 1 but that might introduce some race conditions
const thisMessageIndex = messageStore[selectedGuild.id].findIndex(e => e._nonce === nonce); const thisMessageIndex = messageStore[selectedGuild.id][selectedChannel.id].findIndex(e => e._nonce === nonce);
apiClient.postRequest(`/guilds/${selectedGuild.id}/channels/${selectedChannel.id}/messages/create`, { apiClient.postRequest(`/guilds/${selectedGuild.id}/channels/${selectedChannel.id}/messages/create`, {
content: event.detail content: event.detail
}).then(() => { }).then(() => {
messageStore[selectedGuild.id][thisMessageIndex]._pendingStatus = "success"; messageStore[selectedGuild.id][selectedChannel.id][thisMessageIndex]._pendingStatus = "success";
}).catch(() => { }).catch(() => {
messageStore[selectedGuild.id][thisMessageIndex]._pendingStatus = "error"; messageStore[selectedGuild.id][selectedChannel.id][thisMessageIndex]._pendingStatus = "error";
}); });
} }
</script> </script>
@ -100,7 +113,7 @@
<div class="card full-card"> <div class="card full-card">
<SelectedGuildInfoDisplay guild={selectedGuild} channel={selectedChannel} /> <SelectedGuildInfoDisplay guild={selectedGuild} channel={selectedChannel} />
<div class="message-list-container"> <div class="message-list-container">
<MessageList messages={selectedGuildMessages} /> <MessageList messages={selectedChannelMessages} />
</div> </div>
</div> </div>
<MessageEntry on:sendmessage={onTextEntryMessage} /> <MessageEntry on:sendmessage={onTextEntryMessage} />

View file

@ -127,4 +127,28 @@ router.get("/guilds/:guildId/events/poll", checkAuth(async (req, res) => {
} }
})); }));
router.get("/events/poll", checkAuth(async (req, res) => {
const { guildAccess } = req.user;
try {
// note: probably not very optimal
const promises = [];
guildAccess.forEach((guildId) => {
const guild = guildMap.get(guildId);
if (guild) {
promises.push(guild.holdForEvent(15000));
}
});
// note: if 2 guild events happen at the same time, one of them may be dropped
Promise.race(promises)
.then(e => {
res.status(200).send({ error: false, event: e })
});
} catch(e) {
console.error("server main: api: guild poll events: error: ", e);
res.status(500).send({ error: true, message: "ERROR_POLL_FAILURE" });
}
}));
export default router; export default router;