fix tests and cache bugs

This commit is contained in:
Skillz4Killz
2021-10-29 15:46:36 +00:00
committed by GitHub
parent dfe37ef4ea
commit 6f6099abc6
16 changed files with 127 additions and 39 deletions

View File

@@ -253,11 +253,11 @@ export async function startBot(bot: Bot) {
// SETUP
bot.utils = createUtils({});
bot.transformers = createTransformers(bot.transformers || {});
bot.helpers = createHelpers(bot.helpers || {});
bot.helpers = createHelpers(bot);
// START REST
bot.rest = createRestManager({ token: bot.token, debug: bot.events.debug });
if (!bot.botGatewayData) bot.botGatewayData = await bot.helpers.getGatewayBot(bot);
if (!bot.botGatewayData) bot.botGatewayData = await bot.helpers.getGatewayBot();
// START WS
bot.gateway = createGatewayManager({
@@ -629,7 +629,24 @@ export interface Helpers {
suppressEmbeds: typeof helpers.suppressEmbeds;
}
export function createHelpers(options: Partial<Helpers>) {
export function createHelpers(
bot: Bot,
customHelpers?: Partial<Helpers>,
): FinalHelpers {
const converted = {} as FinalHelpers;
for (const [name, fun] of Object.entries({ ...createBaseHelpers(customHelpers || {}) })) {
// @ts-ignore - TODO: make the types better
converted[name as keyof FinalHelpers] = (
...args: RemoveFirstFromTuple<Parameters<typeof fun>>
) =>
// @ts-ignore - TODO: make the types better
fun(bot, ...args);
}
return converted;
}
export function createBaseHelpers(options: Partial<Helpers>) {
return {
addDiscoverySubcategory: options.addDiscoverySubcategory || helpers.addDiscoverySubcategory,
addReaction: options.addReaction || helpers.addReaction,
@@ -1236,3 +1253,12 @@ export function createBotGatewayHandlers(
INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete,
};
}
export type RemoveFirstFromTuple<T extends any[]> = T["length"] extends 0 ? []
: ((...b: T) => void) extends (a: any, ...b: infer I) => void ? I
: [];
export type FinalHelpers = {
[K in keyof Helpers]: (
...args: RemoveFirstFromTuple<Parameters<Helpers[K]>>
) => ReturnType<Helpers[K]>;
};

View File

@@ -1,14 +1,9 @@
import { Bot } from "./bot.ts";
import type { DiscordenoChannel } from "./transformers/channel.ts";
import type { DiscordenoGuild } from "./transformers/guild.ts";
import type { DiscordenoMember, DiscordenoUser } from "./transformers/member.ts";
import type { DiscordenoMessage } from "./transformers/message.ts";
import { DiscordenoPresence } from "./transformers/presence.ts";
import { PresenceUpdate } from "./types/activity/presence_update.ts";
import { Channel } from "./types/channels/channel.ts";
import { GuildMember } from "./types/members/guild_member.ts";
import { Message } from "./types/messages/message.ts";
import { SnakeCasedPropertiesDeep } from "./types/util.ts";
import { Collection } from "./util/collection.ts";
export function createCache(
@@ -33,7 +28,7 @@ export function createCache(
throw new Error("Async cache requires a tableCreator to be passed.");
}
return {
const cache = {
guilds: tableCreator("guilds"),
users: tableCreator("users"),
members: tableCreator("members"),
@@ -44,10 +39,14 @@ export function createCache(
unavailableGuilds: tableCreator("unavailableGuilds"),
executedSlashCommands: new Set(),
} as AsyncCache;
cache.execute = createExecute(cache);
return cache;
}
if (!tableCreator) tableCreator = createTable;
return {
const cache = {
guilds: tableCreator("guilds"),
users: tableCreator("users"),
members: tableCreator("members"),
@@ -58,6 +57,10 @@ export function createCache(
unavailableGuilds: tableCreator("unavailableGuilds"),
executedSlashCommands: new Set(),
} as Cache;
cache.execute = createExecute(cache);
return cache;
}
export type CachedDiscordenoUser = DiscordenoUser & { guilds: Map<bigint, GuildMember> };
@@ -180,7 +183,15 @@ export function createExecute(cache: Cache | AsyncCache): CacheExecutor {
};
}
export type TableNames = "channels" | "users" | "guilds" | "messages" | "presences" | "threads" | "unavailableGuilds" | "members";
export type TableNames =
| "channels"
| "users"
| "guilds"
| "messages"
| "presences"
| "threads"
| "unavailableGuilds"
| "members";
// function messageSweeper(bot: Bot, message: DiscordenoMessage) {
// // DM messages aren't needed

View File

@@ -25,5 +25,5 @@ export async function cloneChannel(bot: Bot, channelId: bigint, reason?: string)
};
//Create the channel (also handles permissions)
return await bot.helpers.createChannel(bot, channelToClone.guildId!, createChannelOptions, reason);
return await bot.helpers.createChannel(channelToClone.guildId!, createChannelOptions, reason);
}

View File

@@ -98,14 +98,14 @@ function processEditChannelQueue(bot: Bot) {
if (!details) return;
await bot.helpers
.editChannel(bot, details.channelId, details.options)
.editChannel(details.channelId, details.options)
.then((result) => details.resolve(result))
.catch(details.reject);
const secondDetails = request.items.shift();
if (!secondDetails) return;
await bot.helpers
.editChannel(bot, secondDetails.channelId, secondDetails.options)
.editChannel(secondDetails.channelId, secondDetails.options)
.then((result) => secondDetails.resolve(result))
.catch(secondDetails.reject);
return;

View File

@@ -2,5 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Sets a thread channel to be archived. */
export async function archiveThread(bot: Bot, threadId: bigint) {
return await bot.helpers.editThread(bot, threadId, { archived: true });
return await bot.helpers.editThread(threadId, { archived: true });
}

View File

@@ -2,5 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Sets a thread channel to be unarchived. */
export async function unarchiveThread(bot: Bot, threadId: bigint) {
return await bot.helpers.editThread(bot, threadId, { archived: false });
return await bot.helpers.editThread(threadId, { archived: false });
}

View File

@@ -2,5 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Sets a thread channel to be unlocked. */
export async function unlockThread(bot: Bot, threadId: bigint) {
return await bot.helpers.editThread(bot, threadId, { locked: false });
return await bot.helpers.editThread(threadId, { locked: false });
}

View File

@@ -22,7 +22,7 @@ export async function createGuild(bot: Bot, options: CreateGuild) {
// MANUALLY CACHE THE GUILD
await bot.cache.guilds.set(guild.id, guild);
// MANUALLY CACHE THE BOT
await bot.helpers.getMember(bot, guild.id, bot.id);
await bot.helpers.getMember(guild.id, bot.id);
return guild;
}

View File

@@ -2,5 +2,5 @@ import type { Bot } from "../../bot.ts";
/** Kicks a member from a voice channel */
export function disconnectMember(bot: Bot, guildId: bigint, memberId: bigint) {
return bot.helpers.editMember(bot, guildId, memberId, { channelId: null });
return bot.helpers.editMember(guildId, memberId, { channelId: null });
}

View File

@@ -8,5 +8,5 @@ import type { Bot } from "../../bot.ts";
* @param channelId id of channel to move user to (if they are connected to voice)
*/
export function moveMember(bot: Bot, guildId: bigint, memberId: bigint, channelId: bigint) {
return bot.helpers.editMember(bot, guildId, memberId, { channelId });
return bot.helpers.editMember(guildId, memberId, { channelId });
}

View File

@@ -25,5 +25,5 @@ export async function sendDirectMessage(bot: Bot, memberId: bigint, content: str
}
// If it does exist try sending a message to this user
return await bot.helpers.sendMessage(bot, dmChannel.id, content);
return await bot.helpers.sendMessage(dmChannel.id, content);
}

View File

@@ -9,11 +9,11 @@ export async function addReactions(
ordered = false
) {
if (!ordered) {
await Promise.all(reactions.map((reaction) => bot.helpers.addReaction(bot, channelId, messageId, reaction)));
await Promise.all(reactions.map((reaction) => bot.helpers.addReaction(channelId, messageId, reaction)));
} else {
for (const reaction of reactions) {
bot.events.debug("Running for of loop in addReactions function.");
await bot.helpers.addReaction(bot, channelId, messageId, reaction);
await bot.helpers.addReaction(channelId, messageId, reaction);
}
}
}

View File

@@ -1,4 +1,3 @@
// import { cacheHandlers } from "../../cache.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { Errors } from "../../types/discordeno/errors.ts";
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
@@ -6,8 +5,6 @@ import type { CreateMessage } from "../../types/messages/create_message.ts";
import type { Message } from "../../types/messages/message.ts";
import type { PermissionStrings } from "../../types/permissions/permission_strings.ts";
import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
import { Embed } from "../../types/embeds/embed.ts";
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) {

View File

@@ -49,7 +49,7 @@ export async function dispatchRequirements(bot: Bot, data: DiscordGatewayPayload
bot.events.debug(`[DISPATCH] New Guild ID has appeared: ${id} in ${data.t} event`);
const rawGuild = (await bot.helpers
.getGuild(bot, id, {
.getGuild(id, {
counts: true,
addToCache: false,
})
@@ -63,8 +63,8 @@ export async function dispatchRequirements(bot: Bot, data: DiscordGatewayPayload
bot.events.debug(`[DISPATCH] Guild ID ${id} has been found. ${rawGuild.name}`);
const [channels, botMember] = await Promise.all([
bot.helpers.getChannels(bot, id, false),
bot.helpers.getMember(bot, id, bot.id, { force: true }),
bot.helpers.getChannels(id, false),
bot.helpers.getMember(id, bot.id, { force: true }),
]).catch((error) => {
bot.events.debug(error);
return [];

View File

@@ -0,0 +1,42 @@
import { Bot } from "../../src/bot.ts";
import { assertExists } from "../deps.ts";
import { delayUntil } from "../utils.ts";
async function ifItFailsBlameWolf(bot: Bot, channelId: bigint, reason?: string) {
const message = await bot.helpers.sendMessage(channelId, "Hello World!");
// Assertions
assertExists(message);
// Delay the execution by 5 seconds to allow MESSAGE_CREATE event to be processed
await delayUntil(10000, () => bot.cache.messages.has(message.id));
// Make sure the message was created.
if (!bot.cache.messages.has(message.id)) {
throw new Error("The message seemed to be sent but it was not cached. Reason: ${reason}");
}
// Delete the message now
await bot.helpers.deleteMessage(channelId, message.id, reason);
// Wait 5 seconds to give it time for MESSAGE_DELETE event
await delayUntil(10000, () => !bot.cache.messages.has(message.id));
// Make sure it is gone from cache
if (bot.cache.messages.has(message.id)) {
throw new Error("The message should have been deleted but it is still in cache.");
}
}
export async function deleteMessageWithoutReasonTest(bot: Bot, channelId: bigint, t: Deno.TestContext) {
console.log("⏳ [message] delete a message without a reason.");
await ifItFailsBlameWolf(bot, channelId);
console.log("✅ [message] delete a message without a reason.");
}
export async function deleteMessageWithReasonTest(bot: Bot, channelId: bigint, t: Deno.TestContext) {
console.log("⏳ [message] delete a message with a reason.");
await ifItFailsBlameWolf(bot, channelId, "with a reason");
console.log("✅ [message] delete a message with a reason.");
}

View File

@@ -1,27 +1,33 @@
// import { TOKEN } from "../configs.ts";
import { TOKEN } from "../configs.ts";
import { createBot, createEventHandlers, DiscordChannelTypes, startBot, stopBot } from "../mod.ts";
import { assertEquals, assertExists } from "./deps.ts";
import { deleteMessageWithReasonTest } from "./messages/deleteMessage.ts";
import { deleteMessageWithoutReasonTest } from "./messages/deleteMessage.ts";
import { delayUntil } from "./utils.ts";
Deno.test("[Bot] - Starting Tests", async (t) => {
let startedAt = 0;
const bot = createBot({
// token: TOKEN || Deno.env.get("DISCORD_TOKEN"),
token: Deno.env.get("DISCORD_TOKEN")!,
token: TOKEN || Deno.env.get("DISCORD_TOKEN"),
// token: Deno.env.get("DISCORD_TOKEN")!,
// TEST BOT
botId: 770381961553510451n,
// DD bot
// botId: 675412054529540107n,
events: createEventHandlers({
ready: () => {
startedAt = Date.now();
},
debug: console.log,
// debug: console.log,
}),
intents: [],
intents: ["Guilds", "GuildMessages"],
cache: {
isAsync: false,
},
});
await startBot(bot);
// Delay the execution to allow READY events to be processed
await delayUntil(10000, () => Boolean(startedAt));
console.log("Bot online");
@@ -29,15 +35,15 @@ Deno.test("[Bot] - Starting Tests", async (t) => {
// DELETE GUILDS IF LESS THAN 10 SERVERS AS SAFETY MEASURE
if (bot.cache.guilds.size() <= 10) {
bot.cache.guilds.forEach(async (guild) => {
if (guild.ownerId === bot.id) await bot.helpers.deleteGuild(bot, guild.id);
})
if (guild.ownerId === bot.id) await bot.helpers.deleteGuild(guild.id);
});
}
// Delay the execution to allow delete guilds to be processed
await delayUntil(10000, () => Boolean(startedAt));
// CREATE ONE GUILD SO WE CAN REUSE LATER TO SAVE RATE LIMITS
const guild = await bot.helpers.createGuild(bot, { name: "Discordeno Test" });
const guild = await bot.helpers.createGuild({ name: "Discordeno Test" });
// Assertions
assertExists(guild);
@@ -53,7 +59,7 @@ Deno.test("[Bot] - Starting Tests", async (t) => {
// CHANNEL TESTS GROUPED
await t.step("Channel related tests", async (t) => {
const channel = await bot.helpers.createChannel(bot, guild.id, { name: "Discordeno-test" });
const channel = await bot.helpers.createChannel(guild.id, { name: "Discordeno-test" });
// Assertions
assertExists(channel);
@@ -61,7 +67,7 @@ Deno.test("[Bot] - Starting Tests", async (t) => {
// ALL MESSAGE RELATED TESTS THAT DEPEND ON AN EXISTING CHANNEL
await t.step("Message related tests", async (t) => {
const message = await bot.helpers.sendMessage(bot, channel.id, "Testing");
const message = await bot.helpers.sendMessage(channel.id, "Testing");
// Assertions
assertExists(message);
@@ -72,6 +78,12 @@ Deno.test("[Bot] - Starting Tests", async (t) => {
if (!bot.cache.messages.has(message.id)) {
throw new Error("The message seemed to be sent but it was not cached.");
}
// CONDUCT ALL TESTS RELATED TO A MESSAGE HERE
await Promise.all([
deleteMessageWithoutReasonTest(bot, channel.id, t),
deleteMessageWithReasonTest(bot, channel.id, t),
]);
});
});