making it testable

This commit is contained in:
Skillz4Killz
2021-10-25 00:11:07 +00:00
committed by GitHub
parent 5b4b10ae45
commit 231554d091
33 changed files with 459 additions and 781 deletions
+1
View File
@@ -1,6 +1,7 @@
{ {
"deno.enable": true, "deno.enable": true,
"deno.lint": false, "deno.lint": false,
"deno.unstable": true,
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
+1 -1
View File
@@ -3,7 +3,7 @@ export * from "./src/cache.ts";
export * from "./src/handlers/mod.ts"; export * from "./src/handlers/mod.ts";
export * from "./src/helpers/mod.ts"; export * from "./src/helpers/mod.ts";
export * from "./src/rest/mod.ts"; export * from "./src/rest/mod.ts";
export * from "./src/structures/mod.ts"; export * from "./src/transformers/mod.ts";
export * from "./src/types/mod.ts"; export * from "./src/types/mod.ts";
export * from "./src/util/mod.ts"; export * from "./src/util/mod.ts";
export * from "./src/ws/mod.ts"; export * from "./src/ws/mod.ts";
+25 -26
View File
@@ -296,7 +296,7 @@ import { DiscordenoEmoji, transformEmoji } from "./transformers/emoji.ts";
import { transformActivity } from "./transformers/activity.ts"; import { transformActivity } from "./transformers/activity.ts";
import { DiscordenoPresence, transformPresence } from "./transformers/presence.ts"; import { DiscordenoPresence, transformPresence } from "./transformers/presence.ts";
export async function createBot(options: CreateBotOptions) { export function createBot(options: CreateBotOptions) {
return { return {
id: options.botId, id: options.botId,
applicationId: options.applicationId || options.botId, applicationId: options.applicationId || options.botId,
@@ -430,13 +430,6 @@ export async function createBot(options: CreateBotOptions) {
}; };
} }
const bot = await createBot({
token: "",
botId: 0n,
events: createEventHandlers({}),
intents: [],
});
export function createEventHandlers(events: Partial<EventHandlers>): EventHandlers { export function createEventHandlers(events: Partial<EventHandlers>): EventHandlers {
function ignore() {} function ignore() {}
@@ -543,14 +536,27 @@ export function createRestManager(options: CreateRestManagerOptions) {
export async function startBot(bot: Bot) { export async function startBot(bot: Bot) {
// SETUP // SETUP
bot.utils = createUtils({}); bot.utils = createUtils({});
bot.transformers = createTransformers(bot.transformers); bot.transformers = createTransformers(bot.transformers || {});
bot.helpers = createHelpers(bot.helpers); bot.helpers = createHelpers(bot.helpers || {});
// START REST // START REST
bot.rest = createRestManager({ token: bot.token }); bot.rest = createRestManager({ token: bot.token });
// START WS // START WS
bot.gateway = createGatewayManager({}); bot.gateway = createGatewayManager({
handleDiscordPayload:
// bot.handleDiscordPayload ||
async function (_, data: DiscordGatewayPayload, shardId: number) {
// TRIGGER RAW EVENT
bot.events.raw(bot as Bot, data, shardId);
if (!data.t) return;
// RUN DISPATCH CHECK
await bot.events.dispatchRequirements(bot as Bot, data, shardId);
bot.handlers[data.t as GatewayDispatchEventNames]?.(bot as Bot, data, shardId);
},
});
if (!bot.botGatewayData) bot.botGatewayData = await bot.helpers.getGatewayBot(bot); if (!bot.botGatewayData) bot.botGatewayData = await bot.helpers.getGatewayBot(bot);
} }
@@ -612,7 +618,9 @@ export interface HelperUtils {
validateComponents: typeof validateComponents; validateComponents: typeof validateComponents;
} }
export function createGatewayManager(options: Partial<GatewayManager>): GatewayManager { export function createGatewayManager(
options: Partial<GatewayManager> & Pick<GatewayManager, "handleDiscordPayload">
): GatewayManager {
return { return {
cache: { cache: {
guildIds: new Set(), guildIds: new Set(),
@@ -661,18 +669,7 @@ export function createGatewayManager(options: Partial<GatewayManager>): GatewayM
closeWS, closeWS,
sendShardMessage, sendShardMessage,
resume, resume,
handleDiscordPayload: handleDiscordPayload: options.handleDiscordPayload,
options.handleDiscordPayload ||
async function (_, data: DiscordGatewayPayload, shardId: number) {
// TRIGGER RAW EVENT
bot.events.raw(bot as Bot, data, shardId);
if (!data.t) return;
// RUN DISPATCH CHECK
await bot.events.dispatchRequirements(bot as Bot, data, shardId);
bot.handlers[data.t as GatewayDispatchEventNames]?.(bot as Bot, data, shardId);
},
}; };
} }
@@ -693,7 +690,7 @@ export interface CreateBotOptions {
export type UnPromise<T extends Promise<unknown>> = T extends Promise<infer K> ? K : never; export type UnPromise<T extends Promise<unknown>> = T extends Promise<infer K> ? K : never;
export type CreatedBot = UnPromise<ReturnType<typeof createBot>>; export type CreatedBot = ReturnType<typeof createBot>;
export type Bot = CreatedBot & { export type Bot = CreatedBot & {
utils: HelperUtils; utils: HelperUtils;
@@ -1369,7 +1366,9 @@ export interface BotGatewayHandlerOptions {
INTEGRATION_DELETE: typeof handleIntegrationDelete; INTEGRATION_DELETE: typeof handleIntegrationDelete;
} }
export function createBotGatewayHandlers(options: Partial<BotGatewayHandlerOptions>): Record<GatewayDispatchEventNames | "GUILD_LOADED_DD", (bot: Bot, data: GatewayPayload, shardId: number) => any> { export function createBotGatewayHandlers(
options: Partial<BotGatewayHandlerOptions>
): Record<GatewayDispatchEventNames | "GUILD_LOADED_DD", (bot: Bot, data: GatewayPayload, shardId: number) => any> {
return { return {
// misc // misc
READY: options.READY ?? handleReady, READY: options.READY ?? handleReady,
+8 -8
View File
@@ -1,17 +1,17 @@
import { eventHandlers } from "../../bot.ts"; // import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { Channel } from "../../types/channels/channel.ts"; import { Channel } from "../../types/channels/channel.ts";
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
export async function handleThreadDelete(data: DiscordGatewayPayload) { export async function handleThreadDelete(data: DiscordGatewayPayload) {
const payload = data.d as Channel; // const payload = data.d as Channel;
const cachedChannel = await cacheHandlers.get("threads", snowflakeToBigint(payload.id)); // const cachedChannel = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
if (!cachedChannel) return; // if (!cachedChannel) return;
await cacheHandlers.delete("threads", snowflakeToBigint(payload.id)); // await cacheHandlers.delete("threads", snowflakeToBigint(payload.id));
await cacheHandlers.forEach("DELETE_MESSAGES_FROM_CHANNEL", { channelId: snowflakeToBigint(payload.id) }); // await cacheHandlers.forEach("DELETE_MESSAGES_FROM_CHANNEL", { channelId: snowflakeToBigint(payload.id) });
eventHandlers.threadDelete?.(cachedChannel); // eventHandlers.threadDelete?.(cachedChannel);
} }
+17 -17
View File
@@ -1,27 +1,27 @@
import { eventHandlers } from "../../bot.ts"; // import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { ThreadListSync } from "../../types/channels/threads/thread_list_sync.ts"; import { ThreadListSync } from "../../types/channels/threads/thread_list_sync.ts";
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
import { channelToThread } from "../../util/transformers/channel_to_thread.ts"; // import { channelToThread } from "../../util/transformers/channel_to_thread.ts";
import { Collection } from "../../util/collection.ts"; import { Collection } from "../../util/collection.ts";
import { threadMemberModified } from "../../util/transformers/thread_member_modified.ts"; // import { threadMemberModified } from "../../util/transformers/thread_member_modified.ts";
export async function handleThreadListSync(data: DiscordGatewayPayload) { export async function handleThreadListSync(data: DiscordGatewayPayload) {
const payload = data.d as ThreadListSync; // const payload = data.d as ThreadListSync;
const threads = await Promise.all( // const threads = await Promise.all(
payload.threads.map(async (thread) => { // payload.threads.map(async (thread) => {
const threadData = channelToThread(thread); // const threadData = channelToThread(thread);
await cacheHandlers.set("threads", threadData.id, threadData); // await cacheHandlers.set("threads", threadData.id, threadData);
return threadData; // return threadData;
}) // })
); // );
eventHandlers.threadListSync?.( // eventHandlers.threadListSync?.(
new Collection(threads.map((t) => [t.id, t])), // new Collection(threads.map((t) => [t.id, t])),
payload.members.map((member) => threadMemberModified(member)), // payload.members.map((member) => threadMemberModified(member)),
snowflakeToBigint(payload.guildId) // snowflakeToBigint(payload.guildId)
); // );
} }
@@ -1,17 +1,17 @@
import { eventHandlers } from "../../bot.ts"; // import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { ThreadMembersUpdate } from "../../types/channels/threads/thread_members_update.ts"; import { ThreadMembersUpdate } from "../../types/channels/threads/thread_members_update.ts";
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
import { threadMembersUpdateModified } from "../../util/transformers/thread_members_update_modified.ts"; // import { threadMembersUpdateModified } from "../../util/transformers/thread_members_update_modified.ts";
export async function handleThreadMembersUpdate(data: DiscordGatewayPayload) { export async function handleThreadMembersUpdate(data: DiscordGatewayPayload) {
const payload = data.d as ThreadMembersUpdate; // const payload = data.d as ThreadMembersUpdate;
const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id)); // const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
if (!thread) return; // if (!thread) return;
thread.memberCount = payload.memberCount; // thread.memberCount = payload.memberCount;
await cacheHandlers.set("threads", thread.id, thread); // await cacheHandlers.set("threads", thread.id, thread);
eventHandlers.threadMembersUpdate?.(threadMembersUpdateModified(payload)); // eventHandlers.threadMembersUpdate?.(threadMembersUpdateModified(payload));
} }
+15 -15
View File
@@ -1,24 +1,24 @@
import { eventHandlers } from "../../bot.ts"; // import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { ThreadMember } from "../../types/channels/threads/thread_member.ts"; import { ThreadMember } from "../../types/channels/threads/thread_member.ts";
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
export async function handleThreadMemberUpdate(data: DiscordGatewayPayload) { export async function handleThreadMemberUpdate(data: DiscordGatewayPayload) {
const payload = data.d as ThreadMember; // const payload = data.d as ThreadMember;
// The id field is omitted from the thread member dispatched within the GUILD_CREATE gateway event. // // The id field is omitted from the thread member dispatched within the GUILD_CREATE gateway event.
const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id!)); // const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id!));
if (!thread) return; // if (!thread) return;
thread.botIsMember = true; // thread.botIsMember = true;
await cacheHandlers.set("threads", thread.id, thread); // await cacheHandlers.set("threads", thread.id, thread);
const member = { // const member = {
...payload, // ...payload,
id: snowflakeToBigint(payload.id!), // id: snowflakeToBigint(payload.id!),
userId: snowflakeToBigint(payload.userId!), // userId: snowflakeToBigint(payload.userId!),
joinTimestamp: Date.parse(payload.joinTimestamp), // joinTimestamp: Date.parse(payload.joinTimestamp),
}; // };
eventHandlers.threadMemberUpdate?.(member, thread); // eventHandlers.threadMemberUpdate?.(member, thread);
} }
+9 -9
View File
@@ -1,17 +1,17 @@
import { eventHandlers } from "../../bot.ts"; // import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { Channel } from "../../types/channels/channel.ts"; import { Channel } from "../../types/channels/channel.ts";
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
import { channelToThread } from "../../util/transformers/channel_to_thread.ts"; // import { channelToThread } from "../../util/transformers/channel_to_thread.ts";
export async function handleThreadUpdate(data: DiscordGatewayPayload) { export async function handleThreadUpdate(data: DiscordGatewayPayload) {
const payload = data.d as Channel; // const payload = data.d as Channel;
const oldThread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id)); // const oldThread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
if (!oldThread) return; // if (!oldThread) return;
const thread = channelToThread(payload); // const thread = channelToThread(payload);
await cacheHandlers.set("threads", thread.id, thread); // await cacheHandlers.set("threads", thread.id, thread);
eventHandlers.threadUpdate?.(thread, oldThread); // eventHandlers.threadUpdate?.(thread, oldThread);
} }
+10 -10
View File
@@ -1,6 +1,6 @@
import type { ModifyThread } from "../../../types/channels/threads/modify_thread.ts"; import type { ModifyThread } from "../../../types/channels/threads/modify_thread.ts";
import type { Bot } from "../../../bot.ts"; import type { Bot } from "../../../bot.ts";
import { channelToThread } from "../../../util/transformers/channel_to_thread.ts"; // import { channelToThread } from "../../../util/transformers/channel_to_thread.ts";
/** Update a thread's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */ /** Update a thread's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */
export async function editThread(bot: Bot, threadId: bigint, options: ModifyThread, reason?: string) { export async function editThread(bot: Bot, threadId: bigint, options: ModifyThread, reason?: string) {
@@ -8,14 +8,14 @@ export async function editThread(bot: Bot, threadId: bigint, options: ModifyThre
// TODO: permission checking // TODO: permission checking
const result = await bot.rest.runMethod(bot.rest, "patch", bot.constants.endpoints.CHANNEL_BASE(threadId), { // const result = await bot.rest.runMethod(bot.rest, "patch", bot.constants.endpoints.CHANNEL_BASE(threadId), {
name: options.name, // name: options.name,
archived: options.archived, // archived: options.archived,
auto_archive_duration: options.autoArchiveDuration, // auto_archive_duration: options.autoArchiveDuration,
locked: options.locked, // locked: options.locked,
rate_limit_per_user: options.rateLimitPerUser, // rate_limit_per_user: options.rateLimitPerUser,
reason, // reason,
}); // });
return channelToThread(result); // return channelToThread(result);
} }
@@ -1,34 +1,34 @@
import type { Bot } from "../../../bot.ts"; import type { Bot } from "../../../bot.ts";
import type { ListActiveThreads } from "../../../types/channels/threads/list_active_threads.ts"; import type { ListActiveThreads } from "../../../types/channels/threads/list_active_threads.ts";
import { Collection } from "../../../util/collection.ts"; import { Collection } from "../../../util/collection.ts";
import { channelToThread } from "../../../util/transformers/channel_to_thread.ts"; // import { channelToThread } from "../../../util/transformers/channel_to_thread.ts";
/** Returns all active threads in the channel, including public and private threads. Threads are ordered by their id, in descending order. Requires the VIEW_CHANNEL permission. */ /** Returns all active threads in the channel, including public and private threads. Threads are ordered by their id, in descending order. Requires the VIEW_CHANNEL permission. */
export async function getActiveThreads(bot: Bot, channelId: bigint) { export async function getActiveThreads(bot: Bot, channelId: bigint) {
await bot.utils.requireBotChannelPermissions(bot, channelId, ["VIEW_CHANNEL"]); // await bot.utils.requireBotChannelPermissions(bot, channelId, ["VIEW_CHANNEL"]);
// TODO: pagination // // TODO: pagination
const result = (await bot.rest.runMethod( // const result = (await bot.rest.runMethod(
bot.rest, // bot.rest,
"get", // "get",
bot.constants.endpoints.THREAD_ACTIVE(channelId) // bot.constants.endpoints.THREAD_ACTIVE(channelId)
)) as ListActiveThreads; // )) as ListActiveThreads;
const threads = new Collection( // const threads = new Collection(
result.threads.map((t) => { // result.threads.map((t) => {
const ddThread = channelToThread(t); // const ddThread = channelToThread(t);
return [ddThread.id, ddThread]; // return [ddThread.id, ddThread];
}) // })
); // );
for (const member of result.members) { // for (const member of result.members) {
const thread = threads.get(bot.transformers.snowflake(member.id!)); // const thread = threads.get(bot.transformers.snowflake(member.id!));
thread?.members.set(bot.transformers.snowflake(member.userId!), { // thread?.members.set(bot.transformers.snowflake(member.userId!), {
userId: bot.transformers.snowflake(member.userId!), // userId: bot.transformers.snowflake(member.userId!),
flags: member.flags, // flags: member.flags,
joinTimestamp: Date.parse(member.joinTimestamp), // joinTimestamp: Date.parse(member.joinTimestamp),
}); // });
} // }
return threads; // return threads;
} }
@@ -3,7 +3,7 @@ import { ListPublicArchivedThreads } from "../../../types/channels/threads/list_
import { PermissionStrings } from "../../../types/permissions/permission_strings.ts"; import { PermissionStrings } from "../../../types/permissions/permission_strings.ts";
import { Collection } from "../../../util/collection.ts"; import { Collection } from "../../../util/collection.ts";
import type { Bot } from "../../../bot.ts"; import type { Bot } from "../../../bot.ts";
import { channelToThread } from "../../../util/transformers/channel_to_thread.ts"; // import { channelToThread } from "../../../util/transformers/channel_to_thread.ts";
/** Get the archived threads for this channel, defaults to public */ /** Get the archived threads for this channel, defaults to public */
export async function getArchivedThreads( export async function getArchivedThreads(
@@ -13,45 +13,45 @@ export async function getArchivedThreads(
type?: "public" | "private" | "privateJoinedThreads"; type?: "public" | "private" | "privateJoinedThreads";
} }
) { ) {
const permissions = new Set<PermissionStrings>(["READ_MESSAGE_HISTORY"]); // const permissions = new Set<PermissionStrings>(["READ_MESSAGE_HISTORY"]);
if (options?.type === "private") permissions.add("MANAGE_THREADS"); // if (options?.type === "private") permissions.add("MANAGE_THREADS");
await bot.utils.requireBotChannelPermissions(bot, channelId, [...permissions]); // await bot.utils.requireBotChannelPermissions(bot, channelId, [...permissions]);
// TODO: pagination // // TODO: pagination
const result = (await bot.rest.runMethod( // const result = (await bot.rest.runMethod(
bot.rest, // bot.rest,
"get", // "get",
options?.type === "privateJoinedThreads" // options?.type === "privateJoinedThreads"
? bot.constants.endpoints.THREAD_ARCHIVED_PRIVATE_JOINED(channelId) // ? bot.constants.endpoints.THREAD_ARCHIVED_PRIVATE_JOINED(channelId)
: options?.type === "private" // : options?.type === "private"
? bot.constants.endpoints.THREAD_ARCHIVED_PRIVATE(channelId) // ? bot.constants.endpoints.THREAD_ARCHIVED_PRIVATE(channelId)
: bot.constants.endpoints.THREAD_ARCHIVED_PUBLIC(channelId), // : bot.constants.endpoints.THREAD_ARCHIVED_PUBLIC(channelId),
options // options
? { // ? {
before: options.before, // before: options.before,
limit: options.limit, // limit: options.limit,
type: options.type, // type: options.type,
} // }
: {} // : {}
)) as ListActiveThreads; // )) as ListActiveThreads;
const threads = new Collection( // const threads = new Collection(
result.threads.map((t) => { // result.threads.map((t) => {
const ddThread = channelToThread(t); // const ddThread = channelToThread(t);
return [ddThread.id, ddThread]; // return [ddThread.id, ddThread];
}) // })
); // );
for (const member of result.members) { // for (const member of result.members) {
const thread = threads.get(bot.transformers.snowflake(member.id!)); // const thread = threads.get(bot.transformers.snowflake(member.id!));
thread?.members.set(bot.transformers.snowflake(member.userId!), { // thread?.members.set(bot.transformers.snowflake(member.userId!), {
userId: bot.transformers.snowflake(member.userId!), // userId: bot.transformers.snowflake(member.userId!),
flags: member.flags, // flags: member.flags,
joinTimestamp: Date.parse(member.joinTimestamp), // joinTimestamp: Date.parse(member.joinTimestamp),
}); // });
} // }
return threads; // return threads;
} }
@@ -2,31 +2,32 @@ import type { Bot } from "../../../bot.ts";
import { ThreadMember } from "../../../types/channels/threads/thread_member.ts"; import { ThreadMember } from "../../../types/channels/threads/thread_member.ts";
import { DiscordGatewayIntents } from "../../../types/gateway/gateway_intents.ts"; import { DiscordGatewayIntents } from "../../../types/gateway/gateway_intents.ts";
import { Collection } from "../../../util/collection.ts"; import { Collection } from "../../../util/collection.ts";
import { threadMemberModified } from "../../../util/transformers/thread_member_modified.ts"; // import { threadMemberModified } from "../../../util/transformers/thread_member_modified.ts";
/** Returns thread members objects that are members of the thread. */ /** Returns thread members objects that are members of the thread. */
export async function getThreadMembers(bot: Bot, threadId: bigint) { export async function getThreadMembers(bot: Bot, threadId: bigint) {
// Check if intents is not 0 as proxy ws won't set intents in other instances // // Check if intents is not 0 as proxy ws won't set intents in other instances
if ( // if (
bot.gateway.identifyPayload.intents && // bot.gateway.identifyPayload.intents &&
!(bot.gateway.identifyPayload.intents & DiscordGatewayIntents.GuildMembers) // !(bot.gateway.identifyPayload.intents & DiscordGatewayIntents.GuildMembers)
) { // ) {
throw new Error(bot.constants.Errors.MISSING_INTENT_GUILD_MEMBERS); // throw new Error(bot.constants.Errors.MISSING_INTENT_GUILD_MEMBERS);
} // }
const thread = await bot.cache.threads.get(threadId); // const thread = await bot.cache.threads.get(threadId);
if (thread?.isPrivate) { // if (thread?.isPrivate) {
const channel = await bot.cache.channels.get(thread.parentId); // const channel = await bot.cache.channels.get(thread.parentId);
if (channel && !(await bot.utils.botHasChannelPermissions(bot, channel, ["MANAGE_THREADS"])) && !thread.botIsMember) // if (channel && !(await bot.utils.botHasChannelPermissions(bot, channel, ["MANAGE_THREADS"])) && !thread.botIsMember)
throw new Error(bot.constants.Errors.CANNOT_GET_MEMBERS_OF_AN_UNJOINED_PRIVATE_THREAD); // throw new Error(bot.constants.Errors.CANNOT_GET_MEMBERS_OF_AN_UNJOINED_PRIVATE_THREAD);
} // }
const result = await bot.rest.runMethod<ThreadMember[]>( // const result = await bot.rest.runMethod<ThreadMember[]>(
bot.rest, // bot.rest,
"get", // "get",
bot.constants.endpoints.THREAD_MEMBERS(threadId) // bot.constants.endpoints.THREAD_MEMBERS(threadId)
); // );
const members = result.map((member) => threadMemberModified(member)); // const members = result.map((member) => threadMemberModified(member));
return new Collection(members.map((member) => [member.id, member])); // return new Collection(members.map((member) => [member.id, member]));
} }
@@ -1,23 +1,22 @@
import type { Channel } from "../../../types/channels/channel.ts"; import type { Channel } from "../../../types/channels/channel.ts";
import type { StartThread } from "../../../types/channels/threads/start_thread.ts"; import type { StartThread } from "../../../types/channels/threads/start_thread.ts";
import type { Bot } from "../../../bot.ts"; import type { Bot } from "../../../bot.ts";
import { channelToThread } from "../../../util/transformers/channel_to_thread.ts";
/** Creates a new private thread. Returns a thread channel. */ /** Creates a new private thread. Returns a thread channel. */
export async function startPrivateThread(bot: Bot, channelId: bigint, options: StartThread) { export async function startPrivateThread(bot: Bot, channelId: bigint, options: StartThread) {
const channel = await bot.cache.channels.get(channelId); // const channel = await bot.cache.channels.get(channelId);
if (channel) { // if (channel) {
if (!channel.isGuildTextBasedChannel) throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE); // if (!channel.isGuildTextBasedChannel) throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE);
if (channel.isNewsChannel) throw new Error(bot.constants.Errors.GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS); // if (channel.isNewsChannel) throw new Error(bot.constants.Errors.GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS);
await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PRIVATE_THREADS"]); // await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PRIVATE_THREADS"]);
} // }
return channelToThread( // return channelToThread(
await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.THREAD_START_PRIVATE(channelId), { // await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.THREAD_START_PRIVATE(channelId), {
name: options.name, // name: options.name,
auto_archive_duration: options.autoArchiveDuration, // auto_archive_duration: options.autoArchiveDuration,
}) // })
); // );
} }
+18 -19
View File
@@ -1,28 +1,27 @@
import type { Channel } from "../../../types/channels/channel.ts"; import type { Channel } from "../../../types/channels/channel.ts";
import type { StartThread } from "../../../types/channels/threads/start_thread.ts"; import type { StartThread } from "../../../types/channels/threads/start_thread.ts";
import type { Bot } from "../../../bot.ts"; import type { Bot } from "../../../bot.ts";
import { channelToThread } from "../../../util/transformers/channel_to_thread.ts";
/** Creates a new public thread from an existing message. Returns a thread channel. */ /** Creates a new public thread from an existing message. Returns a thread channel. */
export async function startThread(bot: Bot, channelId: bigint, messageId: bigint, options: StartThread) { export async function startThread(bot: Bot, channelId: bigint, messageId: bigint, options: StartThread) {
const channel = await bot.cache.channels.get(channelId); // const channel = await bot.cache.channels.get(channelId);
if (channel) { // if (channel) {
if (!channel.isGuildTextBasedChannel) { // if (!channel.isGuildTextBasedChannel) {
throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE); // throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE);
} // }
await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PUBLIC_THREADS"]); // await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PUBLIC_THREADS"]);
} // }
return channelToThread( // return channelToThread(
await bot.rest.runMethod<Channel>( // await bot.rest.runMethod<Channel>(
bot.rest, // bot.rest,
"post", // "post",
bot.constants.endpoints.THREAD_START_PUBLIC(channelId, messageId), // bot.constants.endpoints.THREAD_START_PUBLIC(channelId, messageId),
{ // {
name: options.name, // name: options.name,
auto_archive_duration: options.autoArchiveDuration, // auto_archive_duration: options.autoArchiveDuration,
} // }
) // )
); // );
} }
+2 -2
View File
@@ -1,4 +1,4 @@
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import type { Bot } from "../../bot.ts"; import type { Bot } from "../../bot.ts";
/** Delete a message with the channel id and message id only. */ /** Delete a message with the channel id and message id only. */
@@ -9,7 +9,7 @@ export async function deleteMessage(
reason?: string, reason?: string,
delayMilliseconds = 0 delayMilliseconds = 0
) { ) {
const message = await cacheHandlers.get("messages", messageId); const message = await bot.cache.messages.get(messageId);
if (message && message.authorId !== bot.id) { if (message && message.authorId !== bot.id) {
await bot.utils.requireBotChannelPermissions(bot, message.channelId, ["MANAGE_MESSAGES"]); await bot.utils.requireBotChannelPermissions(bot, message.channelId, ["MANAGE_MESSAGES"]);
+14 -3
View File
@@ -1,4 +1,4 @@
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import type { EditMessage } from "../../types/messages/edit_message.ts"; import type { EditMessage } from "../../types/messages/edit_message.ts";
import type { Message } from "../../types/messages/message.ts"; import type { Message } from "../../types/messages/message.ts";
import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import type { PermissionStrings } from "../../types/permissions/permission_strings.ts";
@@ -7,7 +7,7 @@ import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Edit the message. */ /** Edit the message. */
export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) { export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) {
const message = await cacheHandlers.get("messages", messageId); const message = await bot.cache.messages.get(messageId);
if (message) { if (message) {
if (message.authorId !== bot.id) { if (message.authorId !== bot.id) {
@@ -34,7 +34,18 @@ export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint
bot.rest, bot.rest,
"patch", "patch",
bot.constants.endpoints.CHANNEL_MESSAGE(channelId, messageId), bot.constants.endpoints.CHANNEL_MESSAGE(channelId, messageId),
bot.utils.snakelize(content) {
content: content.content,
embeds: content.embeds,
allowed_mentions: {
parse: content.allowedMentions?.parse,
roles: content.allowedMentions?.roles,
users: content.allowedMentions?.users,
replied_user: content.allowedMentions?.repliedUser,
},
file: content.file,
components: content.components,
}
); );
return bot.transformers.message(bot, result); return bot.transformers.message(bot, result);
+2 -2
View File
@@ -1,11 +1,11 @@
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import type { Message } from "../../types/messages/message.ts"; import type { Message } from "../../types/messages/message.ts";
import type { Bot } from "../../bot.ts"; import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts"; import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Fetch a single message from the server. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */ /** Fetch a single message from the server. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */
export async function getMessage(bot: Bot, channelId: bigint, id: bigint) { export async function getMessage(bot: Bot, channelId: bigint, id: bigint) {
if (await cacheHandlers.has("channels", channelId)) { if (await bot.cache.channels.has(channelId)) {
await bot.utils.requireBotChannelPermissions(bot, channelId, ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY"]); await bot.utils.requireBotChannelPermissions(bot, channelId, ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY"]);
} }
+8 -8
View File
@@ -1,4 +1,4 @@
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { Errors } from "../../types/discordeno/errors.ts"; import { Errors } from "../../types/discordeno/errors.ts";
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
@@ -12,7 +12,7 @@ import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) { export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) {
if (typeof content === "string") content = { content }; if (typeof content === "string") content = { content };
const channel = await cacheHandlers.get("channels", channelId); const channel = await bot.cache.channels.get(channelId);
if (channel) { if (channel) {
if ( if (
![ ![
@@ -77,15 +77,15 @@ export async function sendMessage(bot: Bot, channelId: bigint, content: string |
bot.rest, bot.rest,
"post", "post",
bot.constants.endpoints.CHANNEL_MESSAGES(channelId), bot.constants.endpoints.CHANNEL_MESSAGES(channelId),
bot.utils.snakelize({ {
content: content.content, content: content.content,
tts: content.tts, tts: content.tts,
embeds: content.embeds, embeds: content.embeds,
allowed_mentions: { allowed_mentions: {
parse: content.allowedMentions.parse, parse: content.allowedMentions?.parse,
roles: content.allowedMentions.roles, roles: content.allowedMentions?.roles,
users: content.allowedMentions.users, users: content.allowedMentions?.users,
replied_user: content.allowedMentions.repliedUser, replied_user: content.allowedMentions?.repliedUser,
}, },
file: content.file, file: content.file,
// TODO: Snakelize components?? // TODO: Snakelize components??
@@ -100,7 +100,7 @@ export async function sendMessage(bot: Bot, channelId: bigint, content: string |
}, },
} }
: {}), : {}),
}) }
); );
return bot.transformers.message(bot, result); return bot.transformers.message(bot, result);
+2 -2
View File
@@ -1,11 +1,11 @@
import type { Bot } from "../../bot.ts"; import type { Bot } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts"; // import { cacheHandlers } from "../../cache.ts";
import type { Message } from "../../types/messages/message.ts"; import type { Message } from "../../types/messages/message.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts"; import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Suppress all the embeds in this message */ /** Suppress all the embeds in this message */
export async function suppressEmbeds(bot: Bot, channelId: bigint, messageId: bigint) { export async function suppressEmbeds(bot: Bot, channelId: bigint, messageId: bigint) {
const message = await cacheHandlers.get("messages", messageId); const message = await bot.cache.messages.get(messageId);
await bot.utils.requireBotChannelPermissions(bot, channelId, message ? ["MANAGE_MESSAGES"] : ["SEND_MESSAGES"]); await bot.utils.requireBotChannelPermissions(bot, channelId, message ? ["MANAGE_MESSAGES"] : ["SEND_MESSAGES"]);
+86 -24
View File
@@ -1,13 +1,10 @@
import { Bot } from "../bot.ts"; import { Bot } from "../bot.ts";
import type { PresenceUpdate } from "../types/activity/presence_update.ts";
import type { Emoji } from "../types/emojis/emoji.ts"; import type { Emoji } from "../types/emojis/emoji.ts";
import type { Guild } from "../types/guilds/guild.ts"; import type { Guild } from "../types/guilds/guild.ts";
import { Collection } from "../util/collection.ts"; import { Collection } from "../util/collection.ts";
import { iconHashToBigInt } from "../util/hash.ts"; import { iconHashToBigInt } from "../util/hash.ts";
import { channelToThread } from "../util/transformers/channel_to_thread.ts"; import { DiscordenoRole } from "./role.ts";
import { transformChannel } from "./channel.ts"; import { DiscordenoVoiceState } from "./voice_state.ts";
import { DiscordenoRole, transformRole } from "./role.ts";
import { DiscordenoVoiceState, transformVoiceState } from "./voice_state.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts"; import { SnakeCasedPropertiesDeep } from "../types/util.ts";
export function transformGuild( export function transformGuild(
@@ -31,11 +28,34 @@ export function transformGuild(
preferredLocale: payload.guild.preferred_locale, preferredLocale: payload.guild.preferred_locale,
premiumSubscriptionCount: payload.guild.premium_subscription_count, premiumSubscriptionCount: payload.guild.premium_subscription_count,
premiumTier: payload.guild.premium_tier, premiumTier: payload.guild.premium_tier,
stageInstances: payload.guild.stage_instances, stageInstances: payload.guild.stage_instances?.map((si) => ({
/** The id of this Stage instance */
id: bot.transformers.snowflake(si.id),
/** The guild id of the associated Stage channel */
guildId: bot.transformers.snowflake(si.guild_id),
/** The id of the associated Stage channel */
channelId: bot.transformers.snowflake(si.channel_id),
/** The topic of the Stage instance (1-120 characters) */
topic: si.topic,
/** The privacy level of the Stage instance */
privacyLevel: si.privacy_level,
/** Whether or not Stage discovery is disabled */
discoverableDisabled: si.discoverable_disabled,
})),
systemChannelFlags: payload.guild.system_channel_flags, systemChannelFlags: payload.guild.system_channel_flags,
vanityUrlCode: payload.guild.vanity_url_code, vanityUrlCode: payload.guild.vanity_url_code,
verificationLevel: payload.guild.verification_level, verificationLevel: payload.guild.verification_level,
welcomeScreen: payload.guild.welcome_screen, welcomeScreen: payload.guild.welcome_screen
? {
description: payload.guild.welcome_screen.description ?? undefined,
welcomeChannels: payload.guild.welcome_screen.welcome_channels.map((wc) => ({
channelId: bot.transformers.snowflake(wc.channel_id),
description: wc.description,
emojiId: wc.emoji_id ? bot.transformers.snowflake(wc.emoji_id) : undefined,
emojiName: wc.emoji_name ?? undefined,
})),
}
: undefined,
discoverySplash: payload.guild.discovery_splash, discoverySplash: payload.guild.discovery_splash,
bitfield: bitfield:
@@ -49,26 +69,31 @@ export function transformGuild(
shardId: payload.shardId, shardId: payload.shardId,
icon: payload.guild.icon ? iconHashToBigInt(payload.guild.icon) : undefined, icon: payload.guild.icon ? iconHashToBigInt(payload.guild.icon) : undefined,
banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined, banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined,
splash: payload.guild.icon ? iconHashToBigInt(payload.guild.splash) : undefined, splash: payload.guild.splash ? iconHashToBigInt(payload.guild.splash) : undefined,
// TRANSFORMED STUFF BELOW // TRANSFORMED STUFF BELOW
// TODO: Handle channels/threads in a better way? // TODO: Handle channels/threads in a better way?
channels: (payload.guild.channels || []).map((channel) => // channels: (payload.guild.channels || []).map((channel) =>
transformChannel(bot, { channel, guildId: bot.transformers.snowflake(payload.guild.id) }) // bot.transformers.channel(bot, { channel, guildId: bot.transformers.snowflake(payload.guild.id) })
), // ),
threads: (payload.guild.threads || []).map((channel) => channelToThread(channel)), // threads: (payload.guild.threads || []).map((channel) => channelToThread(channel)),
roles: new Collection( roles: new Collection(
(payload.guild.roles || []) (payload.guild.roles || [])
.map((role) => transformRole(bot, { role, guildId: bot.transformers.snowflake(payload.guild.id) })) .map((role) => bot.transformers.role(bot, { role, guildId: bot.transformers.snowflake(payload.guild.id) }))
.map((role) => [role.id, role]) .map((role) => [role.id, role])
), ),
presences: new Collection((payload.guild.presences || []).map((p) => [bot.transformers.snowflake(p.user!.id), p])), // presences: new Collection(
// (payload.guild.presences || []).map((p) => [
// bot.transformers.snowflake(p.user!.id),
// bot.transformers.presence(bot, p),
// ])
// ),
emojis: new Collection((payload.guild.emojis || []).map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])), emojis: new Collection((payload.guild.emojis || []).map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])),
voiceStates: new Collection( voiceStates: new Collection(
(payload.guild.voice_states || []) (payload.guild.voice_states || [])
.map((vs) => .map((vs) =>
transformVoiceState(bot, { voiceState: vs, guildId: bot.transformers.snowflake(payload.guild.id) }) bot.transformers.voiceState(bot, { voiceState: vs, guildId: bot.transformers.snowflake(payload.guild.id) })
) )
.map((vs) => [vs.userId, vs]) .map((vs) => [vs.userId, vs])
), ),
@@ -113,6 +138,13 @@ export interface DiscordenoGuild
| "systemChannelId" | "systemChannelId"
| "rulesChannelId" | "rulesChannelId"
| "publicUpdatesChannelId" | "publicUpdatesChannelId"
| "joinedAt"
| "icon"
| "banner"
| "splash"
| "stageInstances"
| "welcomeScreen"
| "channels"
> { > {
/** Guild id */ /** Guild id */
id: bigint; id: bigint;
@@ -132,12 +164,6 @@ export interface DiscordenoGuild
rulesChannelId?: bigint; rulesChannelId?: bigint;
/** The id of the channel where admins and moderators of Community guilds receive notices from Discord */ /** The id of the channel where admins and moderators of Community guilds receive notices from Discord */
publicUpdatesChannelId?: bigint; publicUpdatesChannelId?: bigint;
/** Whether this server's icon is animated */
animatedIcon: boolean;
/** Whether this server's banner is animated. */
animatedBanner: boolean;
/** Whether this server's splash is animated. */
animatedSplash: boolean;
/** The id of the shard this guild is bound to */ /** The id of the shard this guild is bound to */
shardId: number; shardId: number;
/** Total number of members in this guild */ /** Total number of members in this guild */
@@ -145,13 +171,49 @@ export interface DiscordenoGuild
/** The roles in the guild */ /** The roles in the guild */
roles: Collection<bigint, DiscordenoRole>; roles: Collection<bigint, DiscordenoRole>;
/** The presences of all the users in the guild. */ /** The presences of all the users in the guild. */
presences: Collection<bigint, PresenceUpdate>; // presences: Collection<bigint, DiscordenoPresence>;
/** The Voice State data for each user in a voice channel in this server. */ /** The Voice State data for each user in a voice channel in this server. */
voiceStates: Collection<bigint, DiscordenoVoiceState>; voiceStates: Collection<bigint, DiscordenoVoiceState>;
/** Custom guild emojis */ /** Custom guild emojis */
emojis: Collection<bigint, Emoji>; emojis: Collection<bigint, Emoji>;
/** Whether the bot is the owner of this guild */
isOwner: boolean;
/** Holds all the boolean toggles. */ /** Holds all the boolean toggles. */
bitfield: bigint; bitfield: bigint;
/** When this guild was joined at */
joinedAt?: number;
/** Icon hash */
icon?: bigint;
/** Splash hash */
splash?: bigint;
/** Banner hash */
banner?: bigint;
/** The stage instances in this guild */
stageInstances?: {
/** The id of this Stage instance */
id: bigint;
/** The guild id of the associated Stage channel */
guildId: bigint;
/** The id of the associated Stage channel */
channelId: bigint;
/** The topic of the Stage instance (1-120 characters) */
topic: string;
/** The privacy level of the Stage instance */
privacyLevel: number;
/** Whether or not Stage discovery is disabled */
discoverableDisabled: boolean;
}[];
welcomeScreen?: {
/** The server description shown in the welcome screen */
description?: string;
/** The channels shown in the welcome screen, up to 5 */
welcomeChannels: {
/** The channel's id */
channelId: bigint;
/** The descriptino schown for the channel */
description: string;
/** The emoji id, if the emoji is custom */
emojiId?: bigint;
/** The emoji name if custom, the unicode character if standard, or `null` if no emoji is set */
emojiName?: string;
}[];
};
} }
+3 -1
View File
@@ -5,7 +5,7 @@ import { SnakeCasedPropertiesDeep } from "../types/util.ts";
export function transformVoiceState( export function transformVoiceState(
bot: Bot, bot: Bot,
payload: { voiceState: SnakeCasedPropertiesDeep<VoiceState> } & { guildId: bigint } payload: { voiceState: SnakeCasedPropertiesDeep<VoiceState> } & { guildId: bigint }
) { ): DiscordenoVoiceState {
return { return {
bitfield: bitfield:
(payload.voiceState.deaf ? 1n : 0n) | (payload.voiceState.deaf ? 1n : 0n) |
@@ -40,4 +40,6 @@ export interface DiscordenoVoiceState {
bitfield: bigint; bitfield: bigint;
/** The time at which the user requested to speak */ /** The time at which the user requested to speak */
requestToSpeakTimestamp?: number; requestToSpeakTimestamp?: number;
/** The unique session id */
sessionId: string;
} }
-162
View File
@@ -1,162 +0,0 @@
import { DiscordenoThread } from "../../util/transformers/channel_to_thread.ts";
import type { Collection } from "../../util/collection.ts";
import type { PresenceUpdate } from "../activity/presence_update.ts";
import type { StageInstance } from "../channels/stage_instance.ts";
import type { ThreadMemberModified } from "../channels/threads/thread_member.ts";
import type { ThreadMembersUpdateModified } from "../channels/threads/thread_members_update.ts";
import type { Emoji } from "../emojis/emoji.ts";
import type { GatewayPayload } from "../gateway/gateway_payload.ts";
import type { DiscordGatewayPayload } from "../gateway/gateway_payload.ts";
import type { IntegrationCreateUpdate } from "../integrations/integration_create_update.ts";
import type { IntegrationDelete } from "../integrations/integration_delete.ts";
import type { ApplicationCommandCreateUpdateDelete } from "../interactions/commands/application_command_create_update_delete.ts";
import type { BigInteraction, Interaction } from "../interactions/interaction.ts";
import type { InviteCreate } from "../invites/invite_create.ts";
import type { InviteDelete } from "../invites/invite_delete.ts";
import type { MessageReactionAdd } from "../messages/message_reaction_add.ts";
import type { MessageReactionRemove } from "../messages/message_reaction_remove.ts";
import type { MessageReactionRemoveAll } from "../messages/message_reaction_remove_all.ts";
import type { TypingStart } from "../misc/typing_start.ts";
import type { User } from "../users/user.ts";
import type { VoiceServerUpdate } from "../voice/voice_server_update.ts";
import type { VoiceState } from "../voice/voice_state.ts";
import type { DebugArg } from "./debug_arg.ts";
import type { GuildUpdateChange } from "./guild_update_change.ts";
export type EventHandlersDefinitions = {
/** Sent when properties about the user change. */
botUpdate: [user: User];
/** Sent when a new guild channel is created, relevant to the current user. */
channelCreate: [channel: DiscordenoChannel];
/** Sent when a channel is updated. This is not sent when the field `last_message_id` is altered. To keep track of the `last_message_id` changes, you must listen for `MESSAGE_CREATE` events. */
channelUpdate: [channel: DiscordenoChannel, oldChannel: DiscordenoChannel];
/** Sent when a channel relevant to the current user is deleted. */
channelDelete: [channel: DiscordenoChannel];
/** Sent when a message pin is updated */
channelPinsUpdate: [channel: DiscordenoChannel, guild?: DiscordenoGuild, lastPinTimestamp?: string | null];
debug: [args: string | DebugArg, data?: string];
/** Sent before every event. Discordeno awaits the execution of this event before main event gets sent. */
dispatchRequirements: [data: DiscordGatewayPayload, shardId: number];
/** Sent when a user is banned from a guild. */
guildBanAdd: [guild: DiscordenoGuild, user: User, member?: DiscordenoMember];
/** Sent when a user is unbanned from a guild. */
guildBanRemove: [guild: DiscordenoGuild, user: User, member?: DiscordenoMember];
/**
* This event can be sent in three different scenarios:
* 1. When a user is initially connecting, to lazily load and backfill information for all unavailable guilds sent in the `READY` event. Guilds that are unavailable due to an outage will send a `GUILD_DELETE` event.
* 2. When a Guild becomes available again to the client.
* 3. When the current user joins a new Guild.
*
* This event does not get sent on startup
*/
guildCreate: [guild: DiscordenoGuild];
/** This event does get sent on start when shards are loading the guilds */
guildLoaded: [guild: DiscordenoGuild];
/** When a guild goes available this event will be ran. */
guildAvailable: [guild: DiscordenoGuild];
/** When a guild goes unavailable this event will be ran. */
guildUnavailable: [guild: DiscordenoGuild];
/** Sent when a guilds integration gets updated */
guildIntegrationsUpdate: [guild: DiscordenoGuild];
/** Sent when a guild is updated. */
guildUpdate: [guild: DiscordenoGuild, changes: GuildUpdateChange[]];
/** Sent when a guild becomes or was already unavailable due to an outage, or when the user leaves or is removed from a guild. If the `unavailable` field is not set, the user was removed from the guild. */
guildDelete: [guild: DiscordenoGuild];
/** Sent when a guild's emojis have been updated. */
guildEmojisUpdate: [guild: DiscordenoGuild, emojis: Collection<bigint, Emoji>, oldEmojis: Collection<bigint, Emoji>];
/** Sent when a new user joins a guild. */
guildMemberAdd: [guild: DiscordenoGuild, member: DiscordenoMember];
/** Sent when a user is removed from a guild (leave/kick/ban). */
guildMemberRemove: [guild: DiscordenoGuild, user: User, member?: DiscordenoMember];
/** Sent when a guild member is updated. This will also fire when the user object of a guild member changes. */
guildMemberUpdate: [guild: DiscordenoGuild, member: DiscordenoMember, oldMember?: DiscordenoMember];
/** Sent when a user uses a Slash Command (type 2) or clicks a button (type 3). */
interactionCreate: [data: BigInteraction, member?: DiscordenoMember];
/** Sent when a user uses a Slash Command in a guild (type 2) or clicks a button (type 3). */
interactionGuildCreate: [data: BigInteraction, member: DiscordenoMember];
/** Sent when a user uses a Slash Command in a dm (type 2) or clicks a button (type 3). */
interactionDMCreate: [data: Omit<BigInteraction, "member">];
/** Sent when a lurker joins/leaves/moves stage channels. */
lurkerVoiceStateUpdate: [member: DiscordenoMember, voiceState: VoiceState];
/** Sent when a message is created. */
messageCreate: [message: DiscordenoMessage];
/** Sent when a message is deleted. */
messageDelete: [partial: { id: string; channel: DiscordenoChannel }, message?: DiscordenoMessage];
/** Sent when a message is updated. */
messageUpdate: [message: DiscordenoMessage, oldMessage: DiscordenoMessage];
/** Sent when a user updates its nickname */
nicknameUpdate: [guild: DiscordenoGuild, member: DiscordenoMember, nickname: string, oldNickname?: string];
/** A user's presence is their current state on a guild. This event is sent when a user's presence or info, such as name or avatar, is updated. */
presenceUpdate: [presence: PresenceUpdate, oldPresence?: PresenceUpdate];
/** Sent before every event execution. Discordeno will not await its execution. */
raw: [data: GatewayPayload];
/** Sent when all shards went ready. */
ready: [];
/** Sent when a user adds a reaction to a message. */
reactionAdd: [data: MessageReactionAdd, message?: DiscordenoMessage];
/** Sent when a user removes a reaction from a message. */
reactionRemove: [data: MessageReactionRemove, message?: DiscordenoMessage];
/** Sent when a user explicitly removes all reactions from a message. */
reactionRemoveAll: [payload: MessageReactionRemoveAll, message?: DiscordenoMessage];
/** Sent when a bot removes all instances of a given emoji from the reactions of a message. */
reactionRemoveEmoji: [emoji: Partial<Emoji>, messageId: bigint, channelId: bigint, guildId?: bigint];
/** Sent when a guild role is created. */
roleCreate: [guild: DiscordenoGuild, role: DiscordenoRole];
/** Sent when a guild role is deleted. */
roleDelete: [guild: DiscordenoGuild, role: DiscordenoRole];
/** Sent when a guild role is updated. */
roleUpdate: [guild: DiscordenoGuild, role: DiscordenoRole, old: DiscordenoRole];
roleGained: [guild: DiscordenoGuild, member: DiscordenoMember, roleId: bigint];
roleLost: [guild: DiscordenoGuild, member: DiscordenoMember, roleId: bigint];
shardReady: [shardId: number];
/** Sent when a shard failed to load. */
shardFailedToLoad: [shardId: number, unavailableGuildIds: Set<bigint>];
/** Sent when a Stage instance is created (i.e. the Stage is now "live"). */
stageInstanceCreate: [instance: StageInstance];
/** Sent when a Stage instance has been deleted (i.e. the Stage has been closed). */
stageInstanceDelete: [instance: StageInstance];
/** Sent when a Stage instance has been updated. */
stageInstanceUpdate: [instance: StageInstance];
/** Sent when a thread is created */
threadCreate: [thread: DiscordenoThread];
/** Sent when a thread is updated */
threadUpdate: [thread: DiscordenoThread, oldThread: DiscordenoThread];
/** Sent when the bot gains access to threads */
threadListSync: [threads: Collection<bigint, DiscordenoThread>, members: ThreadMemberModified[], guildId: bigint];
/** Sent when the current users thread member is updated */
threadMemberUpdate: [threadMember: ThreadMemberModified, thread: DiscordenoThread];
/** Sent when anyone is added to or removed from a thread */
threadMembersUpdate: [update: ThreadMembersUpdateModified];
/** Sent when a thread is deleted */
threadDelete: [thread: DiscordenoThread];
/** Sent when a user starts typing in a channel. */
typingStart: [data: TypingStart];
/** Sent when a user joins a voice channel */
voiceChannelJoin: [member: DiscordenoMember, channelId: bigint];
/** Sent when a user leaves a voice channel. Does not get sent when user switches the voice channel */
voiceChannelLeave: [member: DiscordenoMember, channelId: bigint];
/** Sent when a user switches the voice channel */
voiceChannelSwitch: [member: DiscordenoMember, channelId: bigint, oldChannelId: bigint];
/** Sent when a voice server is updated with information for making the bot connect to a voice channel. */
voiceServerUpdate: [payload: VoiceServerUpdate, guild: DiscordenoGuild];
/** Sent when someone joins/leaves/moves voice channels. */
voiceStateUpdate: [member: DiscordenoMember, voiceState: VoiceState];
/** Sent when a guild channel's webhook is created, updated, or deleted. */
webhooksUpdate: [channelId: bigint, guildId: bigint];
/** Sent when a member has passed the guild's Membership Screening requirements */
membershipScreeningPassed: [guild: DiscordenoGuild, member: DiscordenoMember];
/** Sent when an integration is created on a server such as twitch, youtube etc.. */
integrationCreate: [data: IntegrationCreateUpdate];
/** Sent when an integration is updated. */
integrationUpdate: [data: IntegrationCreateUpdate];
/** Sent when an integration is deleted. */
integrationDelete: [data: IntegrationDelete];
/** Sent when a new invite to a channel is created. */
inviteCreate: [data: InviteCreate];
/** Sent when an invite is deleted. */
inviteDelete: [data: InviteDelete];
};
export type EventHandlers = {
[E in keyof EventHandlersDefinitions]?: (...args: EventHandlersDefinitions[E]) => unknown;
};
-1
View File
@@ -2,7 +2,6 @@ export * from "./create_slash_command.ts";
export * from "./debug_arg.ts"; export * from "./debug_arg.ts";
export * from "./edit_webhook_message.ts"; export * from "./edit_webhook_message.ts";
export * from "./errors.ts"; export * from "./errors.ts";
export * from "./event_handlers.ts";
export * from "./file_content.ts"; export * from "./file_content.ts";
export * from "./guild_member.ts"; export * from "./guild_member.ts";
export * from "./guild_update_change.ts"; export * from "./guild_update_change.ts";
+2 -2
View File
@@ -1,11 +1,11 @@
/** https://discord.com/developers/docs/resources/guild#welcome-screen-object-welcome-screen-channel-structure */ /** https://discord.com/developers/docs/resources/guild#welcome-screen-object-welcome-screen-channel-structure */
export interface WelcomeScreenChannel { export interface WelcomeScreenChannel {
/** The channel's id */ /** The channel's id */
channelId: bigint; channelId: string;
/** The descriptino schown for the channel */ /** The descriptino schown for the channel */
description: string; description: string;
/** The emoji id, if the emoji is custom */ /** The emoji id, if the emoji is custom */
emojiId: bigint | null; emojiId: string | null;
/** The emoji name if custom, the unicode character if standard, or `null` if no emoji is set */ /** The emoji name if custom, the unicode character if standard, or `null` if no emoji is set */
emojiName: string | null; emojiName: string | null;
} }
-3
View File
@@ -1,12 +1,9 @@
export * from "./transformers/mod.ts";
export * from "./bigint.ts"; export * from "./bigint.ts";
export * from "./cache_members.ts";
export * from "./calculate_shard_id.ts"; export * from "./calculate_shard_id.ts";
export * from "./collection.ts"; export * from "./collection.ts";
export * from "./constants.ts"; export * from "./constants.ts";
export * from "./dispatch_requirements.ts"; export * from "./dispatch_requirements.ts";
export * from "./hash.ts"; export * from "./hash.ts";
export * from "./loop_object.ts";
export * from "./permissions.ts"; export * from "./permissions.ts";
export * from "./utils.ts"; export * from "./utils.ts";
export * from "./validate_length.ts"; export * from "./validate_length.ts";
-108
View File
@@ -1,108 +0,0 @@
import { cache } from "../../cache.ts";
import { Channel } from "../../types/channels/channel.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { ThreadMemberModified } from "../../types/channels/threads/thread_member.ts";
import { snowflakeToBigint } from "../bigint.ts";
import { Collection } from "../collection.ts";
import { createNewProp } from "../utils.ts";
export const threadToggles = {
/** Whether this thread is archived. */
archived: 1n,
/** Whether this thread is locked. */
locked: 2n,
};
const baseThread: Partial<DiscordenoThread> = {
get archived() {
return Boolean(this.bitfield! & threadToggles.archived);
},
get locked() {
return Boolean(this.bitfield! & threadToggles.locked);
},
get isPrivate() {
return this.type === DiscordChannelTypes.GuildPrivateThread;
},
get isPublic() {
return !this.isPrivate;
},
get guildId() {
return cache.channels.get(this.parentId!)!.guildId;
},
toJSON() {
return {
id: this.id?.toString(),
type: this.type,
parentId: this.parentId?.toString(),
memberCount: this.memberCount,
messageCount: this.messageCount,
archiveTimestamp: new Date(this.archiveTimestamp!).toISOString(),
autoArchiveDuration: this.autoArchiveDuration,
archived: this.archived,
locked: this.locked,
} as Thread;
},
};
export function channelToThread(channel: Channel) {
let bitfield = 0n;
if (channel.threadMetadata?.archived) bitfield |= threadToggles.archived;
if (channel.threadMetadata?.locked) bitfield |= threadToggles.locked;
return Object.create(baseThread, {
id: createNewProp(snowflakeToBigint(channel.id)),
type: createNewProp(channel.type),
parentId: createNewProp(snowflakeToBigint(channel.parentId!)),
memberCount: createNewProp(channel.memberCount),
messageCount: createNewProp(channel.messageCount),
archiveTimestamp: createNewProp(
channel.threadMetadata?.archiveTimestamp ? Date.parse(channel.threadMetadata.archiveTimestamp) : undefined
),
autoArchiveDuration: createNewProp(channel.threadMetadata?.autoArchiveDuration || 0),
bitfield: createNewProp(bitfield),
ownerId: createNewProp(snowflakeToBigint(channel.ownerId!)),
botIsMember: createNewProp(Boolean(channel.member)),
members: createNewProp(new Collection<bigint, Omit<ThreadMemberModified, "id">>()),
}) as DiscordenoThread;
}
export interface Thread {
id: string;
type:
| DiscordChannelTypes.GuildNewsThread
| DiscordChannelTypes.GuildPublicThread
| DiscordChannelTypes.GuildPrivateThread;
parentId: string;
memberCount: number;
messageCount: number;
archiveTimestamp: string;
autoArchiveDuration: number;
archived: boolean;
locked: boolean;
ownerId: string;
botIsMember: boolean;
}
export interface DiscordenoThread {
id: bigint;
type:
| DiscordChannelTypes.GuildNewsThread
| DiscordChannelTypes.GuildPublicThread
| DiscordChannelTypes.GuildPrivateThread;
parentId: bigint;
memberCount: number;
messageCount: number;
archiveTimestamp: number;
autoArchiveDuration: number;
archived: boolean;
locked: boolean;
bitfield: bigint;
ownerId: bigint;
isPrivate: boolean;
isPublic: boolean;
botIsMember: boolean;
guildId: bigint;
members: Collection<bigint, Omit<ThreadMemberModified, "id">>;
toJSON(): Thread;
}
-3
View File
@@ -1,3 +0,0 @@
export * from "./channel_to_thread.ts";
export * from "./thread_member_modified.ts";
export * from "./thread_members_update_modified.ts";
@@ -1,11 +0,0 @@
import { ThreadMember, ThreadMemberModified } from "../../types/channels/threads/thread_member.ts";
import { snowflakeToBigint } from "../bigint.ts";
export function threadMemberModified(member: ThreadMember) {
return {
...member,
id: snowflakeToBigint(member.id!),
userId: snowflakeToBigint(member.userId!),
joinTimestamp: Date.parse(member.joinTimestamp),
} as ThreadMemberModified;
}
@@ -1,16 +0,0 @@
import {
ThreadMembersUpdate,
ThreadMembersUpdateModified,
} from "../../types/channels/threads/thread_members_update.ts";
import { snowflakeToBigint } from "../bigint.ts";
import { threadMemberModified } from "./thread_member_modified.ts";
export function threadMembersUpdateModified(data: ThreadMembersUpdate) {
return {
...data,
id: snowflakeToBigint(data.id),
guildId: snowflakeToBigint(data.guildId),
addedMembers: data.addedMembers?.map((member) => threadMemberModified(member)) || [],
removedMemberIds: data.removedMemberIds?.map((id) => snowflakeToBigint(id)) || [],
} as ThreadMembersUpdateModified;
}
+14 -11
View File
@@ -1,15 +1,15 @@
import { DiscordGatewayIntents } from "../types/gateway/gateway_intents.ts"; import { DiscordGatewayIntents } from "../types/gateway/gateway_intents.ts";
import type { GetGatewayBot } from "../types/gateway/get_gateway_bot.ts"; import type { GetGatewayBot } from "../types/gateway/get_gateway_bot.ts";
import { camelize } from "../util/utils.ts";
import { StartGatewayOptions } from "./start_gateway_options.ts"; import { StartGatewayOptions } from "./start_gateway_options.ts";
import { GatewayManager } from "../bot.ts"; import { GatewayManager } from "../bot.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
/** ADVANCED DEVS ONLY!!!!!! /** ADVANCED DEVS ONLY!!!!!!
* Starts the standalone gateway. * Starts the standalone gateway.
* This will require starting the bot separately. * This will require starting the bot separately.
*/ */
export async function startGateway(gateway: GatewayManager, options: StartGatewayOptions) { export async function startGateway(gateway: GatewayManager, options: StartGatewayOptions) {
gateway.identifyPayload.token = `Bot ${options.token}`; gateway.token = `Bot ${options.token}`;
gateway.secretKey = options.secretKey; gateway.secretKey = options.secretKey;
gateway.firstShardId = options.firstShardId; gateway.firstShardId = options.firstShardId;
gateway.url = options.url; gateway.url = options.url;
@@ -17,25 +17,28 @@ export async function startGateway(gateway: GatewayManager, options: StartGatewa
if (options.maxClusters) gateway.maxClusters = options.maxClusters; if (options.maxClusters) gateway.maxClusters = options.maxClusters;
if (options.compress) { if (options.compress) {
gateway.identifyPayload.compress = options.compress; gateway.compress = options.compress;
} }
if (options.reshard) gateway.reshard = options.reshard; if (options.reshard) gateway.reshard = options.reshard;
// Once an hour check if resharding is necessary // Once an hour check if resharding is necessary
setInterval(() => gateway.resharder(gateway), 1000 * 60 * 60); setInterval(() => gateway.resharder(gateway), 1000 * 60 * 60);
gateway.identifyPayload.intents = options.intents.reduce( gateway.intents = options.intents.reduce(
(bits, next) => (bits |= typeof next === "string" ? DiscordGatewayIntents[next] : next), (bits, next) => (bits |= typeof next === "string" ? DiscordGatewayIntents[next] : next),
0 0
); );
gateway.botGatewayData = camelize( const result = (await fetch(`https://discord.com/api/gateway/bot`, {
await fetch(`https://discord.com/api/gateway/bot`, { headers: { Authorization: gateway.token },
headers: { Authorization: gateway.identifyPayload.token }, }).then((res) => res.json())) as SnakeCasedPropertiesDeep<GetGatewayBot>;
}).then((res) => res.json())
) as GetGatewayBot;
gateway.maxShards = options.maxShards || gateway.botGatewayData.shards; gateway.url = result.url;
gateway.lastShardId = options.lastShardId || gateway.botGatewayData.shards - 1; gateway.sessionStartLimitTotal = result.session_start_limit.total;
gateway.sessionStartLimitRemaining = result.session_start_limit.remaining;
gateway.sessionStartLimitResetAfter = result.session_start_limit.reset_after;
gateway.maxConcurrency = result.session_start_limit.max_concurrency;
gateway.maxShards = options.maxShards || result.shards;
gateway.lastShardId = options.lastShardId || result.shards - 1;
gateway.spawnShards(gateway, gateway.firstShardId); gateway.spawnShards(gateway, gateway.firstShardId);
} }
-122
View File
@@ -1,126 +1,4 @@
import { DiscordGatewayOpcodes } from "../types/codes/gateway_opcodes.ts"; import { DiscordGatewayOpcodes } from "../types/codes/gateway_opcodes.ts";
import { Collection } from "../util/collection.ts";
import { closeWS } from "./close_ws.ts";
import { createShard } from "./create_shard.ts";
import { log } from "./events.ts";
import { handleDiscordPayload } from "./handle_discord_payload.ts";
import { handleOnMessage } from "./handle_on_message.ts";
import { heartbeat } from "./heartbeat.ts";
import { identify } from "./identify.ts";
import { processQueue } from "./process_queue.ts";
import { resharder } from "./resharder.ts";
import { sendShardMessage } from "./send_shard_message.ts";
import { spawnShards } from "./spawn_shards.ts";
import { startGateway } from "./start_gateway.ts";
import { tellClusterToIdentify } from "./tell_cluster_to_identify.ts";
import { resume } from "./resume.ts";
// CONTROLLER LIKE INTERFACE FOR WS HANDLING
export const ws = {
/** The secret key authorization header the bot will expect when sending payloads. */
secretKey: "",
/** The url that all discord payloads for the dispatch type should be sent to. */
url: "",
/** Whether or not to automatically reshard. */
reshard: true,
/** The percentage at which resharding should occur. */
reshardPercentage: 80,
/** The delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 2500. YOU DON"T WANT TO HIT THE RATE LIMIT!!! */
spawnShardDelay: 2600,
/** The maximum shard Id number. Useful for zero-downtime updates or resharding. */
maxShards: 0,
/** Whether or not the resharder should automatically switch to LARGE BOT SHARDING when you are above 100K servers. */
useOptimalLargeBotSharding: true,
/** The amount of shards to load per cluster. */
shardsPerCluster: 25,
/** The maximum amount of clusters to use for your bot. */
maxClusters: 4,
/** The first shard Id to start spawning. */
firstShardId: 0,
/** The last shard Id for this cluster. */
lastShardId: 1,
/** The identify payload holds the necessary data to connect and stay connected with Discords WSS. */
identifyPayload: {
token: "",
compress: false,
properties: {
$os: "linux",
$browser: "Discordeno",
$device: "Discordeno",
},
intents: 0,
shard: [0, 0],
},
botGatewayData: {
/** The WSS URL that can be used for connecting to the gateway. */
url: "wss://gateway.discord.gg/?v=9&encoding=json",
/** The recommended number of shards to use when connecting. */
shards: 1,
/** Info on the current start limit. */
sessionStartLimit: {
/** The total number of session starts the current user is allowed. */
total: 1000,
/** The remaining number of session starts the current user is allowed. */
remaining: 1000,
/** Milliseconds left until limit is reset. */
resetAfter: 0,
/** The number of identify requests allowed per 5 seconds.
* So, if you had a max concurrency of 16, and 16 shards for example, you could start them all up at the same time.
* Whereas if you had 32 shards, if you tried to start up shard 0 and 16 at the same time for example, it would not work. You can start shards 0-15 concurrently, then 16-31...
*/
maxConcurrency: 1,
},
},
shards: new Collection<number, DiscordenoShard>(),
loadingShards: new Collection<
number,
{
shardId: number;
resolve: (value: unknown) => void;
startedAt: number;
}
>(),
/** Stored as bucketId: { clusters: [clusterId, [ShardIds]], createNextShard: boolean } */
buckets: new Collection<
number,
{
clusters: number[][];
createNextShard: (() => unknown)[];
}
>(),
utf8decoder: new TextDecoder(),
// METHODS
/** The handler function that starts the gateway. */
startGateway,
/** The handler for spawning ALL the shards. */
spawnShards,
/** Create the websocket and adds the proper handlers to the websocket. */
createShard,
/** Begins identification of the shard to discord. */
identify,
/** Begins heartbeating of the shard to keep it alive. */
heartbeat,
/** Sends the discord payload to another server. */
handleDiscordPayload,
/** Tell the cluster/worker to begin identifying this shard */
tellClusterToIdentify,
/** Handle the different logs. Used for debugging. */
log,
/** Handles resharding the bot when necessary. */
resharder,
/** Handles the message events from websocket. */
handleOnMessage,
/** Handles processing queue of requests send to this shard. */
processQueue,
/** Closes shard WebSocket connection properly. */
closeWS,
/** Properly adds a message to the shards queue. */
sendShardMessage,
/** Properly resume an old shards session. */
resume,
};
export interface DiscordenoShard { export interface DiscordenoShard {
/** The shard id number. */ /** The shard id number. */
+15 -17
View File
@@ -1,22 +1,20 @@
// THE ORDER OF THE IMPORTS IN THIS FILE MATTER! // // THE ORDER OF THE IMPORTS IN THIS FILE MATTER!
// DO NOT MOVE THEM UNLESS YOU KNOW WHAT YOUR DOING! // // DO NOT MOVE THEM UNLESS YOU KNOW WHAT YOUR DOING!
import "./util/utils.ts"; // import "./util/utils.ts";
import "./util/validate_length.ts"; // import "./util/validate_length.ts";
import "./util/loop_object.ts"; // import "./util/loop_object.ts";
// Final cleanup // // Final cleanup
import { cache } from "../src/cache.ts"; // import { delay } from "../src/util/utils.ts";
import { delay } from "../src/util/utils.ts"; // if (import.meta.main) {
if (import.meta.main) { // // clear all the sweeper intervals
// clear all the sweeper intervals // for (const c of Object.values(cache)) {
for (const c of Object.values(cache)) { // if (!(c instanceof Map)) continue;
if (!(c instanceof Map)) continue;
c.stopSweeper(); // console.log("Cleaned");
console.log("Cleaned"); // }
}
await delay(3000); // await delay(3000);
} // }
+105 -76
View File
@@ -1,90 +1,119 @@
// THE ORDER OF THE IMPORTS IN THIS FILE MATTER! import { TOKEN } from "../configs.ts";
// DO NOT MOVE THEM UNLESS YOU KNOW WHAT YOUR DOING! import { Bot, createBot, createEventHandlers, startBot } from "../mod.ts";
// First complete non-api reliant testing. Deno.test("[Bot] - Starting Tests", async (t) => {
// Don't waste api rate limits if a early test fails. const bot = createBot({
import "./local.ts"; token: TOKEN || Deno.env.get('DISCORD_TOKEN'),
botId: 0n,
events: createEventHandlers({
}),
intents: [],
})
// API TESTING BELOW await startBot(bot as Bot);
// First initiate the connection console.log('Bot online')
import "./ws/start_bot.ts"; })
import "./guilds/create_guild.ts";
// Channel tests
import "./channels/category_children.ts";
import "./channels/channel_overwrite_has_permission.ts";
import "./channels/create_channel.ts";
import "./channels/clone_channel.ts";
import "./channels/delete_channel.ts";
import "./channels/delete_channel_overwrite.ts";
import "./channels/edit_channel.ts";
import "./channels/edit_channel_overwrite.ts";
import "./channels/get_channel.ts";
import "./channels/get_channels.ts";
import "./channels/get_pins.ts";
import "./channels/is_channel_synced.ts";
import "./channels/start_typing.ts";
import "./channels/swap_channels.ts";
// Emojis tests
import "./emojis/create_emoji.ts";
import "./emojis/delete_emoji.ts";
import "./emojis/edit_emoji.ts";
import "./emojis/get_emoji.ts";
import "./emojis/get_emojis.ts";
// Invites tests
import "./invites/create_invite.ts";
import "./invites/delete_invite.ts";
import "./invites/get_channel_invites.ts";
import "./invites/get_invite.ts";
import "./invites/get_invites.ts";
// Messages tests
import "./messages/add_reaction.ts";
import "./messages/add_reactions.ts";
import "./messages/remove_all_reactions.ts";
import "./messages/remove_reaction.ts";
import "./messages/remove_reaction_emoji.ts";
import "./messages/create_message.ts";
import "./messages/delete_message.ts";
import "./messages/delete_messages.ts";
import "./messages/edit_message.ts";
import "./messages/get_message.ts";
import "./messages/get_messages.ts";
import "./messages/get_reactions.ts";
import "./messages/pin_message.ts";
import "./messages/unpin_message.ts";
// Roles tests
import "./roles/add_role.ts";
import "./roles/create_role.ts";
import "./roles/delete_role.ts";
import "./roles/edit_role.ts";
import "./roles/remove_role.ts";
// Members tests
import "./members/search_members.ts";
// Discoveries tests
import "./discoveries/get_discovery_categories.ts";
import "./discoveries/valid_discovery_term.ts";
// Final cleanup
import "./guilds/delete_guild.ts";
import "./ws/ws_close.ts";
import { cache } from "../src/cache.ts";
import { delay } from "../src/util/utils.ts";
if (import.meta.main) {
// clear all the sweeper intervals
for (const c of Object.values(cache)) {
if (!(c instanceof Map)) continue;
c.stopSweeper(); // // THE ORDER OF THE IMPORTS IN THIS FILE MATTER!
console.log("Cleaned"); // // DO NOT MOVE THEM UNLESS YOU KNOW WHAT YOUR DOING!
}
// // First complete non-api reliant testing.
// // Don't waste api rate limits if a early test fails.
// // import "./local.ts";
// // API TESTING BELOW
// // First initiate the connection
// import "./ws/start_bot.ts";
// import "./guilds/create_guild.ts";
// // Channel tests
// import "./channels/category_children.ts";
// import "./channels/channel_overwrite_has_permission.ts";
// import "./channels/create_channel.ts";
// import "./channels/clone_channel.ts";
// import "./channels/delete_channel.ts";
// import "./channels/delete_channel_overwrite.ts";
// import "./channels/edit_channel.ts";
// import "./channels/edit_channel_overwrite.ts";
// import "./channels/get_channel.ts";
// import "./channels/get_channels.ts";
// import "./channels/get_pins.ts";
// import "./channels/is_channel_synced.ts";
// import "./channels/start_typing.ts";
// import "./channels/swap_channels.ts";
// // Emojis tests
// import "./emojis/create_emoji.ts";
// import "./emojis/delete_emoji.ts";
// import "./emojis/edit_emoji.ts";
// import "./emojis/get_emoji.ts";
// import "./emojis/get_emojis.ts";
// // Invites tests
// import "./invites/create_invite.ts";
// import "./invites/delete_invite.ts";
// import "./invites/get_channel_invites.ts";
// import "./invites/get_invite.ts";
// import "./invites/get_invites.ts";
// // Messages tests
// import "./messages/add_reaction.ts";
// import "./messages/add_reactions.ts";
// import "./messages/remove_all_reactions.ts";
// import "./messages/remove_reaction.ts";
// import "./messages/remove_reaction_emoji.ts";
// import "./messages/create_message.ts";
// import "./messages/delete_message.ts";
// import "./messages/delete_messages.ts";
// import "./messages/edit_message.ts";
// import "./messages/get_message.ts";
// import "./messages/get_messages.ts";
// import "./messages/get_reactions.ts";
// import "./messages/pin_message.ts";
// import "./messages/unpin_message.ts";
// // Roles tests
// import "./roles/add_role.ts";
// import "./roles/create_role.ts";
// import "./roles/delete_role.ts";
// import "./roles/edit_role.ts";
// import "./roles/remove_role.ts";
// // Members tests
// import "./members/search_members.ts";
// // Discoveries tests
// import "./discoveries/get_discovery_categories.ts";
// import "./discoveries/valid_discovery_term.ts";
// // Final cleanup
// import "./guilds/delete_guild.ts";
// import "./ws/ws_close.ts";
// import { cache } from "../src/cache.ts";
// import { delay } from "../src/util/utils.ts";
// if (import.meta.main) {
// // clear all the sweeper intervals
// for (const c of Object.values(cache)) {
// if (!(c instanceof Map)) continue;
// c.stopSweeper();
// console.log("Cleaned");
// }
// await delay(3000);
// }
await delay(3000);
}