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();
this.emit("close", code, 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) {

View file

@ -60,7 +60,7 @@ class WatchedGuild extends EventEmitter {
return;
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
this.pushEvent({

View file

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

View file

@ -30,18 +30,24 @@
selectedChannel = guilds[0].channels[0];
}
const { poll } = apiClient.createPollingListener(selectedGuild.id, ({ event }) => {
const { poll } = apiClient.createPollingListener(null, ({ event }) => {
if (event.eventType === "MESSAGE_CREATE") {
if (!messageStore[selectedGuild.id]) {
messageStore[selectedGuild.id] = [];
const guildId = event.message.guild_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();
});
$: selectedGuildMessages = selectedGuild ? (messageStore[selectedGuild.id] || []) : [];
$: selectedChannelMessages = selectedGuild ? ((messageStore[selectedGuild.id] || [])[selectedChannel.id] || []) : [];
function onTextEntryMessage(event) {
if (!selectedGuild || !selectedChannel) {
@ -49,8 +55,15 @@
}
const nonce = Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 10));
messageStore[selectedGuild.id] = [
...messageStore[selectedGuild.id] || [],
if (!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,
content: event.detail,
@ -62,14 +75,14 @@
}
];
// 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`, {
content: event.detail
}).then(() => {
messageStore[selectedGuild.id][thisMessageIndex]._pendingStatus = "success";
messageStore[selectedGuild.id][selectedChannel.id][thisMessageIndex]._pendingStatus = "success";
}).catch(() => {
messageStore[selectedGuild.id][thisMessageIndex]._pendingStatus = "error";
messageStore[selectedGuild.id][selectedChannel.id][thisMessageIndex]._pendingStatus = "error";
});
}
</script>
@ -100,7 +113,7 @@
<div class="card full-card">
<SelectedGuildInfoDisplay guild={selectedGuild} channel={selectedChannel} />
<div class="message-list-container">
<MessageList messages={selectedGuildMessages} />
<MessageList messages={selectedChannelMessages} />
</div>
</div>
<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;