diff --git a/src/helpers/messages/get_messages.ts b/src/helpers/messages/get_messages.ts index d262ae912..74f5ebd3f 100644 --- a/src/helpers/messages/get_messages.ts +++ b/src/helpers/messages/get_messages.ts @@ -19,6 +19,12 @@ export async function getMessages( throw new Error(bot.constants.Errors.INVALID_GET_MESSAGES_LIMIT); } + if (options) { + if (bot.utils.hasProperty(options, "around")) options.around = (options.around as bigint).toString(); + if (bot.utils.hasProperty(options, "before")) options.before = (options.before as bigint).toString(); + if (bot.utils.hasProperty(options, "after")) options.after = (options.after as bigint).toString(); + } + const result = await bot.rest.runMethod( bot.rest, "get", diff --git a/src/rest/process_global_queue.ts b/src/rest/process_global_queue.ts index 6875c6b57..a540d2ac9 100644 --- a/src/rest/process_global_queue.ts +++ b/src/rest/process_global_queue.ts @@ -22,12 +22,9 @@ export async function processGlobalQueue(rest: RestManager) { break; } - const request = rest.globalQueue[0]; + const request = rest.globalQueue.shift(); // REMOVES ANY POTENTIAL INVALID CONFLICTS - if (!request) { - rest.globalQueue.shift(); - continue; - } + if (!request) continue; // CHECK RATELIMITS FOR 429 REPEATS // IF THIS URL IS STILL RATE LIMITED, TRY AGAIN @@ -36,17 +33,14 @@ export async function processGlobalQueue(rest: RestManager) { const bucketResetIn = request.payload.bucketId ? rest.checkRateLimits(rest, request.payload.bucketId) : false; if (urlResetIn || bucketResetIn) { - const rateLimitedRequest = rest.globalQueue.shift(); - if (rateLimitedRequest) { - // ONLY ADD TIMEOUT IF ANOTHER QUEUE IS NOT PENDING - setTimeout(() => { - rest.debug(`[REST - processGlobalQueue] rate limited, running setTimeout.`); - // THIS REST IS RATE LIMITED, SO PUSH BACK TO START - rest.globalQueue.unshift(rateLimitedRequest); - // START QUEUE IF NOT STARTED - rest.processGlobalQueue(rest); - }, urlResetIn || (bucketResetIn as number)); - } + // ONLY ADD TIMEOUT IF ANOTHER QUEUE IS NOT PENDING + setTimeout(() => { + rest.debug(`[REST - processGlobalQueue] rate limited, running setTimeout.`); + // THIS REST IS RATE LIMITED, SO PUSH BACK TO START + rest.globalQueue.unshift(request); + // START QUEUE IF NOT STARTED + rest.processGlobalQueue(rest); + }, urlResetIn || (bucketResetIn as number)); continue; } @@ -94,12 +88,10 @@ export async function processGlobalQueue(rest: RestManager) { // If NOT rate limited remove from queue if (response.status !== 429) { request.request.reject(new Error(`[${response.status}] ${error}`)); - rest.globalQueue.shift(); } else { if (request.payload.retryCount++ >= rest.maxRetryCount) { rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(request.payload)}`); // REMOVE ITEM FROM QUEUE TO PREVENT RETRY - rest.globalQueue.shift(); request.request.reject( new Error(`[${response.status}] The request was rate limited and it maxed out the retries limit.`) ); @@ -107,7 +99,9 @@ export async function processGlobalQueue(rest: RestManager) { } // WAS RATE LIMITED. PUSH TO END OF GLOBAL QUEUE, SO WE DON'T BLOCK OTHER REQUESTS. - rest.globalQueue.push(rest.globalQueue.shift()!); + console.log("delaying request, rate limit 1", rest.globalQueue.length); + rest.globalQueue.push(request); + console.log("delaying request, rate limit 2", rest.globalQueue.length); } continue; @@ -116,16 +110,12 @@ export async function processGlobalQueue(rest: RestManager) { // SOMETIMES DISCORD RETURNS AN EMPTY 204 RESPONSE THAT CAN'T BE MADE TO JSON if (response.status === 204) { rest.debug(`[REST - FetchSuccess] URL: ${request.urlToUse} | ${JSON.stringify(request.payload)}`); - // REMOVE FROM QUEUE - rest.globalQueue.shift(); request.request.respond({ status: 204 }); } else { // CONVERT THE RESPONSE TO JSON const json = await response.json(); rest.debug(`[REST - fetchSuccess] ${JSON.stringify(request.payload)}`); - // REMOVE FROM QUEUE - rest.globalQueue.shift(); request.request.respond({ status: 200, body: JSON.stringify(json), @@ -135,8 +125,6 @@ export async function processGlobalQueue(rest: RestManager) { // SOMETHING WENT WRONG, LOG AND RESPOND WITH ERROR rest.debug(`[REST - fetchFailed] Payload: ${JSON.stringify(request.payload)} | Error: ${error}`); request.request.reject(error); - // REMOVE FROM QUEUE - rest.globalQueue.shift(); } } diff --git a/src/rest/process_queue.ts b/src/rest/process_queue.ts index d54390853..0539bd882 100644 --- a/src/rest/process_queue.ts +++ b/src/rest/process_queue.ts @@ -1,7 +1,7 @@ import { RestManager } from "../bot.ts"; /** Processes the queue by looping over each path separately until the queues are empty. */ -export function processQueue(rest: RestManager, id: string) { +export function processQueue(rest: RestManager, id: string, redo?: "redo") { const queue = rest.pathQueues.get(id); if (!queue) return; @@ -12,28 +12,43 @@ export function processQueue(rest: RestManager, id: string) { // IF THIS DOESNT HAVE ANY ITEMS JUST CANCEL, THE CLEANER WILL REMOVE IT. if (!queuedRequest) break; + // console.log("process queue", 3); + // if (redo) console.log("process queue redo", 3); + const basicURL = rest.simplifyUrl(queuedRequest.request.url, queuedRequest.request.method.toUpperCase()); // IF THIS URL IS STILL RATE LIMITED, TRY AGAIN const urlResetIn = rest.checkRateLimits(rest, basicURL); if (urlResetIn) { + // if (redo) console.log("process queue redo", 4); + // console.log("process queue", 4); + // ONLY ADD TIMEOUT IF ANOTHER QUEUE IS NOT PENDING if (!queue.isWaiting) { queue.isWaiting = true; setTimeout(() => { + // if (redo) console.log("process queue redo", 5); + // console.log("process queue", 5); + queue.isWaiting = false; + rest.debug(`[REST - processQueue] rate limited, running setTimeout.`); - rest.processQueue(rest, id); + rest.processQueue(rest, id, "redo"); }, urlResetIn); } // BREAK WHILE LOOP break; } + + // console.log("process queue", 6); + // if (redo) console.log("process queue redo", 6); + // IF A BUCKET EXISTS, CHECK THE BUCKET'S RATE LIMITS const bucketResetIn = queuedRequest.payload.bucketId ? rest.checkRateLimits(rest, queuedRequest.payload.bucketId) : false; + if (bucketResetIn) console.log("process queue bucketed", bucketResetIn); // THIS BUCKET IS STILL RATELIMITED, RE-ADD TO QUEUE if (bucketResetIn) continue; // EXECUTE THE REQUEST @@ -62,7 +77,7 @@ export function processQueue(rest: RestManager, id: string) { urlToUse, }); rest.processGlobalQueue(rest); - queue.requests.splice(0, 1) + queue.requests.shift(); } // ONCE QUEUE IS DONE, WE CAN TRY CLEANING UP diff --git a/tests/helpers/messages/addReaction.ts b/tests/helpers/messages/addReaction.ts index 0e521d0c0..5633eb2a5 100644 --- a/tests/helpers/messages/addReaction.ts +++ b/tests/helpers/messages/addReaction.ts @@ -2,6 +2,8 @@ import { Bot } from "../../../src/bot.ts"; import { assertEquals, assertExists } from "../../deps.ts"; import { delayUntil } from "../../utils.ts"; +const reactionCounters = new Map(); + export async function addReactionTest( bot: Bot, guildId: bigint, @@ -59,18 +61,17 @@ export async function addReactionTest( } } - let reactions = 0; + reactionCounters.set(message.id, 0); bot.events.reactionAdd = function (bot, payload) { - if (payload.messageId !== message.id) return; - - reactions++; + const current = reactionCounters.get(payload.messageId) || 0; + reactionCounters.set(payload.messageId, current + 1); }; if (options.single) await bot.helpers.addReaction(message.channelId, message.id, emojiId); else await bot.helpers.addReactions(message.channelId, message.id, emojiIds, options.ordered); - await delayUntil(10000, () => reactions === (options.single ? 1 : emojiIds.length)); + await delayUntil(10000, () => reactionCounters.get(message.id) === (options.single ? 1 : emojiIds.length)); - assertEquals(reactions, options.single ? 1 : emojiIds.length); + assertEquals(reactionCounters.get(message.id), options.single ? 1 : emojiIds.length); } diff --git a/tests/mod.ts b/tests/mod.ts index f759a2cec..9c94c5a44 100644 --- a/tests/mod.ts +++ b/tests/mod.ts @@ -4,7 +4,6 @@ import { assertEquals, assertExists } from "./deps.ts"; import { deleteMessageWithReasonTest, deleteMessageWithoutReasonTest } from "./helpers/messages/deleteMessage.ts"; import { getMessagesTest } from "./helpers/messages/getMessages.ts"; import { deleteMessagesWithoutReasonTest, deleteMessagesWithReasonTest } from "./helpers/messages/deleteMessages.ts"; -import { editMessageTest } from "./helpers/messages/editMessage.ts"; import { delayUntil } from "./utils.ts"; import { sendMessageWithComponents, @@ -93,142 +92,105 @@ Deno.test("[Bot] - Starting Tests", async (t) => { t.step({ name: "[message] send message with text", fn: async (t) => { - console.log("start", 1); await sendMessageWithTextTest(bot, channel.id, t); - console.log("pass", 1); }, ...sanitizeMode, }), t.step({ name: "[message] send message with embeds", fn: async (t) => { - console.log("start", 2); await sendMessageWithEmbedsTest(bot, channel.id, t); - console.log("pass", 2); }, ...sanitizeMode, }), // t.step({ // name: "[message] send message with components", // fn: async (t) => { - // console.log('start', 2.5) // await sendMessageWithComponents(bot, channel.id, t); - // console.log('pass', 2.5) // }, // ...sanitizeMode, // }), t.step({ name: "[message] delete message without a reason", fn: async (t) => { - console.log("start", 3); await deleteMessageWithoutReasonTest(bot, channel.id, t); - console.log("pass", 3); }, ...sanitizeMode, }), t.step({ name: "[message] delete message with a reason", fn: async (t) => { - console.log("start", 4); await deleteMessageWithReasonTest(bot, channel.id, t); - console.log("pass", 4); }, ...sanitizeMode, }), t.step({ name: "[message] delete messages without a reason", fn: async (t) => { - console.log("start", 5); await deleteMessagesWithoutReasonTest(bot, channel.id, t); - console.log("pass", 5); }, ...sanitizeMode, }), t.step({ name: "[message] delete messages with a reason", fn: async (t) => { - console.log("start", 6); await deleteMessagesWithReasonTest(bot, channel.id, t); - console.log("pass", 6); }, ...sanitizeMode, }), t.step({ name: "[message] fetch a message", fn: async (t) => { - console.log("start", 6.1); await getMessageTest(bot, channel.id, t); - console.log("pass", 6.1); }, ...sanitizeMode, }), t.step({ name: "[message] fetch messages", fn: async (t) => { - console.log("start", 6.2); await getMessagesTest(bot, channel.id, t); - console.log("pass", 6.2); }, ...sanitizeMode, }), t.step({ name: "[message] add a reaction", fn: async (t) => { - console.log("start", 7); await addReactionTest(bot, guild.id, channel.id, { custom: false, single: true, ordered: false }, t); - console.log("pass", 7); }, ...sanitizeMode, }), t.step({ name: "[message] add a custom reaction", fn: async (t) => { - console.log("start", 8); await addReactionTest(bot, guild.id, channel.id, { custom: true, single: true, ordered: false }, t); - console.log("pass", 8); }, ...sanitizeMode, }), t.step({ name: "[message] add multiple reactions", fn: async (t) => { - console.log("start", 9); await addReactionTest(bot, guild.id, channel.id, { custom: false, single: false, ordered: false }, t); - console.log("pass", 9); }, ...sanitizeMode, }), t.step({ name: "[message] add multiple custom reactions", fn: async (t) => { - console.log("start", 10); await addReactionTest(bot, guild.id, channel.id, { custom: true, single: false, ordered: false }, t); - console.log("pass", 10); }, ...sanitizeMode, }), t.step({ name: "[message] add multiple reactions in order", fn: async (t) => { - console.log("start", 11); await addReactionTest(bot, guild.id, channel.id, { custom: false, single: false, ordered: true }, t); - console.log("pass", 11); }, ...sanitizeMode, }), t.step({ name: "[message] add multiple custom reactions in order", fn: async (t) => { - console.log("start", 12); await addReactionTest(bot, guild.id, channel.id, { custom: true, single: false, ordered: true }, t); - console.log("pass", 12); - }, - ...sanitizeMode, - }), - t.step({ - name: "[message] edit message", - fn: async (t) => { - await editMessageTest(bot, channel.id, t); }, ...sanitizeMode, }),