more stuff

This commit is contained in:
Skillz4Killz
2021-04-08 19:26:38 +00:00
committed by GitHub
parent 3eaf1a5dcc
commit ad87124bca
13 changed files with 371 additions and 372 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
export { serve } from "https://deno.land/std@0.90.0/http/server.ts"; export { serve } from "https://deno.land/std@0.90.0/http/server.ts";
export { verify } from "https://esm.sh/@evan/wasm@0.0.50/target/ed25519/deno.js"; export { verify } from "https://unpkg.com/@evan/wasm@0.0.50/target/ed25519/deno.js";
+16 -16
View File
@@ -8,6 +8,7 @@ export async function processQueue(id: string) {
if (!queue) return; if (!queue) return;
while (queue.length) { while (queue.length) {
console.log("process queue");
// IF THE BOT IS GLOBALLY RATELIMITED TRY AGAIN // IF THE BOT IS GLOBALLY RATELIMITED TRY AGAIN
if (rest.globallyRateLimited) { if (rest.globallyRateLimited) {
setTimeout(() => processQueue(id), 1000); setTimeout(() => processQueue(id), 1000);
@@ -36,19 +37,18 @@ export async function processQueue(id: string) {
// EXECUTE THE REQUEST // EXECUTE THE REQUEST
// IF THIS IS A GET REQUEST, CHANGE THE BODY TO QUERY PARAMETERS // IF THIS IS A GET REQUEST, CHANGE THE BODY TO QUERY PARAMETERS
const query = queuedRequest.request.method.toUpperCase() === "GET" && const query =
queuedRequest.payload.body queuedRequest.request.method.toUpperCase() === "GET" &&
? Object.entries(queuedRequest.payload.body) queuedRequest.payload.body
.map( ? Object.entries(queuedRequest.payload.body)
([key, value]) => .map(
`${encodeURIComponent(key)}=${ ([key, value]) =>
encodeURIComponent( `${encodeURIComponent(key)}=${encodeURIComponent(
value as string, value as string
) )}`
}`, )
) .join("&")
.join("&") : "";
: "";
const urlToUse = const urlToUse =
queuedRequest.request.method.toUpperCase() === "GET" && query queuedRequest.request.method.toUpperCase() === "GET" && query
? `${queuedRequest.request.url}?${query}` ? `${queuedRequest.request.url}?${query}`
@@ -60,13 +60,13 @@ export async function processQueue(id: string) {
try { try {
const response = await fetch( const response = await fetch(
urlToUse, urlToUse,
rest.createRequestBody(queuedRequest), rest.createRequestBody(queuedRequest)
); );
rest.eventHandlers.fetched(queuedRequest.payload); rest.eventHandlers.fetched(queuedRequest.payload);
const bucketIdFromHeaders = rest.processRequestHeaders( const bucketIdFromHeaders = rest.processRequestHeaders(
queuedRequest.request.url, queuedRequest.request.url,
response.headers, response.headers
); );
if (response.status < 200 || response.status >= 400) { if (response.status < 200 || response.status >= 400) {
@@ -124,7 +124,7 @@ export async function processQueue(id: string) {
// IF IT HAS MAXED RETRIES SOMETHING SERIOUSLY WRONG. CANCEL OUT. // IF IT HAS MAXED RETRIES SOMETHING SERIOUSLY WRONG. CANCEL OUT.
if ( if (
queuedRequest.payload.retryCount >= queuedRequest.payload.retryCount >=
queuedRequest.options.maxRetryCount queuedRequest.options.maxRetryCount
) { ) {
rest.eventHandlers.retriesMaxed(queuedRequest.payload); rest.eventHandlers.retriesMaxed(queuedRequest.payload);
queuedRequest.request.respond({ queuedRequest.request.respond({
+1 -1
View File
@@ -1,6 +1,6 @@
import { SnakeCasedPropertiesDeep } from "../util.ts"; import { SnakeCasedPropertiesDeep } from "../util.ts";
import { DiscordVisibilityTypes } from "./visibility_types.ts"; import { DiscordVisibilityTypes } from "./visibility_types.ts";
import { Integration } from "../guilds/integration.ts"; import { Integration } from "../integration/integration.ts";
export interface Connection { export interface Connection {
/** id of the connection account */ /** id of the connection account */
+2 -2
View File
@@ -59,11 +59,11 @@ export const formatImageURL = (
}; };
function camelToSnakeCase(text: string) { function camelToSnakeCase(text: string) {
return text.replace(/Id|[A-Z]/g, ($1) => `_${$1.toLowerCase()}`); return text.replace(/[A-Z]/g, ($1) => `_${$1.toLowerCase()}`);
} }
function snakeToCamelCase(text: string) { function snakeToCamelCase(text: string) {
return text.replace(/_id|([-_][a-z])/gi, ($1) => return text.replace(/([-_][a-z])/gi, ($1) =>
$1.toUpperCase().replace("_", "") $1.toUpperCase().replace("_", "")
); );
} }
+3 -1
View File
@@ -4,13 +4,15 @@ import { ws } from "./ws.ts";
/** The handler to clean up shards that identified but never received a READY. */ /** The handler to clean up shards that identified but never received a READY. */
export async function cleanupLoadingShards() { export async function cleanupLoadingShards() {
while (ws.loadingShards.size) { while (ws.loadingShards.size) {
console.log("cls");
const now = Date.now(); const now = Date.now();
ws.loadingShards.forEach((loadingShard) => { ws.loadingShards.forEach((loadingShard) => {
console.log(loadingShard);
// Not a minute yet. Max should be few seconds but do a minute to be safe. // Not a minute yet. Max should be few seconds but do a minute to be safe.
if (now < loadingShard.startedAt + 60000) return; if (now < loadingShard.startedAt + 60000) return;
loadingShard.reject( loadingShard.reject(
`[Identify Failure] Shard ${loadingShard.shardId} has not received READY event in over a minute.`, `[Identify Failure] Shard ${loadingShard.shardId} has not received READY event in over a minute.`
); );
}); });
+4 -2
View File
@@ -16,6 +16,9 @@ export async function createShard(shardId: number) {
socket.onclose = (event) => { socket.onclose = (event) => {
ws.log("CLOSED", { shardId, payload: event }); ws.log("CLOSED", { shardId, payload: event });
if (event.code === 4009 && ["Resharded!", "Resuming the shard, closing old shard."].includes(event.reason)) {
return ws.log("CLOSED_RECONNECT", { shardId, payload: event });
}
// TODO: ENUM FOR THESE CODES? // TODO: ENUM FOR THESE CODES?
switch (event.code) { switch (event.code) {
@@ -29,14 +32,13 @@ export async function createShard(shardId: number) {
case 4013: case 4013:
case 4014: case 4014:
throw new Error( throw new Error(
event.reason || "Discord gave no reason! GG! You broke Discord!", event.reason || "Discord gave no reason! GG! You broke Discord!"
); );
// THESE ERRORS CAN NO BE RESUMED! THEY MUST RE-IDENTIFY! // THESE ERRORS CAN NO BE RESUMED! THEY MUST RE-IDENTIFY!
case 4003: case 4003:
case 4007: case 4007:
case 4008: case 4008:
case 4009: case 4009:
ws.log("CLOSED_RECONNECT", { shardId, payload: event });
identify(shardId, ws.maxShards); identify(shardId, ws.maxShards);
break; break;
default: default:
+15 -5
View File
@@ -15,10 +15,8 @@ export async function handleOnMessage(message: any, shardId: number) {
} }
if (message instanceof Uint8Array) { if (message instanceof Uint8Array) {
message = decompressWith( message = decompressWith(message, 0, (slice: Uint8Array) =>
message, ws.utf8decoder.decode(slice)
0,
(slice: Uint8Array) => ws.utf8decoder.decode(slice),
); );
} }
@@ -31,7 +29,7 @@ export async function handleOnMessage(message: any, shardId: number) {
case DiscordGatewayOpcodes.Hello: case DiscordGatewayOpcodes.Hello:
ws.heartbeat( ws.heartbeat(
shardId, shardId,
(messageData.d as DiscordHeartbeat).heartbeat_interval, (messageData.d as DiscordHeartbeat).heartbeat_interval
); );
break; break;
case DiscordGatewayOpcodes.HeartbeatACK: case DiscordGatewayOpcodes.HeartbeatACK:
@@ -80,8 +78,20 @@ export async function handleOnMessage(message: any, shardId: number) {
shard.sessionId = (messageData.d as DiscordReady).session_id; shard.sessionId = (messageData.d as DiscordReady).session_id;
} }
console.log(
"shoulda deleted it",
shardId,
ws.loadingShards.has(shardId),
ws.loadingShards
);
ws.loadingShards.get(shardId)?.resolve(true); ws.loadingShards.get(shardId)?.resolve(true);
ws.loadingShards.delete(shardId); ws.loadingShards.delete(shardId);
console.log(
"shoulda deleted it",
shardId,
ws.loadingShards.has(shardId),
ws.loadingShards
);
} }
// Update the sequence number if it is present // Update the sequence number if it is present
+2 -1
View File
@@ -32,11 +32,12 @@ export async function identify(shardId: number, maxShards: number) {
JSON.stringify({ JSON.stringify({
op: DiscordGatewayOpcodes.Identify, op: DiscordGatewayOpcodes.Identify,
d: { ...ws.identifyPayload, shard: [shardId, maxShards] }, d: { ...ws.identifyPayload, shard: [shardId, maxShards] },
}), })
); );
}; };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log("setting the shard loader");
ws.loadingShards.set(shardId, { ws.loadingShards.set(shardId, {
shardId, shardId,
resolve, resolve,
+1
View File
@@ -44,6 +44,7 @@ export function spawnShards(firstShardId = 0) {
let shardId = queue.shift(); let shardId = queue.shift();
while (shardId !== undefined) { while (shardId !== undefined) {
console.log("spawn shards");
await ws.tellClusterToIdentify(clusterId as number, shardId, bucketId); await ws.tellClusterToIdentify(clusterId as number, shardId, bucketId);
shardId = queue.shift(); shardId = queue.shift();
} }
+2 -2
View File
@@ -18,8 +18,8 @@ export async function startGateway(options: StartGatewayOptions) {
ws.identifyPayload.compress = options.compress; ws.identifyPayload.compress = options.compress;
} }
if (options.reshard) ws.reshard = options.reshard; if (options.reshard) ws.reshard = options.reshard;
// Once an hour check if resharding is necessary // TODO: Once an hour check if resharding is necessary
setInterval(ws.resharder, 1000 * 60 * 60); // setInterval(ws.resharder, 1000 * 60 * 60);
ws.identifyPayload.intents = options.intents.reduce( ws.identifyPayload.intents = options.intents.reduce(
( (
-341
View File
@@ -1,341 +0,0 @@
import {
addReaction,
botId,
cache,
Channel,
channelOverwriteHasPermission,
createChannel,
createGuild,
createRole,
delay,
deleteChannel,
deleteMessage,
deleteRole,
deleteServer,
editChannel,
editRole,
getChannel,
getMessage,
getPins,
Guild,
OverwriteType,
pinMessage,
removeReaction,
Role,
sendMessage,
startBot,
unpinMessage,
} from "../mod.ts";
import { assertEquals, assertExists } from "./deps.ts";
// Default options for tests
export const defaultTestOptions: Partial<Deno.TestDefinition> = {
sanitizeOps: false,
sanitizeResources: false,
sanitizeExit: false,
};
// Temporary data
export const tempData = {
guildId: "",
roleId: "",
channelId: "",
messageId: "",
};
// Main
Deno.test({
name: "[main] connect to gateway",
async fn() {
const token = Deno.env.get("DISCORD_TOKEN");
if (!token) throw new Error("Token is not provided");
await startBot({
token,
intents: ["GUILD_MESSAGES", "GUILDS"],
});
// Delay the execution by 5 seconds
await delay(5000);
// Assertions
assertExists(botId);
},
...defaultTestOptions,
});
// Guild
Deno.test({
name: "[guild] create a new guild",
async fn() {
const guild = await createGuild({
name: "Discordeno Test",
}) as Guild;
// Assertions
assertExists(guild);
tempData.guildId = guild.id;
// Delay the execution by 5 seconds to allow GUILD_CREATE event to be processed
await delay(5000);
},
...defaultTestOptions,
});
// Role
Deno.test({
name: "[role] create a role in a guild",
async fn() {
if (!tempData.guildId) {
throw new Error("guildId not present in temporary data");
}
const name = "Discordeno Test";
const role = await createRole(tempData.guildId, {
name,
});
// Assertions
assertExists(role);
assertEquals(role.name, name);
tempData.roleId = role.id;
},
...defaultTestOptions,
});
Deno.test({
name: "[role] edit a role in a guild",
async fn() {
const name = "Discordeno Test Edited";
const color = 4320244;
const role = await editRole(tempData.guildId, tempData.roleId, {
name,
color,
hoist: false,
mentionable: false,
}) as Role;
// Assertions
assertExists(role);
assertEquals(role.name, name);
assertEquals(role.color, color);
assertEquals(role.hoist, false);
assertEquals(role.mentionable, false);
tempData.roleId = role.id;
},
...defaultTestOptions,
});
// Channel
Deno.test({
name: "[channel] create a channel in a guild",
async fn() {
const channel = await createChannel(tempData.guildId, "test");
// Assertions
assertExists(channel);
tempData.channelId = channel.id;
},
...defaultTestOptions,
});
Deno.test({
name: "[channel] get a channel in a guild",
async fn() {
const channel = await getChannel(tempData.channelId);
// Assertions
assertExists(channel);
assertEquals(channel.id, tempData.channelId);
},
...defaultTestOptions,
});
Deno.test({
name: "[channel] edit a channel in a guild",
async fn() {
const channel = await editChannel(tempData.channelId, {
name: "discordeno-test-edited",
overwrites: [
{
id: tempData.roleId,
type: OverwriteType.ROLE,
allow: ["VIEW_CHANNEL", "SEND_MESSAGES"],
deny: ["USE_EXTERNAL_EMOJIS"],
},
],
}) as Channel;
// Wait 5s for CHANNEL_UPDATE to fire
await delay(5000);
// Assertions
assertExists(channel);
assertEquals(channel.name, "discordeno-test-edited");
},
...defaultTestOptions,
});
Deno.test({
name: "[channel] channel overwrite has permission",
fn() {
const channel = cache.channels.get(tempData.channelId);
if (!channel) throw new Error("Channel not found");
if (!channel.permissionOverwrites) {
throw new Error("permissionOverwrites not found");
}
const hasPerm = channelOverwriteHasPermission(
tempData.guildId,
tempData.roleId,
channel.permissionOverwrites,
["VIEW_CHANNEL", "SEND_MESSAGES"],
);
const missingPerm = channelOverwriteHasPermission(
tempData.guildId,
tempData.roleId,
channel.permissionOverwrites,
["USE_EXTERNAL_EMOJIS"],
);
assertEquals(hasPerm, true);
assertEquals(missingPerm, false);
},
...defaultTestOptions,
});
// Message
Deno.test({
name: "[message] send a message in a text channel",
async fn() {
const message = await sendMessage(tempData.channelId, {
embed: {
title: "Discordeno Test",
},
});
// Assertions
assertExists(message);
assertEquals(message.embeds[0].title, "Discordeno Test");
tempData.messageId = message.id;
},
...defaultTestOptions,
});
Deno.test({
name: "[message] get a message in a guild",
async fn() {
const message = await getMessage(tempData.channelId, tempData.messageId);
// Assertions
assertExists(message);
assertEquals(message.embeds[0].title, "Discordeno Test");
},
...defaultTestOptions,
});
Deno.test({
name: "[message] pin a message in a channel",
async fn() {
await pinMessage(tempData.channelId, tempData.messageId);
},
...defaultTestOptions,
});
Deno.test({
name: "[message] get pinned message in a channel",
async fn() {
const [msg] = await getPins(tempData.channelId);
// Assertions
assertExists(msg);
assertEquals(msg.id, tempData.messageId);
assertEquals(msg.pinned, true);
},
...defaultTestOptions,
});
Deno.test({
name: "[message] unpin a message",
async fn() {
await unpinMessage(tempData.channelId, tempData.messageId);
},
...defaultTestOptions,
});
Deno.test({
name: "[message] add a reaction to a message",
async fn() {
// TODO: add tests for a guild emoji ― <:name:id>
await addReaction(tempData.channelId, tempData.messageId, "👍");
},
...defaultTestOptions,
});
// TODO(ayntee): add unit tests for getReactions()
Deno.test({
name: "[message] remove a reaction to a message",
async fn() {
await removeReaction(tempData.channelId, tempData.messageId, "👍");
},
...defaultTestOptions,
});
// Cleanup
Deno.test({
name: "[message] delete a message by channel Id",
async fn() {
await deleteMessage(tempData.channelId, tempData.messageId);
},
...defaultTestOptions,
});
Deno.test({
name: "[channel] delete a channel in a guild",
async fn() {
await deleteChannel(tempData.guildId, tempData.channelId);
},
...defaultTestOptions,
});
Deno.test({
name: "[role] delete a role in a guild",
async fn() {
await deleteRole(tempData.guildId, tempData.roleId);
},
...defaultTestOptions,
});
Deno.test({
name: "[guild] delete a guild",
async fn() {
await deleteServer(tempData.guildId);
// TODO(ayntee): remove this weird shit lol
// TODO(ayntee): check if the GUILD_DELETE event is fired
tempData.guildId = "";
assertEquals(tempData.guildId, "");
},
...defaultTestOptions,
});
// Forcefully exit the Deno process once all tests are done.
Deno.test({
name: "[main] exit the process forcefully",
fn() {
Deno.exit();
},
...defaultTestOptions,
});
+324
View File
@@ -0,0 +1,324 @@
import { botId, delay, startBot, ws } from "../mod.ts";
import { assertExists } from "./deps.ts";
// Set necessary settings
// Disables the logger which logs everything
ws.log = function (x: string, d: any) {
if (["RAW", "GUILD_CREATE", "HEARTBEATING_DETAILS"].includes(x)) return console.log(x);
console.log(x, d);
};
// Default options for tests
export const defaultTestOptions: Partial<Deno.TestDefinition> = {
sanitizeOps: false,
sanitizeResources: false,
sanitizeExit: false,
};
// Temporary data
export const tempData = {
guildId: "",
roleId: "",
channelId: "",
messageId: "",
};
// Main
Deno.test({
name: "[main] connect to gateway",
async fn() {
const token = Deno.env.get("DISCORD_TOKEN");
if (!token) throw new Error("Token is not provided");
await startBot({
token,
intents: ["GUILD_MESSAGES", "GUILDS"],
});
// Delay the execution by 5 seconds
await delay(5000);
// Assertions
assertExists(botId);
},
...defaultTestOptions,
});
// Guild
// Deno.test({
// name: "[guild] create a new guild",
// async fn() {
// const guild = await createGuild({
// name: "Discordeno Test",
// }) as Guild;
// // Assertions
// assertExists(guild);
// tempData.guildId = guild.id;
// // Delay the execution by 5 seconds to allow GUILD_CREATE event to be processed
// await delay(5000);
// },
// ...defaultTestOptions,
// });
// // Role
// Deno.test({
// name: "[role] create a role in a guild",
// async fn() {
// if (!tempData.guildId) {
// throw new Error("guildId not present in temporary data");
// }
// const name = "Discordeno Test";
// const role = await createRole(tempData.guildId, {
// name,
// });
// // Assertions
// assertExists(role);
// assertEquals(role.name, name);
// tempData.roleId = role.id;
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[role] edit a role in a guild",
// async fn() {
// const name = "Discordeno Test Edited";
// const color = 4320244;
// const role = await editRole(tempData.guildId, tempData.roleId, {
// name,
// color,
// hoist: false,
// mentionable: false,
// }) as Role;
// // Assertions
// assertExists(role);
// assertEquals(role.name, name);
// assertEquals(role.color, color);
// assertEquals(role.hoist, false);
// assertEquals(role.mentionable, false);
// tempData.roleId = role.id;
// },
// ...defaultTestOptions,
// });
// // Channel
// Deno.test({
// name: "[channel] create a channel in a guild",
// async fn() {
// const channel = await createChannel(tempData.guildId, "test");
// // Assertions
// assertExists(channel);
// tempData.channelId = channel.id;
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[channel] get a channel in a guild",
// async fn() {
// const channel = await getChannel(tempData.channelId);
// // Assertions
// assertExists(channel);
// assertEquals(channel.id, tempData.channelId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[channel] edit a channel in a guild",
// async fn() {
// const channel = await editChannel(tempData.channelId, {
// name: "discordeno-test-edited",
// overwrites: [
// {
// id: tempData.roleId,
// type: OverwriteType.ROLE,
// allow: ["VIEW_CHANNEL", "SEND_MESSAGES"],
// deny: ["USE_EXTERNAL_EMOJIS"],
// },
// ],
// }) as Channel;
// // Wait 5s for CHANNEL_UPDATE to fire
// await delay(5000);
// // Assertions
// assertExists(channel);
// assertEquals(channel.name, "discordeno-test-edited");
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[channel] channel overwrite has permission",
// fn() {
// const channel = cache.channels.get(tempData.channelId);
// if (!channel) throw new Error("Channel not found");
// if (!channel.permissionOverwrites) {
// throw new Error("permissionOverwrites not found");
// }
// const hasPerm = channelOverwriteHasPermission(
// tempData.guildId,
// tempData.roleId,
// channel.permissionOverwrites,
// ["VIEW_CHANNEL", "SEND_MESSAGES"],
// );
// const missingPerm = channelOverwriteHasPermission(
// tempData.guildId,
// tempData.roleId,
// channel.permissionOverwrites,
// ["USE_EXTERNAL_EMOJIS"],
// );
// assertEquals(hasPerm, true);
// assertEquals(missingPerm, false);
// },
// ...defaultTestOptions,
// });
// // Message
// Deno.test({
// name: "[message] send a message in a text channel",
// async fn() {
// const message = await sendMessage(tempData.channelId, {
// embed: {
// title: "Discordeno Test",
// },
// });
// // Assertions
// assertExists(message);
// assertEquals(message.embeds[0].title, "Discordeno Test");
// tempData.messageId = message.id;
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[message] get a message in a guild",
// async fn() {
// const message = await getMessage(tempData.channelId, tempData.messageId);
// // Assertions
// assertExists(message);
// assertEquals(message.embeds[0].title, "Discordeno Test");
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[message] pin a message in a channel",
// async fn() {
// await pinMessage(tempData.channelId, tempData.messageId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[message] get pinned message in a channel",
// async fn() {
// const [msg] = await getPins(tempData.channelId);
// // Assertions
// assertExists(msg);
// assertEquals(msg.id, tempData.messageId);
// assertEquals(msg.pinned, true);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[message] unpin a message",
// async fn() {
// await unpinMessage(tempData.channelId, tempData.messageId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[message] add a reaction to a message",
// async fn() {
// // TODO: add tests for a guild emoji ― <:name:id>
// await addReaction(tempData.channelId, tempData.messageId, "👍");
// },
// ...defaultTestOptions,
// });
// // TODO(ayntee): add unit tests for getReactions()
// Deno.test({
// name: "[message] remove a reaction to a message",
// async fn() {
// await removeReaction(tempData.channelId, tempData.messageId, "👍");
// },
// ...defaultTestOptions,
// });
// // Cleanup
// Deno.test({
// name: "[message] delete a message by channel Id",
// async fn() {
// await deleteMessage(tempData.channelId, tempData.messageId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[channel] delete a channel in a guild",
// async fn() {
// await deleteChannel(tempData.guildId, tempData.channelId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[role] delete a role in a guild",
// async fn() {
// await deleteRole(tempData.guildId, tempData.roleId);
// },
// ...defaultTestOptions,
// });
// Deno.test({
// name: "[guild] delete a guild",
// async fn() {
// await deleteServer(tempData.guildId);
// // TODO(ayntee): remove this weird shit lol
// // TODO(ayntee): check if the GUILD_DELETE event is fired
// tempData.guildId = "";
// assertEquals(tempData.guildId, "");
// },
// ...defaultTestOptions,
// });
// Forcefully exit the Deno process once all tests are done.
Deno.test({
name: "[main] exit the process forcefully",
fn() {
ws.shards.forEach((shard) => {
clearInterval(shard.heartbeat.intervalId);
shard.ws.close();
});
},
...defaultTestOptions,
});