From 19941ac50ed1613e01618165dd57116cadd576a3 Mon Sep 17 00:00:00 2001 From: chroventer Date: Thu, 24 Sep 2020 11:14:12 -0700 Subject: [PATCH 001/123] Create GitHub action for testing --- .github/workflows/test.yml | 15 +++++++++++++++ test/mod.test.ts | 0 2 files changed, 15 insertions(+) create mode 100644 .github/workflows/test.yml create mode 100644 test/mod.test.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..9cc5554c9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,15 @@ +name: Test +on: + push: + branches: + - master +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: denolib/setup-deno@master + - name: Cache dependencies + run: deno cache mod.ts test/mod.test.ts + - name: Run test script + run: deno test -A \ No newline at end of file diff --git a/test/mod.test.ts b/test/mod.test.ts new file mode 100644 index 000000000..e69de29bb From 9746a8445a57b9ac543155acde9ebf679a72c70c Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 24 Sep 2020 15:57:33 -0400 Subject: [PATCH 002/123] phase 1 of unit tests --- src/module/basicShard.ts | 3 +- src/utils/collection.ts | 2 +- tests/mod.test.ts | 69 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/mod.test.ts diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index d2be980f6..dd8f4499e 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -19,8 +19,9 @@ import { } from "./client.ts"; import { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; import { inflate } from "https://deno.land/x/zlib.es@v1.0.0/mod.ts"; +import { Collection } from "../utils/collection.ts"; -const basicShards = new Map(); +export const basicShards = new Collection(); const heartbeating = new Set(); export interface BasicShard { diff --git a/src/utils/collection.ts b/src/utils/collection.ts index 0ceb347e5..4b5c7b5f1 100644 --- a/src/utils/collection.ts +++ b/src/utils/collection.ts @@ -17,7 +17,7 @@ export class Collection extends Map { } first() { - return this.values().next().value; + return this.values().next().value as V; } last(): V { diff --git a/tests/mod.test.ts b/tests/mod.test.ts new file mode 100644 index 000000000..fcdd135bc --- /dev/null +++ b/tests/mod.test.ts @@ -0,0 +1,69 @@ +import { createClient, Intents, botID } from "../mod.ts"; +import { + assertEquals, +} from "https://deno.land/std/testing/asserts.ts"; +import { createServer, deleteServer } from "../src/handlers/guild.ts"; +import { CreateGuildPayload } from "../src/types/guild.ts"; +import { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; +import { basicShards } from "../src/module/basicShard.ts"; +import { DISTANCE_EXTRA_BIT_BASE } from "https://deno.land/x/zlib.es@v1.0.0/const.ts"; + +const token = Deno.env.get("DISCORD_TOKEN"); +if (!token) throw "No Token Provided!"; + +createClient({ + token, + intents: [Intents.GUILD_MESSAGES, Intents.GUILDS], + eventHandlers: { + // debug: function (data) { + // console.log(data); + // }, + }, +}); + +Deno.test({ + name: "Connecting to gateway", + fn: async () => { + await delay(15000); + assertEquals(botID, "675412054529540107"); + }, + sanitizeResources: false, +}); + +let guildID = ""; + +Deno.test({ + name: "Creating a new guild(Fresh Env)", + fn: async () => { + const result = await createServer({ name: "Discordeno Test Zone" }).catch( + (error) => console.error(error), + ) as CreateGuildPayload; + + guildID = result.id; + assertEquals(typeof result.id, "string"); + }, + sanitizeOps: false, +}); + +Deno.test({ + name: "Deleting guild(Bot is owner)", + fn: async () => { + if (!guildID) throw "The guild id was not present."; + await deleteServer(guildID); + guildID = ""; + + assertEquals(guildID, ""); + }, + sanitizeOps: false, +}); + +// This is meant to be the final test that forcefully crashes the bot +Deno.test({ + name: "Closing Bot! Tests Complete!", + fn: async () => { + const shard = basicShards.first(); + + await shard.socket.close(); + await delay(120000); + }, +}); From 6b2211bc30d8a419bd9cb5528710cca569e4979c Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 24 Sep 2020 23:28:33 -0400 Subject: [PATCH 003/123] exit on last test --- tests/mod.test.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index fcdd135bc..99e37f534 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -5,8 +5,6 @@ import { import { createServer, deleteServer } from "../src/handlers/guild.ts"; import { CreateGuildPayload } from "../src/types/guild.ts"; import { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; -import { basicShards } from "../src/module/basicShard.ts"; -import { DISTANCE_EXTRA_BIT_BASE } from "https://deno.land/x/zlib.es@v1.0.0/const.ts"; const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "No Token Provided!"; @@ -61,9 +59,8 @@ Deno.test({ Deno.test({ name: "Closing Bot! Tests Complete!", fn: async () => { - const shard = basicShards.first(); - - await shard.socket.close(); - await delay(120000); + Deno.exit(); }, + sanitizeOps: false, + sanitizeResources: false, }); From 0ae6c0f353978ac7a1b6668a25bada704574608c Mon Sep 17 00:00:00 2001 From: chroventer Date: Fri, 25 Sep 2020 02:37:36 -0700 Subject: [PATCH 004/123] Move external dependencies to deps.ts --- deps.ts | 1 + tests/mod.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/deps.ts b/deps.ts index c1e06a977..57c27cc2a 100644 --- a/deps.ts +++ b/deps.ts @@ -8,3 +8,4 @@ export { } from "https://deno.land/std@0.67.0/ws/mod.ts"; export { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; export { inflate } from "https://deno.land/x/zlib.es@v1.0.0/mod.ts"; +export { assertEquals } from "https://deno.land/std/testing/asserts.ts"; diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 99e37f534..6522db6fa 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,10 +1,10 @@ import { createClient, Intents, botID } from "../mod.ts"; import { assertEquals, -} from "https://deno.land/std/testing/asserts.ts"; +} from "../deps.ts"; import { createServer, deleteServer } from "../src/handlers/guild.ts"; import { CreateGuildPayload } from "../src/types/guild.ts"; -import { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; +import { delay } from "../deps.ts"; const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "No Token Provided!"; From ad3ec1841ac0d54ee4151a1374eb629b4132a32f Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 25 Sep 2020 10:20:54 -0400 Subject: [PATCH 005/123] role create and delete tests --- tests/mod.test.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 99e37f534..d38d6613b 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -2,10 +2,19 @@ import { createClient, Intents, botID } from "../mod.ts"; import { assertEquals, } from "https://deno.land/std/testing/asserts.ts"; -import { createServer, deleteServer } from "../src/handlers/guild.ts"; +import { + createGuildRole, + createServer, + deleteRole, + deleteServer, +} from "../src/handlers/guild.ts"; import { CreateGuildPayload } from "../src/types/guild.ts"; import { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; +let guildID = ""; +let roleToDelete = ""; +let roleID = ""; + const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "No Token Provided!"; @@ -28,8 +37,6 @@ Deno.test({ sanitizeResources: false, }); -let guildID = ""; - Deno.test({ name: "Creating a new guild(Fresh Env)", fn: async () => { @@ -43,6 +50,58 @@ Deno.test({ sanitizeOps: false, }); +Deno.test({ + name: "Create Role 1: Nothing Provided.", + fn: async () => { + if (!guildID) throw "The guild id was not present"; + + const role = await createGuildRole(guildID, {}); + assertEquals(typeof role.id, "string"); + roleToDelete = role.id; + }, + sanitizeOps: false, +}); + +Deno.test({ + name: "Create Role 2: Custom Options.", + fn: async () => { + if (!guildID) throw "The guild id was not present"; + + const role = await createGuildRole( + guildID, + { + name: "Discordeno", + color: 15277667, + hoist: true, + permissions: ["ADMINISTRATOR"], + mentionable: true, + }, + ); + assertEquals(typeof role.id, "string"); + assertEquals(role.name, "Discordeno"); + assertEquals(role.color, 15277667); + assertEquals(role.hoist, true); + assertEquals(role.mentionable, true); + if ( + !role.permissions.includes("ADMINISTRATOR") + ) { + throw "Missing admin perms on creation."; + } + + roleID = role.id; + }, + sanitizeOps: false, +}); + +Deno.test({ + name: "Delete Role", + fn: async () => { + await deleteRole(guildID, roleToDelete); + roleToDelete = ""; + assertEquals(roleToDelete, ""); + }, +}); + Deno.test({ name: "Deleting guild(Bot is owner)", fn: async () => { From c9f16d01c6188170ee3078bc7c632c10153123c8 Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 29 Sep 2020 10:56:42 -0400 Subject: [PATCH 006/123] edit role test but its failing --- tests/mod.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index be9dfa583..5b980ea3f 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -5,9 +5,11 @@ import { createServer, deleteRole, deleteServer, + editRole, } from "../src/handlers/guild.ts"; import { CreateGuildPayload } from "../src/types/guild.ts"; import { delay } from "../deps.ts"; +import { cache } from "../src/utils/cache.ts"; let guildID = ""; let roleToDelete = ""; @@ -91,6 +93,44 @@ Deno.test({ sanitizeOps: false, }); +Deno.test({ + name: "Edit Role", + fn: async () => { + if (!guildID) throw "The guild id was not present"; + + await editRole(guildID, roleToDelete, { + name: "Discordeno Edited", + color: 4320244, + hoist: false, + permissions: ["READ_MESSAGE_HISTORY"], + mentionable: false, + }); + + const role = cache.guilds.get(guildID)?.roles.get(roleToDelete); + if (!role) throw "Role not found on edit."; + + assertEquals(typeof role.id, "string"); + assertEquals(role.name, "Discordeno Edited"); + assertEquals(role.color, 4320244); + assertEquals(role.hoist, false); + assertEquals(role.mentionable, false); + if ( + role.permissions.includes("ADMINISTRATOR") + ) { + throw "Still have admin perms on edit."; + } + + if ( + !role.permissions.includes("READ_MESSAGE_HISTORY") + ) { + throw "Missing read message history perms on edit."; + } + + roleID = role.id; + }, + sanitizeOps: false, +}); + Deno.test({ name: "Delete Role", fn: async () => { From 364a85f57fcd3c401ffa4acfaf5f9e22b434cfae Mon Sep 17 00:00:00 2001 From: chroventer Date: Tue, 29 Sep 2020 08:47:52 -0700 Subject: [PATCH 007/123] Fix import errors --- deps.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deps.ts b/deps.ts index 2aac186bc..635f2c449 100644 --- a/deps.ts +++ b/deps.ts @@ -1,4 +1,5 @@ export { assertEquals } from "https://deno.land/std/testing/asserts.ts"; +export { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; export { encode } from "https://deno.land/std@0.67.0/encoding/base64.ts"; export { connectWebSocket, @@ -7,3 +8,4 @@ export { isWebSocketPongEvent, } from "https://deno.land/std@0.67.0/ws/mod.ts"; export type { WebSocket } from "https://deno.land/std@0.67.0/ws/mod.ts"; +export { inflate } from "https://deno.land/x/zlib.es@v1.0.0/mod.ts"; From d48fc35e6cb2de2f9e420796fa979d11fb5f34b3 Mon Sep 17 00:00:00 2001 From: chroventer Date: Tue, 29 Sep 2020 09:00:02 -0700 Subject: [PATCH 008/123] Organize imports on save --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index cfa053007..41b6452d6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,8 @@ "editor.formatOnSave": true, "deno.import_intellisense_origins": { "https://deno.land": true + }, + "editor.codeActionsOnSave": { + "source.organizeImports": true } } From 8d8cb7d7184f0b1799c46cae876f7496bd7d30d8 Mon Sep 17 00:00:00 2001 From: chroventer Date: Tue, 29 Sep 2020 11:47:23 -0700 Subject: [PATCH 009/123] Refactor tests --- tests/mod.test.ts | 178 ++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 101 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 5b980ea3f..92fc30fe9 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,163 +1,139 @@ -import { createClient, Intents, botID } from "../mod.ts"; -import { assertEquals } from "../deps.ts"; +import { assertEquals, delay } from "../deps.ts"; import { + botID, + cache, + createClient, createGuildRole, - createServer, deleteRole, deleteServer, editRole, -} from "../src/handlers/guild.ts"; -import { CreateGuildPayload } from "../src/types/guild.ts"; -import { delay } from "../deps.ts"; -import { cache } from "../src/utils/cache.ts"; + Intents, +} from "../mod.ts"; +import { createServer } from "../src/handlers/guild.ts"; +import { Guild } from "../src/structures/guild.ts"; +import { Role } from "../src/structures/role.ts"; -let guildID = ""; -let roleToDelete = ""; -let roleID = ""; - -const token = Deno.env.get("DISCORD_TOKEN"); +const token = "NzUxNzkyMDE3MzUyMjk0NDQx.X1OO4A.GFAh2FCeDNChFQfd3ZNiu6dEAmQ"; +//const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "No Token Provided!"; createClient({ token, intents: [Intents.GUILD_MESSAGES, Intents.GUILDS], - eventHandlers: { - // debug: function (data) { - // console.log(data); - // }, - }, }); +const testOptions = { + sanitizeOps: false, + sanitizeResources: false, +}; + Deno.test({ - name: "Connecting to gateway", + name: "Connecting to the gateway", fn: async () => { await delay(15000); assertEquals(botID, "675412054529540107"); }, - sanitizeResources: false, + ...testOptions, }); -Deno.test({ - name: "Creating a new guild(Fresh Env)", - fn: async () => { - const result = await createServer({ name: "Discordeno Test Zone" }).catch( - (error) => console.error(error), - ) as CreateGuildPayload; +let createdGuild: Guild; - guildID = result.id; - assertEquals(typeof result.id, "string"); +Deno.test({ + name: "Create a guild with and without options", + async fn() { + // Create a test guild + const guild = (await createServer({ + name: "Discordeno Test", + })) as Guild; + assertEquals(typeof guild.id, "string"); + createdGuild = guild; }, - sanitizeOps: false, + ...testOptions, }); -Deno.test({ - name: "Create Role 1: Nothing Provided.", - fn: async () => { - if (!guildID) throw "The guild id was not present"; +// Roles - const role = await createGuildRole(guildID, {}); - assertEquals(typeof role.id, "string"); - roleToDelete = role.id; +let createdRole: Role; + +Deno.test({ + name: "Create a role with and without options", + fn: async () => { + if (!createdGuild.id) throw "The test guild does not exist."; + + const role1 = await createGuildRole(createdGuild.id, { + name: "Role 1", + }); + assertEquals(role1.id, "string"); + + // with options + const role2 = await createGuildRole(createdGuild.id, { + name: "Role 2", + color: 15277667, + hoist: true, + permissions: ["ADMINISTRATOR"], + mentionable: true, + }); + assertEquals(typeof role2.id, "string"); + assertEquals(role2.name, "Role 2"); + assertEquals(role2.color, 15277667); + assertEquals(role2.hoist, true); + assertEquals(role2.mentionable, true); + assertEquals(role2.permissions, 0x00000008); + createdRole = role2; }, - sanitizeOps: false, + ...testOptions, }); Deno.test({ - name: "Create Role 2: Custom Options.", + name: "Edit a role", fn: async () => { - if (!guildID) throw "The guild id was not present"; + if (!createdGuild.id) throw "The guild id was not present"; - const role = await createGuildRole( - guildID, - { - name: "Discordeno", - color: 15277667, - hoist: true, - permissions: ["ADMINISTRATOR"], - mentionable: true, - }, - ); - assertEquals(typeof role.id, "string"); - assertEquals(role.name, "Discordeno"); - assertEquals(role.color, 15277667); - assertEquals(role.hoist, true); - assertEquals(role.mentionable, true); - if ( - !role.permissions.includes("ADMINISTRATOR") - ) { - throw "Missing admin perms on creation."; - } - - roleID = role.id; - }, - sanitizeOps: false, -}); - -Deno.test({ - name: "Edit Role", - fn: async () => { - if (!guildID) throw "The guild id was not present"; - - await editRole(guildID, roleToDelete, { - name: "Discordeno Edited", + await editRole(createdGuild.id, createdRole.id, { + name: "Edited Role", color: 4320244, hoist: false, permissions: ["READ_MESSAGE_HISTORY"], mentionable: false, }); - const role = cache.guilds.get(guildID)?.roles.get(roleToDelete); + const role = cache.guilds.get(createdRole.id)?.roles.get(createdRole.id); if (!role) throw "Role not found on edit."; - assertEquals(typeof role.id, "string"); assertEquals(role.name, "Discordeno Edited"); assertEquals(role.color, 4320244); assertEquals(role.hoist, false); assertEquals(role.mentionable, false); - if ( - role.permissions.includes("ADMINISTRATOR") - ) { - throw "Still have admin perms on edit."; - } - - if ( - !role.permissions.includes("READ_MESSAGE_HISTORY") - ) { - throw "Missing read message history perms on edit."; - } - - roleID = role.id; + createdRole = role; }, - sanitizeOps: false, + ...testOptions, }); Deno.test({ name: "Delete Role", fn: async () => { - await deleteRole(guildID, roleToDelete); - roleToDelete = ""; - assertEquals(roleToDelete, ""); + await deleteRole(createdGuild.id, createdRole.id); + createdRole.id = ""; + assertEquals(createdRole.id, ""); }, }); Deno.test({ name: "Deleting guild(Bot is owner)", fn: async () => { - if (!guildID) throw "The guild id was not present."; - await deleteServer(guildID); - guildID = ""; - - assertEquals(guildID, ""); + if (!createdGuild.id) throw "The guild id was not present."; + await deleteServer(createdGuild.id); + createdGuild.id = ""; + assertEquals(createdGuild, ""); }, - sanitizeOps: false, + ...testOptions, }); // This is meant to be the final test that forcefully crashes the bot Deno.test({ - name: "Closing Bot! Tests Complete!", - fn: async () => { - Deno.exit(); + name: "Exit the process forcefully after all the tests have passed", + async fn() { + Deno.exit(1); }, - sanitizeOps: false, - sanitizeResources: false, + ...testOptions, }); From ad7bd30468f71310ea220311072c0de0e36dfd23 Mon Sep 17 00:00:00 2001 From: chroventer Date: Tue, 29 Sep 2020 12:21:08 -0700 Subject: [PATCH 010/123] Refactored tests --- tests/mod.test.ts | 106 ++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 92fc30fe9..21281dff9 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,27 +1,27 @@ +import { assert } from "https://deno.land/std@0.70.0/testing/asserts.ts"; import { assertEquals, delay } from "../deps.ts"; import { botID, - cache, createClient, createGuildRole, deleteRole, deleteServer, editRole, Intents, + Role, } from "../mod.ts"; import { createServer } from "../src/handlers/guild.ts"; import { Guild } from "../src/structures/guild.ts"; -import { Role } from "../src/structures/role.ts"; -const token = "NzUxNzkyMDE3MzUyMjk0NDQx.X1OO4A.GFAh2FCeDNChFQfd3ZNiu6dEAmQ"; -//const token = Deno.env.get("DISCORD_TOKEN"); -if (!token) throw "No Token Provided!"; +const token = Deno.env.get("DISCORD_TOKEN"); +if (!token) throw "Token is not provided"; createClient({ token, intents: [Intents.GUILD_MESSAGES, Intents.GUILDS], }); +// Default options for all test cases const testOptions = { sanitizeOps: false, sanitizeResources: false, @@ -30,101 +30,89 @@ const testOptions = { Deno.test({ name: "Connecting to the gateway", fn: async () => { + // Delay the execution by 15 seconds await delay(15000); - assertEquals(botID, "675412054529540107"); + + // Check whether botID is nil or not + assert(botID); }, ...testOptions, }); -let createdGuild: Guild; +let guildID: string; Deno.test({ - name: "Create a guild with and without options", + name: "Create a guild (without options)", async fn() { - // Create a test guild - const guild = (await createServer({ + // Create a test guild with the name "Discordeno Test" + const createdGuild = (await createServer({ name: "Discordeno Test", })) as Guild; - assertEquals(typeof guild.id, "string"); - createdGuild = guild; + + // Check whether createdGuild is nil or not + assert(createdGuild); + + guildID = createdGuild.id; }, ...testOptions, }); // Roles - -let createdRole: Role; +let roleID: string; Deno.test({ - name: "Create a role with and without options", + name: "Create a role in a guild (~with~ and without options)", fn: async () => { - if (!createdGuild.id) throw "The test guild does not exist."; - - const role1 = await createGuildRole(createdGuild.id, { + // Create a role "Role 1" in the test guild + const createdRole = await createGuildRole(guildID, { name: "Role 1", }); - assertEquals(role1.id, "string"); - // with options - const role2 = await createGuildRole(createdGuild.id, { - name: "Role 2", - color: 15277667, - hoist: true, - permissions: ["ADMINISTRATOR"], - mentionable: true, - }); - assertEquals(typeof role2.id, "string"); - assertEquals(role2.name, "Role 2"); - assertEquals(role2.color, 15277667); - assertEquals(role2.hoist, true); - assertEquals(role2.mentionable, true); - assertEquals(role2.permissions, 0x00000008); - createdRole = role2; + // Check whether the created role is nil or not + assert(createdRole.id); + + roleID = createdRole.id; }, ...testOptions, }); Deno.test({ - name: "Edit a role", + name: "Edit a role in a guild", fn: async () => { - if (!createdGuild.id) throw "The guild id was not present"; - - await editRole(createdGuild.id, createdRole.id, { + const updatedRole = (await editRole(guildID, roleID, { name: "Edited Role", color: 4320244, hoist: false, - permissions: ["READ_MESSAGE_HISTORY"], mentionable: false, - }); + })) as Role; - const role = cache.guilds.get(createdRole.id)?.roles.get(createdRole.id); - if (!role) throw "Role not found on edit."; - assertEquals(typeof role.id, "string"); - assertEquals(role.name, "Discordeno Edited"); - assertEquals(role.color, 4320244); - assertEquals(role.hoist, false); - assertEquals(role.mentionable, false); - createdRole = role; + // Assertions + assert(updatedRole.id); + assertEquals(updatedRole.name, "Edited Role"); + assertEquals(updatedRole.color, 4320244); + assertEquals(updatedRole.hoist, false); + assertEquals(updatedRole.mentionable, false); + + roleID = updatedRole.id; }, ...testOptions, }); Deno.test({ - name: "Delete Role", - fn: async () => { - await deleteRole(createdGuild.id, createdRole.id); - createdRole.id = ""; - assertEquals(createdRole.id, ""); + name: "Delete a role from the guild", + async fn() { + await deleteRole(guildID, roleID); + roleID = ""; + assertEquals(roleID, ""); }, }); Deno.test({ - name: "Deleting guild(Bot is owner)", - fn: async () => { - if (!createdGuild.id) throw "The guild id was not present."; - await deleteServer(createdGuild.id); - createdGuild.id = ""; - assertEquals(createdGuild, ""); + name: "Delete a guild", + async fn() { + await deleteServer(guildID); + guildID = ""; + assertEquals(guildID, ""); }, ...testOptions, }); From 689fc66493d7d215eb7fb6df66736eaba7d06c5e Mon Sep 17 00:00:00 2001 From: chroventer Date: Wed, 30 Sep 2020 03:25:44 -0700 Subject: [PATCH 011/123] =?UTF-8?q?=F0=9F=A4=94=20some=20refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/mod.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 21281dff9..f29b3fe18 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -28,7 +28,7 @@ const testOptions = { }; Deno.test({ - name: "Connecting to the gateway", + name: "connect to the gateway", fn: async () => { // Delay the execution by 15 seconds await delay(15000); @@ -42,7 +42,7 @@ Deno.test({ let guildID: string; Deno.test({ - name: "Create a guild (without options)", + name: "create a guild (without options)", async fn() { // Create a test guild with the name "Discordeno Test" const createdGuild = (await createServer({ @@ -61,8 +61,8 @@ Deno.test({ let roleID: string; Deno.test({ - name: "Create a role in a guild (~with~ and without options)", - fn: async () => { + name: "create a role in a guild (~with~ and without options)", + async fn() { // Create a role "Role 1" in the test guild const createdRole = await createGuildRole(guildID, { name: "Role 1", @@ -77,8 +77,8 @@ Deno.test({ }); Deno.test({ - name: "Edit a role in a guild", - fn: async () => { + name: "edit a role in a guild", + async fn() { const updatedRole = (await editRole(guildID, roleID, { name: "Edited Role", color: 4320244, @@ -99,7 +99,7 @@ Deno.test({ }); Deno.test({ - name: "Delete a role from the guild", + name: "delete a role from the guild", async fn() { await deleteRole(guildID, roleID); roleID = ""; @@ -108,7 +108,7 @@ Deno.test({ }); Deno.test({ - name: "Delete a guild", + name: "delete a guild", async fn() { await deleteServer(guildID); guildID = ""; @@ -119,7 +119,7 @@ Deno.test({ // This is meant to be the final test that forcefully crashes the bot Deno.test({ - name: "Exit the process forcefully after all the tests have passed", + name: "exit the process forcefully after all the tests are done", async fn() { Deno.exit(1); }, From 3da788196624a15c2a3d701ccbbb330428d7a0bd Mon Sep 17 00:00:00 2001 From: chroventer Date: Wed, 30 Sep 2020 04:07:01 -0700 Subject: [PATCH 012/123] Refactored --- tests/mod.test.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index f29b3fe18..68edaabc1 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -30,7 +30,7 @@ const testOptions = { Deno.test({ name: "connect to the gateway", fn: async () => { - // Delay the execution by 15 seconds + // Delay the execution by 15 seconds (15000 ms) await delay(15000); // Check whether botID is nil or not @@ -42,9 +42,9 @@ Deno.test({ let guildID: string; Deno.test({ - name: "create a guild (without options)", + name: "create a guild", async fn() { - // Create a test guild with the name "Discordeno Test" + // Create a guild "Discordeno Test" const createdGuild = (await createServer({ name: "Discordeno Test", })) as Guild; @@ -61,9 +61,9 @@ Deno.test({ let roleID: string; Deno.test({ - name: "create a role in a guild (~with~ and without options)", + name: "create a role in a guild", async fn() { - // Create a role "Role 1" in the test guild + // Create a role "Role 1" in the guild "Discordeno Test" const createdRole = await createGuildRole(guildID, { name: "Role 1", }); @@ -79,7 +79,8 @@ Deno.test({ Deno.test({ name: "edit a role in a guild", async fn() { - const updatedRole = (await editRole(guildID, roleID, { + // Edit a role "Role 1" in the guild "Discordeno Test" + const editedRole = (await editRole(guildID, roleID, { name: "Edited Role", color: 4320244, hoist: false, @@ -87,13 +88,13 @@ Deno.test({ })) as Role; // Assertions - assert(updatedRole.id); - assertEquals(updatedRole.name, "Edited Role"); - assertEquals(updatedRole.color, 4320244); - assertEquals(updatedRole.hoist, false); - assertEquals(updatedRole.mentionable, false); + assert(editedRole.id); + assertEquals(editedRole.name, "Edited Role"); + assertEquals(editedRole.color, 4320244); + assertEquals(editedRole.hoist, false); + assertEquals(editedRole.mentionable, false); - roleID = updatedRole.id; + roleID = editedRole.id; }, ...testOptions, }); From 5cae8f2627656ee31e64beeb8b418ac67bd9b4c9 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 1 Oct 2020 09:05:20 -0400 Subject: [PATCH 013/123] fix edit role bug --- src/handlers/guild.ts | 9 +++++++-- src/utils/permissions.ts | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 24dbb7efc..5bf2a967d 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -30,7 +30,7 @@ import { urlToBase64 } from "../utils/utils.ts"; import { Intents } from "../types/options.ts"; import { identifyPayload } from "../module/client.ts"; import { requestAllMembers } from "../module/shardingManager.ts"; -import { botHasPermission } from "../utils/permissions.ts"; +import { botHasPermission, calculateBits } from "../utils/permissions.ts"; import { RequestManager } from "../module/requestManager.ts"; import { endpoints } from "../constants/discord.ts"; import { Errors } from "../types/errors.ts"; @@ -321,7 +321,12 @@ export function editRole( ) { throw new Error(Errors.MISSING_MANAGE_ROLES); } - return RequestManager.patch(endpoints.GUILD_ROLE(guildID, id), options); + return RequestManager.patch(endpoints.GUILD_ROLE(guildID, id), { + ...options, + permissions: options.permissions + ? calculateBits(options.permissions) + : undefined, + }); } /** Delete a guild role. Requires the MANAGE_ROLES permission. */ diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index b8ee3eaf5..daa7fe27d 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -180,6 +180,7 @@ export async function hasChannelPermissions( return botHasPermission(guild.id, permissions); } +/** This function converts a bitwise string to permission strings */ export function calculatePermissions(permissionBits: bigint) { return Object.keys(Permissions).filter((perm) => { if (typeof perm !== "number") return false; @@ -187,6 +188,14 @@ export function calculatePermissions(permissionBits: bigint) { }) as Permission[]; } +/** This function converts an array of permissions into the bitwise string. */ +export function calculateBits(permissions: Permission[]) { + return permissions.reduce( + (bits, perm) => bits |= BigInt(Permissions[perm]), + BigInt(0), + ).toString(); +} + export async function highestRole(guildID: string, memberID: string) { const guild = await cacheHandlers.get("guilds", guildID); if (!guild) return; From 3d3aee831053a71045a422a66f9f1f1426edb8bb Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 1 Oct 2020 09:32:47 -0400 Subject: [PATCH 014/123] fixes member cached before creating message --- src/controllers/messages.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/controllers/messages.ts b/src/controllers/messages.ts index a805298ef..a0e72dfdc 100644 --- a/src/controllers/messages.ts +++ b/src/controllers/messages.ts @@ -1,12 +1,11 @@ +import { eventHandlers } from "../module/client.ts"; +import { structures } from "../structures/mod.ts"; import type { DiscordPayload } from "../types/discord.ts"; import type { MessageCreateOptions, - MessageDeletePayload, MessageDeleteBulkPayload, + MessageDeletePayload, } from "../types/message.ts"; - -import { eventHandlers } from "../module/client.ts"; -import { structures } from "../structures/mod.ts"; import { cacheHandlers } from "./cache.ts"; export async function handleInternalMessageCreate(data: DiscordPayload) { @@ -16,9 +15,6 @@ export async function handleInternalMessageCreate(data: DiscordPayload) { const channel = await cacheHandlers.get("channels", payload.channel_id); if (channel) channel.lastMessageID = payload.id; - const message = await structures.createMessage(payload); - // Cache the message - cacheHandlers.set("messages", payload.id, message); const guild = payload.guild_id ? await cacheHandlers.get("guilds", payload.guild_id) : undefined; @@ -47,6 +43,10 @@ export async function handleInternalMessageCreate(data: DiscordPayload) { } }); + const message = await structures.createMessage(payload); + // Cache the message + cacheHandlers.set("messages", payload.id, message); + eventHandlers.messageCreate?.(message); } From 2dc6b8d460115217506db92c924c280eda2dc94b Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 1 Oct 2020 09:48:53 -0400 Subject: [PATCH 015/123] add channel overwrite has permission --- tests/mod.test.ts | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 68edaabc1..5d0052d21 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -10,8 +10,12 @@ import { Intents, Role, } from "../mod.ts"; -import { createServer } from "../src/handlers/guild.ts"; +import { channelOverwriteHasPermission } from "../src/handlers/channel.ts"; +import { createGuildChannel, createServer } from "../src/handlers/guild.ts"; import { Guild } from "../src/structures/guild.ts"; +import { OverwriteType } from "../src/types/guild.ts"; +import { Permissions } from "../src/types/permission.ts"; +import { cache } from "../src/utils/cache.ts"; const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "Token is not provided"; @@ -99,6 +103,53 @@ Deno.test({ ...testOptions, }); +Deno.test({ + name: "channel overwrite has permission", + async fn() { + const guild = cache.guilds.get(guildID)!; + const channel = await createGuildChannel(guild, "testing", { + permission_overwrites: [ + { + id: roleID, + type: OverwriteType.ROLE, + allow: ["VIEW_CHANNEL", "SEND_MESSAGES"], + deny: ["USE_EXTERNAL_EMOJIS"], + }, + ], + }); + + assert(channel.id); + // Checks whether the role has these perms + assert( + channelOverwriteHasPermission( + guildID, + roleID, + channel.permission_overwrites || [], + [Permissions.VIEW_CHANNEL, Permissions.SEND_MESSAGES], + ), + ); + // Checks if this permission was actually disabled + assert( + !channelOverwriteHasPermission( + guildID, + roleID, + channel.permission_overwrites || [], + [Permissions.USE_EXTERNAL_EMOJIS], + ), + ); + // Checks if this permission is missing that was neither allowed nor denied + assert( + !channelOverwriteHasPermission( + guildID, + roleID, + channel.permission_overwrites || [], + [Permissions.MANAGE_MESSAGES], + ), + ); + }, + ...testOptions, +}); + Deno.test({ name: "delete a role from the guild", async fn() { From 11bf0a458f1abb773f9df5c249759574a4f4a8be Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 1 Oct 2020 10:12:56 -0400 Subject: [PATCH 016/123] add get message --- tests/mod.test.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 5d0052d21..1dae163e4 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -10,7 +10,11 @@ import { Intents, Role, } from "../mod.ts"; -import { channelOverwriteHasPermission } from "../src/handlers/channel.ts"; +import { + channelOverwriteHasPermission, + getMessage, + sendMessage, +} from "../src/handlers/channel.ts"; import { createGuildChannel, createServer } from "../src/handlers/guild.ts"; import { Guild } from "../src/structures/guild.ts"; import { OverwriteType } from "../src/types/guild.ts"; @@ -63,6 +67,7 @@ Deno.test({ // Roles let roleID: string; +let channelID: string; Deno.test({ name: "create a role in a guild", @@ -146,10 +151,22 @@ Deno.test({ [Permissions.MANAGE_MESSAGES], ), ); + + channelID = channel.id; }, ...testOptions, }); +Deno.test({ + name: "get message", + async fn() { + const message = await sendMessage(channelID, "Test message 1"); + const rawMessage = await getMessage(channelID, message.id); + + assertEquals(message.id, rawMessage.id); + }, +}); + Deno.test({ name: "delete a role from the guild", async fn() { From 32e88e7f8144d63cac7929ea5feb872390aa4383 Mon Sep 17 00:00:00 2001 From: chroventer Date: Fri, 2 Oct 2020 02:46:48 -0700 Subject: [PATCH 017/123] Format collection.ts --- src/utils/collection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/collection.ts b/src/utils/collection.ts index 99dc26cc0..9576512e0 100644 --- a/src/utils/collection.ts +++ b/src/utils/collection.ts @@ -75,7 +75,7 @@ export class Collection extends Map { reduce( callback: (accumulator: T, value: V, key: K) => T, - initialValue?: T + initialValue?: T, ): T { let accumulator: T = initialValue!; From f5421a615b06bb92ad24039adf00835497039203 Mon Sep 17 00:00:00 2001 From: chroventer Date: Fri, 2 Oct 2020 03:10:33 -0700 Subject: [PATCH 018/123] Add missing tests --- deps.ts | 6 +- tests/mod.test.ts | 173 +++++++++++++++++++++++++++++----------------- 2 files changed, 116 insertions(+), 63 deletions(-) diff --git a/deps.ts b/deps.ts index 635f2c449..fd14f318d 100644 --- a/deps.ts +++ b/deps.ts @@ -1,4 +1,8 @@ -export { assertEquals } from "https://deno.land/std/testing/asserts.ts"; +export { + assert, + assertArrayContains, + assertEquals, +} from "https://deno.land/std/testing/asserts.ts"; export { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; export { encode } from "https://deno.land/std@0.67.0/encoding/base64.ts"; export { diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 1dae163e4..e543769ea 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,25 +1,34 @@ -import { assert } from "https://deno.land/std@0.70.0/testing/asserts.ts"; -import { assertEquals, delay } from "../deps.ts"; +import { assert, assertArrayContains, assertEquals, delay } from "../deps.ts"; import { botID, + + cache, + Channel, createClient, + + createGuildChannel, createGuildRole, + + createServer, + deleteChannel, + deleteRole, + deleteServer, editRole, - Intents, - Role, -} from "../mod.ts"; -import { - channelOverwriteHasPermission, + getMessage, + + Guild, + Intents, + + OverwriteType, + Role, + sendMessage, -} from "../src/handlers/channel.ts"; -import { createGuildChannel, createServer } from "../src/handlers/guild.ts"; -import { Guild } from "../src/structures/guild.ts"; -import { OverwriteType } from "../src/types/guild.ts"; -import { Permissions } from "../src/types/permission.ts"; -import { cache } from "../src/utils/cache.ts"; +} from "../mod.ts"; +import { editChannel } from "../src/handlers/channel.ts"; +import { getChannel } from "../src/handlers/guild.ts"; const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "Token is not provided"; @@ -65,9 +74,8 @@ Deno.test({ ...testOptions, }); -// Roles +// Role let roleID: string; -let channelID: string; Deno.test({ name: "create a role in a guild", @@ -78,7 +86,7 @@ Deno.test({ }); // Check whether the created role is nil or not - assert(createdRole.id); + assert(createdRole); roleID = createdRole.id; }, @@ -97,7 +105,7 @@ Deno.test({ })) as Role; // Assertions - assert(editedRole.id); + assert(editedRole); assertEquals(editedRole.name, "Edited Role"); assertEquals(editedRole.color, 4320244); assertEquals(editedRole.hoist, false); @@ -108,65 +116,98 @@ Deno.test({ ...testOptions, }); +// Channel + +let channelID: string; + Deno.test({ - name: "channel overwrite has permission", + name: "create a channel in a guild", async fn() { - const guild = cache.guilds.get(guildID)!; - const channel = await createGuildChannel(guild, "testing", { - permission_overwrites: [ - { - id: roleID, - type: OverwriteType.ROLE, - allow: ["VIEW_CHANNEL", "SEND_MESSAGES"], - deny: ["USE_EXTERNAL_EMOJIS"], - }, - ], - }); + const guild = cache.guilds.get(guildID); + if (!guild) throw "Guild not found"; + const createdChannel = await createGuildChannel(guild, "test"); - assert(channel.id); - // Checks whether the role has these perms - assert( - channelOverwriteHasPermission( - guildID, - roleID, - channel.permission_overwrites || [], - [Permissions.VIEW_CHANNEL, Permissions.SEND_MESSAGES], - ), - ); - // Checks if this permission was actually disabled - assert( - !channelOverwriteHasPermission( - guildID, - roleID, - channel.permission_overwrites || [], - [Permissions.USE_EXTERNAL_EMOJIS], - ), - ); - // Checks if this permission is missing that was neither allowed nor denied - assert( - !channelOverwriteHasPermission( - guildID, - roleID, - channel.permission_overwrites || [], - [Permissions.MANAGE_MESSAGES], - ), - ); + // Check whether the created channel is nil or not + assert(createdChannel); - channelID = channel.id; + channelID = createdChannel.id; }, ...testOptions, }); Deno.test({ - name: "get message", + name: "get a channel in a guild", async fn() { - const message = await sendMessage(channelID, "Test message 1"); - const rawMessage = await getMessage(channelID, message.id); + const channel = await getChannel(channelID); - assertEquals(message.id, rawMessage.id); + assertEquals(channel.id, channelID); + }, + ...testOptions, +}); + +Deno.test({ + name: "edit a channel in a guild", + async fn() { + const channel = await editChannel(channelID, { + name: "edited channel", + }) as Channel; + + assert(channel); + + channelID = channel.id; }, }); +Deno.test({ + name: "channel overwrite has permission", + async fn() { + const channel = cache.channels.get(channelID); + if (!channel) throw "Channel not found"; + assertArrayContains(channel.permission_overwrites!, [ + { + id: roleID, + type: OverwriteType.ROLE, + // The type for Channel#permission_overwrites is "RawOverwrite[] | undefined" + // not "Overwrite[]"; therefore, permission strings cannot be used. + // allow: ["VIEW_CHANNEL", "SEND_MESSAGES"], + // deny: ["USE_EXTERNAL_EMOJIS"], + }, + ]); + + // THIS TEST CASE SHOULD BE REFACTORED AND IMPROVED + // CURRENTLY, IT USES Channel#permission_overwrites + // but preferably, it should use the channelOverwriteHasPermission() + }, + ...testOptions, +}); + +// Message + +let messageID: string; + +Deno.test({ + name: "create a message in a guild", + async fn() { + const createdMessage = await sendMessage(channelID, "test"); + + // Check whether the created message is nil or not + assert(createdMessage); + + messageID = createdMessage.id; + }, +}); + +Deno.test({ + name: "get a message in a guild", + async fn() { + const message = await getMessage(channelID, messageID); + + assertEquals(messageID, message.id); + }, +}); + +// Clean up + Deno.test({ name: "delete a role from the guild", async fn() { @@ -176,6 +217,14 @@ Deno.test({ }, }); +Deno.test({ + name: "delete a channel in the guild", + async fn() { + await deleteChannel(guildID, channelID); + }, + ...testOptions, +}); + Deno.test({ name: "delete a guild", async fn() { From 8638961c08e3668a149b356af22bbc47db665dd6 Mon Sep 17 00:00:00 2001 From: chroventer Date: Sat, 3 Oct 2020 02:29:18 -0700 Subject: [PATCH 019/123] Format on save mode -> modifications --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index f5003566b..f50a9228a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "deno.enable": true, "editor.formatOnSave": true, + "editor.formatOnSaveMode": "modifications", "deno.import_intellisense_origins": { "https://deno.land": true }, From a81ceff28f7136517a9b0596876b75c08e729c3d Mon Sep 17 00:00:00 2001 From: chroventer Date: Sun, 25 Oct 2020 09:54:40 +0400 Subject: [PATCH 020/123] Add "Competing --- src/types/activity.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types/activity.ts b/src/types/activity.ts index 81a180b4b..f5a97e293 100644 --- a/src/types/activity.ts +++ b/src/types/activity.ts @@ -18,4 +18,6 @@ export enum ActivityType { Listening, /** Example: ":smiley: I am cool" */ Custom = 4, + /** Example: "Competing in Arena World Champions" */ + Competing } From b3704b27772c6c1dbe7a129b8fc55d1ccd1e6a78 Mon Sep 17 00:00:00 2001 From: chroventer Date: Sun, 25 Oct 2020 09:57:31 +0400 Subject: [PATCH 021/123] revert: "Add "Competing" --- src/types/activity.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/types/activity.ts b/src/types/activity.ts index f5a97e293..81a180b4b 100644 --- a/src/types/activity.ts +++ b/src/types/activity.ts @@ -18,6 +18,4 @@ export enum ActivityType { Listening, /** Example: ":smiley: I am cool" */ Custom = 4, - /** Example: "Competing in Arena World Champions" */ - Competing } From 2b618b1cb8438af950968b75352f84acc217eab6 Mon Sep 17 00:00:00 2001 From: chroventer Date: Sun, 25 Oct 2020 10:07:19 +0400 Subject: [PATCH 022/123] Add "Competing" to ActivityType (#142) * Add "Competing" to ActivityType * Add trailing comma --- src/types/activity.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types/activity.ts b/src/types/activity.ts index 81a180b4b..0299625ff 100644 --- a/src/types/activity.ts +++ b/src/types/activity.ts @@ -18,4 +18,6 @@ export enum ActivityType { Listening, /** Example: ":smiley: I am cool" */ Custom = 4, + /** Example: "Competing in Arena World Champions" */ + Competing, } From 1c65db528f6edaa06adbe57cd47ed8e637895c1f Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 26 Oct 2020 11:40:35 -0400 Subject: [PATCH 023/123] slight fix for deleted roles without members inten --- src/controllers/roles.ts | 5 +++++ src/utils/permissions.ts | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/controllers/roles.ts b/src/controllers/roles.ts index 9f889d23b..a1b4586d0 100644 --- a/src/controllers/roles.ts +++ b/src/controllers/roles.ts @@ -30,6 +30,11 @@ export async function handleInternalGuildRoleDelete(data: DiscordPayload) { const cachedRole = guild.roles.get(payload.role_id)!; guild.roles.delete(payload.role_id); eventHandlers.roleDelete?.(guild, cachedRole); + + // For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking. + guild.members.forEach(member => { + member.roles = member.roles.filter(id => id !== payload.role_id); + }); } export async function handleInternalGuildRoleUpdate(data: DiscordPayload) { diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 013c1c56c..049a62089 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -58,6 +58,8 @@ export async function botHasPermission( const permissionBits = member.roles .map((id) => guild.roles.get(id)!) + // Remove any edge case undefined + .filter((r) => r) .reduce((bits, data) => { bits |= BigInt(data.permissions); From f58683b55f6b35eb222300739122220e19b5e89a Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 26 Oct 2020 11:41:55 -0400 Subject: [PATCH 024/123] eggs --- egg.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egg.yml b/egg.yml index 86ddea0a7..408443064 100644 --- a/egg.yml +++ b/egg.yml @@ -2,7 +2,7 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.4 +version: 9.0.5 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' From 92a3e7aab0a7445306dc1acf786baeeea6db942c Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 09:13:32 -0700 Subject: [PATCH 025/123] Remove new lines in between import variables --- .vscode/settings.json | 1 - tests/mod.test.ts | 9 --------- 2 files changed, 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f50a9228a..f5003566b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,6 @@ { "deno.enable": true, "editor.formatOnSave": true, - "editor.formatOnSaveMode": "modifications", "deno.import_intellisense_origins": { "https://deno.land": true }, diff --git a/tests/mod.test.ts b/tests/mod.test.ts index e543769ea..df782a719 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,30 +1,21 @@ import { assert, assertArrayContains, assertEquals, delay } from "../deps.ts"; import { botID, - cache, Channel, createClient, - createGuildChannel, createGuildRole, - createServer, deleteChannel, - deleteRole, - deleteServer, editRole, - getMessage, - Guild, Intents, - OverwriteType, Role, - sendMessage, } from "../mod.ts"; import { editChannel } from "../src/handlers/channel.ts"; From 711adfbeb826b7a7e1db86472e4fdaabad0ea5de Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 09:14:30 -0700 Subject: [PATCH 026/123] Add a TODO note --- tests/mod.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index df782a719..cbedc4a69 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -21,6 +21,7 @@ import { import { editChannel } from "../src/handlers/channel.ts"; import { getChannel } from "../src/handlers/guild.ts"; +// TODO: add DISCORD_TOKEN variable to GitHub secrets const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "Token is not provided"; From e17801ee6fed1219ac73986d21ae95d0d06604e9 Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 09:18:14 -0700 Subject: [PATCH 027/123] Assign guildID, roleID, channelID to an object --- tests/mod.test.ts | 53 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index cbedc4a69..015378744 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -48,7 +48,11 @@ Deno.test({ ...testOptions, }); -let guildID: string; +const data = { + guildID: "", + roleID: "", + channelID: "", +}; Deno.test({ name: "create a guild", @@ -61,26 +65,25 @@ Deno.test({ // Check whether createdGuild is nil or not assert(createdGuild); - guildID = createdGuild.id; + data.guildID = createdGuild.id; }, ...testOptions, }); // Role -let roleID: string; Deno.test({ name: "create a role in a guild", async fn() { // Create a role "Role 1" in the guild "Discordeno Test" - const createdRole = await createGuildRole(guildID, { + const createdRole = await createGuildRole(data.guildID, { name: "Role 1", }); // Check whether the created role is nil or not assert(createdRole); - roleID = createdRole.id; + data.roleID = createdRole.id; }, ...testOptions, }); @@ -89,7 +92,7 @@ Deno.test({ name: "edit a role in a guild", async fn() { // Edit a role "Role 1" in the guild "Discordeno Test" - const editedRole = (await editRole(guildID, roleID, { + const editedRole = (await editRole(data.guildID, data.roleID, { name: "Edited Role", color: 4320244, hoist: false, @@ -103,26 +106,24 @@ Deno.test({ assertEquals(editedRole.hoist, false); assertEquals(editedRole.mentionable, false); - roleID = editedRole.id; + data.roleID = editedRole.id; }, ...testOptions, }); // Channel -let channelID: string; - Deno.test({ name: "create a channel in a guild", async fn() { - const guild = cache.guilds.get(guildID); + const guild = cache.guilds.get(data.guildID); if (!guild) throw "Guild not found"; const createdChannel = await createGuildChannel(guild, "test"); // Check whether the created channel is nil or not assert(createdChannel); - channelID = createdChannel.id; + data.channelID = createdChannel.id; }, ...testOptions, }); @@ -130,9 +131,9 @@ Deno.test({ Deno.test({ name: "get a channel in a guild", async fn() { - const channel = await getChannel(channelID); + const channel = await getChannel(data.channelID); - assertEquals(channel.id, channelID); + assertEquals(channel.id, data.channelID); }, ...testOptions, }); @@ -140,24 +141,24 @@ Deno.test({ Deno.test({ name: "edit a channel in a guild", async fn() { - const channel = await editChannel(channelID, { + const channel = await editChannel(data.channelID, { name: "edited channel", }) as Channel; assert(channel); - channelID = channel.id; + data.channelID = channel.id; }, }); Deno.test({ name: "channel overwrite has permission", async fn() { - const channel = cache.channels.get(channelID); + const channel = cache.channels.get(data.channelID); if (!channel) throw "Channel not found"; assertArrayContains(channel.permission_overwrites!, [ { - id: roleID, + id: data.roleID, type: OverwriteType.ROLE, // The type for Channel#permission_overwrites is "RawOverwrite[] | undefined" // not "Overwrite[]"; therefore, permission strings cannot be used. @@ -180,7 +181,7 @@ let messageID: string; Deno.test({ name: "create a message in a guild", async fn() { - const createdMessage = await sendMessage(channelID, "test"); + const createdMessage = await sendMessage(data.channelID, "test"); // Check whether the created message is nil or not assert(createdMessage); @@ -192,7 +193,7 @@ Deno.test({ Deno.test({ name: "get a message in a guild", async fn() { - const message = await getMessage(channelID, messageID); + const message = await getMessage(data.channelID, messageID); assertEquals(messageID, message.id); }, @@ -203,16 +204,16 @@ Deno.test({ Deno.test({ name: "delete a role from the guild", async fn() { - await deleteRole(guildID, roleID); - roleID = ""; - assertEquals(roleID, ""); + await deleteRole(data.guildID, data.roleID); + data.roleID = ""; + assertEquals(data.roleID, ""); }, }); Deno.test({ name: "delete a channel in the guild", async fn() { - await deleteChannel(guildID, channelID); + await deleteChannel(data.guildID, data.channelID); }, ...testOptions, }); @@ -220,9 +221,9 @@ Deno.test({ Deno.test({ name: "delete a guild", async fn() { - await deleteServer(guildID); - guildID = ""; - assertEquals(guildID, ""); + await deleteServer(data.guildID); + data.guildID = ""; + assertEquals(data.guildID, ""); }, ...testOptions, }); From 3d26bcab88f5d01fbf782ae89a448fad0df87d41 Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 09:23:28 -0700 Subject: [PATCH 028/123] Add GitHub badge for test workflow --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 662026ec3..1011bc643 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,7 @@ Alternatively, you can use boilerplate template repositories that were created b #### Dark Mode ![image](https://i.imgur.com/Vr2Bebr.png) + +### Tests + +![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg) \ No newline at end of file From 0652f0fbf2a33cb30797ddacd671e8cdb6d3f727 Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 09:57:25 -0700 Subject: [PATCH 029/123] Format source files --- src/controllers/roles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/roles.ts b/src/controllers/roles.ts index a1b4586d0..919499a4a 100644 --- a/src/controllers/roles.ts +++ b/src/controllers/roles.ts @@ -32,8 +32,8 @@ export async function handleInternalGuildRoleDelete(data: DiscordPayload) { eventHandlers.roleDelete?.(guild, cachedRole); // For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking. - guild.members.forEach(member => { - member.roles = member.roles.filter(id => id !== payload.role_id); + guild.members.forEach((member) => { + member.roles = member.roles.filter((id) => id !== payload.role_id); }); } From 4abcc5b723ab1aa64b8974fc72473efebf42cc46 Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 10:41:09 -0700 Subject: [PATCH 030/123] Add missing activity types --- src/types/activity.ts | 50 ++++++++++++++++++++++++++++++++++++++++--- src/types/discord.ts | 5 ----- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/types/activity.ts b/src/types/activity.ts index 0299625ff..cc8110d87 100644 --- a/src/types/activity.ts +++ b/src/types/activity.ts @@ -1,12 +1,18 @@ -import type { Timestamps } from "./discord.ts"; - export interface ActivityPayload { name: string; type: number; url?: string; created_at: number; - timestamps: Timestamps; + timestamps?: ActivityTimestamps; + application_id?: string; details?: string; + state?: string; + emoji?: ActivityEmoji; + party?: ActivityParty; + assets?: ActivityAssets; + secrets?: ActivitySecrets; + instance?: boolean; + flags?: number; } export enum ActivityType { @@ -21,3 +27,41 @@ export enum ActivityType { /** Example: "Competing in Arena World Champions" */ Competing, } + +export interface ActivityTimestamps { + start?: number; + end?: number; +} + +export interface ActivityEmoji { + name: string; + id?: string; + animated?: boolean; +} + +export interface ActivityParty { + id?: string; + size?: [number, number]; +} + +export interface ActivityAssets { + large_image?: string; + large_text?: string; + small_image?: string; + small_text?: string; +} + +export interface ActivitySecrets { + join?: string; + spectate?: string; + match?: string; +} + +export enum ActivityFlags { + INSTANCE = 1 << 0, + JOIN = 1 << 1, + SPECTATE = 1 << 2, + JOIN_REQUEST = 1 << 3, + SYNC = 1 << 4, + PLAY = 1 << 5, +} diff --git a/src/types/discord.ts b/src/types/discord.ts index 161c15b59..58e08b343 100644 --- a/src/types/discord.ts +++ b/src/types/discord.ts @@ -196,11 +196,6 @@ export interface Properties { $device: string; } -export interface Timestamps { - start?: number; - end?: number; -} - export interface Emoji { name: string; id?: string; From 5480b8711d19129071757664081f8028ce4fad6a Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 22:39:37 -0700 Subject: [PATCH 031/123] Check if channel is not undefined Closes #144 --- src/utils/permissions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 049a62089..4c5ec8dd5 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -86,7 +86,8 @@ export async function hasChannelPermissions( permissions: Permissions[], ) { const channel = await cacheHandlers.get("channels", channelID); - if (!channel?.guildID) return true; + if (!channel) return false; + if (!channel.guildID) return true; const guild = await cacheHandlers.get("guilds", channel.guildID); if (!guild) return false; From e0d79901a7a9a9316e418df6a70a9865f57cc1bb Mon Sep 17 00:00:00 2001 From: chroventer Date: Mon, 26 Oct 2020 22:50:41 -0700 Subject: [PATCH 032/123] Remove "Greetings" GitHub action --- .github/workflows/greetings.yml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .github/workflows/greetings.yml diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml deleted file mode 100644 index d65aeb3b4..000000000 --- a/.github/workflows/greetings.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Greetings - -on: [pull_request, issues] - -jobs: - greeting: - runs-on: ubuntu-latest - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-message: "Thank you for helping contribute to Discordeno. I really do appreciate any and all contributions! Hopefully, together we will be able to make the very best bot Discord API module in the world. Since, this is your very first issue, feel free to look around the repository and then hop on into the Discord server, where you can chat with me directly. https://discord.gg/J4NqJ72" - pr-message: "Thank you for helping contribute to Discordeno. I really do appreciate any and all contributions! Hopefully, together we will be able to make the very best Discord API module in the world. Since, this is your very first pull request, feel free to look around the repository and then hop on into the Discord server, where you can chat with me directly. https://discord.gg/J4NqJ72" From a90c8b217f4bb5151aef1d6a7c54a394bb6bab4d Mon Sep 17 00:00:00 2001 From: ayyanm Date: Tue, 27 Oct 2020 01:53:03 -0700 Subject: [PATCH 033/123] Replace nest.land large badge with smaller --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d12951fa..f264aa07d 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=white)](https://discord.gg/J4NqJ72) ![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) -[![nest.land](https://nest.land/badge-large.svg)](https://nest.land/package/Discordeno) - +[![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) [Website](https://discordeno.netlify.app) ## Beginner Developers From dac90535f220c9e9ba4c5572279289745c5b5e53 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Tue, 27 Oct 2020 01:56:28 -0700 Subject: [PATCH 034/123] Remove Website link --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index f264aa07d..d9793b368 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=white)](https://discord.gg/J4NqJ72) ![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) -[Website](https://discordeno.netlify.app) ## Beginner Developers From 3ca1d757262ff05dcc7e9c86319f12edec7052e5 Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 07:33:15 -0400 Subject: [PATCH 035/123] check channel type before sendmessage --- egg.yml | 4 ++-- src/handlers/channel.ts | 8 +++++++- src/types/errors.ts | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/egg.yml b/egg.yml index 408443064..49ec7a825 100644 --- a/egg.yml +++ b/egg.yml @@ -2,16 +2,16 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.5 +version: 9.0.7 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' files: - ./src/**/* - LICENSE - - mod.ts - README.md - tsconfig.json - ./deps.ts + - mod.ts checkAll: false unlisted: false diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 881521ea0..1e82245b8 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -1,8 +1,10 @@ import { endpoints } from "../constants/discord.ts"; +import { cacheHandlers } from "../controllers/cache.ts"; import { RequestManager } from "../module/requestManager.ts"; import { structures } from "../structures/mod.ts"; -import type { +import { ChannelEditOptions, + ChannelTypes, CreateInviteOptions, FollowedChannelPayload, GetMessages, @@ -160,6 +162,10 @@ export async function sendMessage( } } + const channel = await cacheHandlers.get("channels", channelID); + if (!channel) throw new Error(Errors.CHANNEL_NOT_FOUND); + if (![ChannelTypes.DM, ChannelTypes.GUILD_NEWS, ChannelTypes.GUILD_TEXT].includes(channel.type)) throw new Error(Errors.CHANNEL_NOT_TEXT_BASED) + const result = await RequestManager.post( endpoints.CHANNEL_MESSAGES(channelID), { diff --git a/src/types/errors.ts b/src/types/errors.ts index da321ff35..98df112d2 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -31,4 +31,6 @@ export enum Errors { CHANNEL_NOT_IN_GUILD = "CHANNEL_NOT_IN_GUILD", INVALID_WEBHOOK_NAME = "INVALID_WEBHOOK_NAME", INVALID_WEBHOOK_OPTIONS = "INVALID_WEBHOOK_OPTIONS", + CHANNEL_NOT_FOUND = "CHANNEL_NOT_FOUND", + CHANNEL_NOT_TEXT_BASED = "CHANNEL_NOT_TEXT_BASED", } From 77246cbc78464f8f57d900e6cc41d516bf434880 Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 07:41:20 -0400 Subject: [PATCH 036/123] forgot to commit --- src/module/requestManager.ts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index 8d37a14fb..c74abe25c 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -286,6 +286,23 @@ async function runMethod( }); } +async function logErrors(response: Response, errorStack?: unknown) { + try { + const error = await response.json(); + console.error(error); + + eventHandlers.debug?.({ type: "error", data: { errorStack, error } }); + } catch { + eventHandlers.debug?.( + { + type: "error", + data: { errorStack }, + }, + ); + console.error(response); + } +} + function handleStatusCode(response: Response, errorStack?: unknown) { const status = response.status; @@ -296,13 +313,7 @@ function handleStatusCode(response: Response, errorStack?: unknown) { return true; } - eventHandlers.debug?.( - { - type: "error", - data: { errorStack }, - }, - ); - console.error(response); + logErrors(response, errorStack); switch (status) { case HttpResponseCode.BadRequest: From 09d8b478f6d01aea37501f780fc02134aef9150f Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 09:06:45 -0400 Subject: [PATCH 037/123] move to v8 gateway --- src/module/basicShard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index 60717ca3c..68b9196ff 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -51,7 +51,7 @@ export async function createBasicShard( const basicShard: BasicShard = { id: shardID, - socket: await connectWebSocket(`${data.url}?v=6&encoding=json`), + socket: await connectWebSocket(`${data.url}?v=8&encoding=json`), resumeInterval: 0, sessionID: oldShard?.sessionID || "", previousSequenceNumber: oldShard?.previousSequenceNumber || 0, From 2522e14dbdd521a5f25291ab4601d4883c61e4ee Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 11:49:12 -0400 Subject: [PATCH 038/123] fix perm bug --- egg.yml | 2 +- src/utils/permissions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/egg.yml b/egg.yml index 49ec7a825..c679a2ee5 100644 --- a/egg.yml +++ b/egg.yml @@ -2,7 +2,7 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.7 +version: 9.0.10 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 4c5ec8dd5..e1d9eb55b 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -93,7 +93,7 @@ export async function hasChannelPermissions( if (!guild) return false; if (guild.ownerID === memberID) return true; - if (botHasPermission(guild.id, [Permissions.ADMINISTRATOR])) return true; + if (await memberIDHasPermission(memberID, guild.id, ["ADMINISTRATOR"])) return true; const member = guild.members.get(memberID); if (!member) return false; From b01c96df6a59b3245ecdb70067917923a4c97bee Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 12:55:03 -0400 Subject: [PATCH 039/123] damm u --- src/utils/permissions.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index e1d9eb55b..6de579299 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -34,6 +34,8 @@ export function memberHasPermission( const permissionBits = memberRoleIDs.map((id) => guild.roles.get(id)?.permissions ) + // Removes any edge case undefined + .filter((id) => id) .reduce((bits, permissions) => { bits |= BigInt(permissions); return bits; @@ -93,7 +95,11 @@ export async function hasChannelPermissions( if (!guild) return false; if (guild.ownerID === memberID) return true; - if (await memberIDHasPermission(memberID, guild.id, ["ADMINISTRATOR"])) return true; + if ( + await memberIDHasPermission(memberID, guild.id, ["ADMINISTRATOR"]) + ) { + return true; + } const member = guild.members.get(memberID); if (!member) return false; From b65c31dcb2cae33e6fde394e3c83e2c7e502e58d Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 12:58:27 -0400 Subject: [PATCH 040/123] fmt --- egg.yml | 2 +- src/handlers/channel.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/egg.yml b/egg.yml index c679a2ee5..3af7f3b38 100644 --- a/egg.yml +++ b/egg.yml @@ -2,7 +2,7 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.10 +version: 9.0.12 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 1e82245b8..0e2580996 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -164,7 +164,12 @@ export async function sendMessage( const channel = await cacheHandlers.get("channels", channelID); if (!channel) throw new Error(Errors.CHANNEL_NOT_FOUND); - if (![ChannelTypes.DM, ChannelTypes.GUILD_NEWS, ChannelTypes.GUILD_TEXT].includes(channel.type)) throw new Error(Errors.CHANNEL_NOT_TEXT_BASED) + if ( + ![ChannelTypes.DM, ChannelTypes.GUILD_NEWS, ChannelTypes.GUILD_TEXT] + .includes(channel.type) + ) { + throw new Error(Errors.CHANNEL_NOT_TEXT_BASED); + } const result = await RequestManager.post( endpoints.CHANNEL_MESSAGES(channelID), From 2908a20ae44f2e753feb24e4a6400515f2d8911d Mon Sep 17 00:00:00 2001 From: ayyanm Date: Tue, 27 Oct 2020 11:14:55 -0700 Subject: [PATCH 041/123] Better wording, segregate into sections, more readable --- README.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d9793b368..73411f7bc 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,17 @@ > Discord API library wrapper in Deno -[![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=white)](https://discord.gg/J4NqJ72) +[![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=dark)](https://discord.gg/J4NqJ72) ![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) -## Beginner Developers +## Why Discordeno? -Don't worry a lot of developers start out coding their first projects as a Discord bot(I did 😉) and it is not so easy. With Discordeno, I tried to build it in a way that solved all the headaches I had when first starting out coding bots. If you are a beginner developer, please use a boilerplate: The official one is at: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! +### Beginner Developers + +Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots. + +If you are a beginner developer, please use this official boilerplate: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! **Modular commands, arguments, events, inhibitors, monitors, tasks.** @@ -39,15 +43,10 @@ Don't worry a lot of developers start out coding their first projects as a Disco - Uses i18next, one of the best localization tools available. - Supports nested folders to keep cleaner translation files -**Hot Reloadable** +- **Hot Reloadable**: Easily update your code without having to restart the bot everytime. +- **Step By Step Guide**: There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website! -- Easily update your code without having to restart the bot everytime. - -**Step By Step Guide** - -- There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website! - -## Advanced Developers +### Advanced Developers The instructions below are meant for advanced developers! @@ -62,7 +61,7 @@ StartBot({ intents: [Intents.GUILD_MESSAGES, Intents.GUILDS], eventHandlers: { ready: () => { - console.log(`Logged!`); + console.log('Successfully connected to gateway'); }, messageCreate: (message) => { if (message.content === "!ping") { @@ -75,8 +74,13 @@ StartBot({ Alternatively, you can use boilerplate template repositories that were created by wonderful developers. Review the list on the website, and add any of yours if you make your own. -![image](https://i.imgur.com/z1BfUnt.png) +## Documentation -#### Dark Mode +- [API Documentation](https://doc.deno.land/https/deno.land/x/discordeno/mod.ts) +- [Guide](https://discordeno.netlify.com) +- [Support server](https://discord.gg/J4NqJ72) +- [Contributing Guide](https://github.com/Skillz4Killz/Discordeno/blob/master/.github/CONTRIBUTING.md) -![image](https://i.imgur.com/Vr2Bebr.png) +## License + +MIT © Skillz4Killz From d1210dae9d958c9cbe396c837d2dfdb499dd87b4 Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 27 Oct 2020 15:55:58 -0400 Subject: [PATCH 042/123] role update cached --- src/controllers/roles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controllers/roles.ts b/src/controllers/roles.ts index 919499a4a..62cf72eb1 100644 --- a/src/controllers/roles.ts +++ b/src/controllers/roles.ts @@ -48,5 +48,6 @@ export async function handleInternalGuildRoleUpdate(data: DiscordPayload) { if (!cachedRole) return; const role = await structures.createRole(payload.role); + guild.roles.set(payload.role.id, role); eventHandlers.roleUpdate?.(guild, role, cachedRole); } From f93cd5e8f49eb17dea92f153c7fe59e83a7c533c Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 09:24:13 -0700 Subject: [PATCH 043/123] Specify the std/testing/asserts.ts version in deps.ts --- deps.ts | 10 +++++----- tests/mod.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/deps.ts b/deps.ts index 8e07e8ced..ddc71fbf2 100644 --- a/deps.ts +++ b/deps.ts @@ -1,8 +1,3 @@ -export { - assert, - assertArrayContains, - assertEquals, -} from "https://deno.land/std/testing/asserts.ts"; export { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; export { encode } from "https://deno.land/std@0.67.0/encoding/base64.ts"; export { @@ -12,4 +7,9 @@ export { isWebSocketPongEvent, } from "https://deno.land/std@0.67.0/ws/mod.ts"; export type { WebSocket } from "https://deno.land/std@0.67.0/ws/mod.ts"; +export { + assert, + assertArrayIncludes, + assertEquals, +} from "https://deno.land/std@0.75.0/testing/asserts.ts"; export { decompress_with as inflate } from "https://unpkg.com/@evan/wasm@0.0.11/target/zlib/deno.js"; diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 015378744..bfa3169e7 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,4 +1,4 @@ -import { assert, assertArrayContains, assertEquals, delay } from "../deps.ts"; +import { assert, assertArrayIncludes, assertEquals, delay } from "../deps.ts"; import { botID, cache, @@ -156,7 +156,7 @@ Deno.test({ async fn() { const channel = cache.channels.get(data.channelID); if (!channel) throw "Channel not found"; - assertArrayContains(channel.permission_overwrites!, [ + assertArrayIncludes(channel.permission_overwrites!, [ { id: data.roleID, type: OverwriteType.ROLE, From dc3ead67a6de6e32fe229c5780f92d47051b756e Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 11:12:03 -0700 Subject: [PATCH 044/123] Remove "deno cache tests/mod.test.ts" from workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9cc5554c9..1c1a717b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,6 @@ jobs: - uses: actions/checkout@v2 - uses: denolib/setup-deno@master - name: Cache dependencies - run: deno cache mod.ts test/mod.test.ts + run: deno cache mod.ts - name: Run test script run: deno test -A \ No newline at end of file From af42f0e1b9109fd63c9a3aae5e1bfe77d8f5bfd9 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 11:13:14 -0700 Subject: [PATCH 045/123] Change "on" to push temporarily --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1c1a717b5..40a131de7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,8 @@ name: Test -on: - push: - branches: - - master +on: [push] +# push: +# branches: +# - master jobs: test: runs-on: ubuntu-latest From 167fe1ca77930413f9b4a40128a7961f85c12e73 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 11:14:38 -0700 Subject: [PATCH 046/123] Revert "Change "on" to push temporarily" --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40a131de7..29fcb6ce4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,8 @@ name: Test -on: [push] -# push: -# branches: -# - master +on: + push: + branches: + - master jobs: test: runs-on: ubuntu-latest From 3f6a5f101e16d8ada0507e44aa332d86542f5beb Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 11:29:36 -0700 Subject: [PATCH 047/123] Add DISCORD_TOKEN env variable to test workflow --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29fcb6ce4..159b4f247 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,4 +12,6 @@ jobs: - name: Cache dependencies run: deno cache mod.ts - name: Run test script - run: deno test -A \ No newline at end of file + run: deno test -A + env: + DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} \ No newline at end of file From 382f445efdb507ca748518c4398894cfe98e1720 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 12:16:54 -0700 Subject: [PATCH 048/123] Remove redundant type cast --- src/utils/cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 3bb3c8d26..aec07ede7 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -21,5 +21,5 @@ export const cache: CacheData = { messages: new Collection(), unavailableGuilds: new Collection(), presences: new Collection(), - fetchAllMembersProcessingRequests: new Collection(), + fetchAllMembersProcessingRequests: new Collection(), }; From c0065abd27fe739fc38357753d0bb6770a1e4bff Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 28 Oct 2020 15:19:19 -0400 Subject: [PATCH 049/123] rework permission test --- src/utils/permissions.ts | 117 ++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 6de579299..bce60a360 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -2,6 +2,7 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import type { Guild } from "../structures/guild.ts"; import type { Role } from "../structures/role.ts"; +import { RawOverwrite } from "../types/guild.ts"; import type { Permission } from "../types/permission.ts"; import { Permissions } from "../types/permission.ts"; @@ -104,87 +105,77 @@ export async function hasChannelPermissions( const member = guild.members.get(memberID); if (!member) return false; - const memberOverwrite = channel.permission_overwrites?.find((o) => - o.id === memberID - ); + let memberOverwrite: RawOverwrite | undefined = undefined; + let everyoneOverwrite: RawOverwrite | undefined = undefined; + let rolesOverwrites: RawOverwrite[] = []; - const rolesOverwrites = channel.permission_overwrites?.filter((o) => - member.roles.includes(o.id) - ); - - const everyoneOverwrite = channel.permission_overwrites?.find((o) => - o.id === guild.id - ); + for (const overwrite of channel.permission_overwrites || []) { + // If the overwrite on this channel is specific to this member + if (overwrite.id === memberID) memberOverwrite = overwrite; + // If it is the everyone role overwrite + if (overwrite.id === guild.id) everyoneOverwrite = overwrite; + // If it is one of the roles the member has + if (member.roles.includes(overwrite.id)) rolesOverwrites.push(overwrite); + } const allowedPermissions = new Set(); + // Member perms override everything so we must check them first if (memberOverwrite) { - // One of the necessary permissions is denied - if ( - permissions.some((perm) => BigInt(memberOverwrite.deny) & BigInt(perm)) - ) { - return false; - } - permissions.forEach((perm) => { + for (const perm of permissions) { + // One of the necessary permissions is denied. Since this is main permission we can cancel if its denied. + if (BigInt(memberOverwrite.deny) & BigInt(perm)) return false; // Already allowed perm - if (allowedPermissions.has(perm)) return; + if (allowedPermissions.has(perm)) continue; // This perm is allowed so we save it if (BigInt(memberOverwrite.allow) & BigInt(perm)) { allowedPermissions.add(perm); } - }); + } } // Check the necessary permissions for roles - if (rolesOverwrites?.length) { - if ( - rolesOverwrites.some((overwrite) => - permissions.some((perm) => - (BigInt(overwrite.deny) & BigInt(perm)) && - // If another role allows these perms then they are not denied - !rolesOverwrites.some((o) => BigInt(o.allow) & BigInt(perm)) && - // Make sure the memberOverwrite does not allow this perm - !(memberOverwrite && BigInt(memberOverwrite.allow) & BigInt(perm)) - ) - ) - ) { - return false; - } + for (const perm of permissions) { + // If this is already allowed, skip + if (allowedPermissions.has(perm)) continue; - permissions.forEach((perm) => { + for (const overwrite of rolesOverwrites) { + // This perm is allowed so we save it + if (BigInt(overwrite.allow) & BigInt(perm)) { + allowedPermissions.add(perm); + break; + } + + // If this role denies it we need to save and check if another role allows it, allows > deny + if (BigInt(overwrite.deny) & BigInt(perm)) { + // This role denies his perm, but before denying we need to check all other roles if any allow as allow > deny + const isAllowed = rolesOverwrites.some((o) => + BigInt(o.allow) & BigInt(perm) + ); + if (isAllowed) continue; + // This permission is in fact denied. Since Roles overrule everything below here we can cancel ou here + return false; + } + } + } + + if (everyoneOverwrite) { + for (const perm of permissions) { // Already allowed perm - if (allowedPermissions.has(perm)) return; - rolesOverwrites.forEach((overwrite) => { - // This perm is allowed so we save it - if (BigInt(overwrite.allow) & BigInt(perm)) { - allowedPermissions.add(perm); - } - }); - }); - } - - // Check the necessary permissions for everyone - if ( - everyoneOverwrite - ) { - if ( - permissions.some((perm) => - BigInt(everyoneOverwrite.deny) & BigInt(perm) && - !allowedPermissions.has(perm) - ) - ) { - return false; - } - // If all permissions are granted - if ( - permissions.every((perm) => - BigInt(everyoneOverwrite.allow) & BigInt(perm) - ) - ) { - return true; + if (allowedPermissions.has(perm)) continue; + // One of the necessary permissions is denied. Since everyone overwrite overrides role perms we can cancel here + if (BigInt(everyoneOverwrite.deny) & BigInt(perm)) return false; + // This perm is allowed so we save it + if (BigInt(everyoneOverwrite.allow) & BigInt(perm)) { + allowedPermissions.add(perm); + } } } + // Is there any remaining permission to check role perms or can we determine that permissions are allowed + if (permissions.every((perm) => allowedPermissions.has(perm))) return true; + + // Some permission was not explicitly allowed so we default to checking role perms directly return botHasPermission(guild.id, permissions); } From f16ba600cff03f1a6212c9e46e06f6d8a6042938 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 28 Oct 2020 15:35:44 -0400 Subject: [PATCH 050/123] use import type --- src/utils/permissions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index bce60a360..62d431bed 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -2,9 +2,9 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import type { Guild } from "../structures/guild.ts"; import type { Role } from "../structures/role.ts"; -import { RawOverwrite } from "../types/guild.ts"; +import type { RawOverwrite } from "../types/guild.ts"; import type { Permission } from "../types/permission.ts"; -import { Permissions } from "../types/permission.ts"; +import type { Permissions } from "../types/permission.ts"; /** Checks if the member has this permission. If the member is an owner or has admin perms it will always be true. */ export async function memberIDHasPermission( From e4f309d0ef1811236565bc1c106421fb6121bb61 Mon Sep 17 00:00:00 2001 From: ayntee Date: Wed, 28 Oct 2020 12:40:24 -0700 Subject: [PATCH 051/123] Update permissions.ts --- src/utils/permissions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 62d431bed..59a26870f 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -4,7 +4,7 @@ import type { Guild } from "../structures/guild.ts"; import type { Role } from "../structures/role.ts"; import type { RawOverwrite } from "../types/guild.ts"; import type { Permission } from "../types/permission.ts"; -import type { Permissions } from "../types/permission.ts"; +import { Permissions } from "../types/permission.ts"; /** Checks if the member has this permission. If the member is an owner or has admin perms it will always be true. */ export async function memberIDHasPermission( From 940ae760d29e79a6b1aff1130a45424b040434e3 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 28 Oct 2020 15:43:07 -0400 Subject: [PATCH 052/123] remove undef --- src/utils/permissions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 62d431bed..f17b8c6f6 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -4,7 +4,7 @@ import type { Guild } from "../structures/guild.ts"; import type { Role } from "../structures/role.ts"; import type { RawOverwrite } from "../types/guild.ts"; import type { Permission } from "../types/permission.ts"; -import type { Permissions } from "../types/permission.ts"; +import { Permissions } from "../types/permission.ts"; /** Checks if the member has this permission. If the member is an owner or has admin perms it will always be true. */ export async function memberIDHasPermission( @@ -105,8 +105,8 @@ export async function hasChannelPermissions( const member = guild.members.get(memberID); if (!member) return false; - let memberOverwrite: RawOverwrite | undefined = undefined; - let everyoneOverwrite: RawOverwrite | undefined = undefined; + let memberOverwrite: RawOverwrite | undefined; + let everyoneOverwrite: RawOverwrite | undefined; let rolesOverwrites: RawOverwrite[] = []; for (const overwrite of channel.permission_overwrites || []) { From 10f67b090ac09efdb6fb519770341bc4f35eb238 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Wed, 28 Oct 2020 12:52:33 -0700 Subject: [PATCH 053/123] Replace all occurrences of "import type" syntax to "import" syntax --- docs/content/djs.md | 8 ++++---- src/controllers/bans.ts | 4 ++-- src/controllers/cache.ts | 10 +++++----- src/controllers/channels.ts | 5 ++--- src/controllers/guilds.ts | 6 +++--- src/controllers/members.ts | 4 ++-- src/controllers/messages.ts | 4 ++-- src/controllers/misc.ts | 4 ++-- src/controllers/reactions.ts | 4 ++-- src/controllers/roles.ts | 7 ++----- src/handlers/channel.ts | 4 ++-- src/handlers/guild.ts | 12 ++++++------ src/handlers/member.ts | 11 ++++------- src/handlers/message.ts | 8 ++++---- src/handlers/webhook.ts | 4 ++-- src/module/basicShard.ts | 11 +++++------ src/module/client.ts | 4 ++-- src/module/requestManager.ts | 2 +- src/module/shard.ts | 16 ++++++++++------ src/module/shardingManager.ts | 18 +++++++++++------- src/structures/channel.ts | 4 ++-- src/structures/guild.ts | 6 +++--- src/structures/member.ts | 4 ++-- src/structures/message.ts | 4 ++-- src/structures/role.ts | 4 ++-- src/types/channel.ts | 4 ++-- src/types/discord.ts | 8 ++++---- src/types/guild.ts | 14 +++++++------- src/types/member.ts | 2 +- src/types/message.ts | 8 ++++---- src/types/options.ts | 16 ++++++++-------- src/types/presence.ts | 2 +- src/types/webhook.ts | 4 ++-- src/utils/cache.ts | 8 ++++---- src/utils/cdn.ts | 2 +- src/utils/permissions.ts | 7 +++---- src/utils/utils.ts | 2 +- 37 files changed, 122 insertions(+), 123 deletions(-) diff --git a/docs/content/djs.md b/docs/content/djs.md index 593d00b55..afc0465a9 100644 --- a/docs/content/djs.md +++ b/docs/content/djs.md @@ -110,9 +110,9 @@ import Client, { import { configs } from "./configs.ts"; import { Intents } from "https://x.nest.land/Discordeno@9.0.1/src/types/options.ts"; import { eventHandlers } from "./src/events/eventHandlers.ts"; -import type { Message } from "https://x.nest.land/Discordeno@9.0.1/src/structures/message.ts"; -import type { Command } from "./src/types/commands.ts"; -import type { Guild } from "https://x.nest.land/Discordeno@9.0.1/src/structures/guild.ts"; +import { Message } from "https://x.nest.land/Discordeno@9.0.1/src/structures/message.ts"; +import { Command } from "./src/types/commands.ts"; +import { Guild } from "https://x.nest.land/Discordeno@9.0.1/src/structures/guild.ts"; export const botCache = { commands: new Map(), @@ -346,7 +346,7 @@ module.exports = class kickCommand extends Command { Discordeno Version ```ts import { sendMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/channel.ts"; -import type { Member } from "https://x.nest.land/Discordeno@9.0.1/src/structures/member.ts"; +import { Member } from "https://x.nest.land/Discordeno@9.0.1/src/structures/member.ts"; import { kick } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/member.ts"; import { deleteMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/message.ts"; import { botCache } from "../../mod.ts"; diff --git a/src/controllers/bans.ts b/src/controllers/bans.ts index dbd4cf10c..fca5c7f6f 100644 --- a/src/controllers/bans.ts +++ b/src/controllers/bans.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../module/client.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { GuildBanPayload } from "../types/guild.ts"; +import { DiscordPayload } from "../types/discord.ts"; +import { GuildBanPayload } from "../types/guild.ts"; import { cacheHandlers } from "./cache.ts"; export async function handleInternalGuildBanAdd(data: DiscordPayload) { diff --git a/src/controllers/cache.ts b/src/controllers/cache.ts index 676d45534..55829c14a 100644 --- a/src/controllers/cache.ts +++ b/src/controllers/cache.ts @@ -1,9 +1,9 @@ -import type { Channel } from "../structures/channel.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { Message } from "../structures/message.ts"; -import type { PresenceUpdatePayload } from "../types/discord.ts"; +import { Channel } from "../structures/channel.ts"; +import { Guild } from "../structures/guild.ts"; +import { Message } from "../structures/message.ts"; +import { PresenceUpdatePayload } from "../types/discord.ts"; import { cache } from "../utils/cache.ts"; -import type { Collection } from "../utils/collection.ts"; +import { Collection } from "../utils/collection.ts"; export type TableName = | "guilds" diff --git a/src/controllers/channels.ts b/src/controllers/channels.ts index 36d78c576..1812e6c20 100644 --- a/src/controllers/channels.ts +++ b/src/controllers/channels.ts @@ -1,8 +1,7 @@ import { eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { ChannelCreatePayload } from "../types/channel.ts"; -import { ChannelTypes } from "../types/channel.ts"; -import type { DiscordPayload } from "../types/discord.ts"; +import { ChannelCreatePayload, ChannelTypes } from "../types/channel.ts"; +import { DiscordPayload } from "../types/discord.ts"; import { cacheHandlers } from "./cache.ts"; export async function handleInternalChannelCreate(data: DiscordPayload) { diff --git a/src/controllers/guilds.ts b/src/controllers/guilds.ts index ef4d4c271..61a2777c6 100644 --- a/src/controllers/guilds.ts +++ b/src/controllers/guilds.ts @@ -1,13 +1,13 @@ import { eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { +import { DiscordPayload } from "../types/discord.ts"; +import { CreateGuildPayload, GuildDeletePayload, GuildEmojisUpdatePayload, UpdateGuildPayload, } from "../types/guild.ts"; -import type { GuildUpdateChange } from "../types/options.ts"; +import { GuildUpdateChange } from "../types/options.ts"; import { cache } from "../utils/cache.ts"; import { cacheHandlers } from "./cache.ts"; diff --git a/src/controllers/members.ts b/src/controllers/members.ts index 0083f158f..f1101525b 100644 --- a/src/controllers/members.ts +++ b/src/controllers/members.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { +import { DiscordPayload } from "../types/discord.ts"; +import { GuildBanPayload, GuildMemberAddPayload, GuildMemberChunkPayload, diff --git a/src/controllers/messages.ts b/src/controllers/messages.ts index a0e72dfdc..3f4298858 100644 --- a/src/controllers/messages.ts +++ b/src/controllers/messages.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { +import { DiscordPayload } from "../types/discord.ts"; +import { MessageCreateOptions, MessageDeleteBulkPayload, MessageDeletePayload, diff --git a/src/controllers/misc.ts b/src/controllers/misc.ts index 3cd7bc813..54f60991d 100644 --- a/src/controllers/misc.ts +++ b/src/controllers/misc.ts @@ -2,7 +2,7 @@ import { delay } from "../../deps.ts"; import { eventHandlers, setBotID } from "../module/client.ts"; import { allowNextShard } from "../module/shardingManager.ts"; import { structures } from "../structures/mod.ts"; -import type { +import { DiscordPayload, PresenceUpdatePayload, ReadyPayload, @@ -10,7 +10,7 @@ import type { VoiceStateUpdatePayload, WebhookUpdatePayload, } from "../types/discord.ts"; -import type { UserPayload } from "../types/guild.ts"; +import { UserPayload } from "../types/guild.ts"; import { cache } from "../utils/cache.ts"; import { cacheHandlers } from "./cache.ts"; diff --git a/src/controllers/reactions.ts b/src/controllers/reactions.ts index 670a7126d..3e867a9b8 100644 --- a/src/controllers/reactions.ts +++ b/src/controllers/reactions.ts @@ -1,7 +1,7 @@ import { botID, eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { +import { DiscordPayload } from "../types/discord.ts"; +import { BaseMessageReactionPayload, MessageReactionPayload, MessageReactionRemoveEmojiPayload, diff --git a/src/controllers/roles.ts b/src/controllers/roles.ts index 62cf72eb1..fe6718798 100644 --- a/src/controllers/roles.ts +++ b/src/controllers/roles.ts @@ -1,10 +1,7 @@ import { eventHandlers } from "../module/client.ts"; import { structures } from "../structures/mod.ts"; -import type { DiscordPayload } from "../types/discord.ts"; -import type { - GuildRoleDeletePayload, - GuildRolePayload, -} from "../types/guild.ts"; +import { DiscordPayload } from "../types/discord.ts"; +import { GuildRoleDeletePayload, GuildRolePayload } from "../types/guild.ts"; import { cacheHandlers } from "./cache.ts"; export async function handleInternalGuildRoleCreate(data: DiscordPayload) { diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 0e2580996..fa5d7b6dc 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -14,8 +14,8 @@ import { MessageContent, } from "../types/channel.ts"; import { Errors } from "../types/errors.ts"; -import type { RawOverwrite } from "../types/guild.ts"; -import type { MessageCreateOptions } from "../types/message.ts"; +import { RawOverwrite } from "../types/guild.ts"; +import { MessageCreateOptions } from "../types/message.ts"; import { Permissions } from "../types/permission.ts"; import { botHasChannelPermissions } from "../utils/permissions.ts"; diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index b045affe6..385b2c017 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -3,13 +3,13 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { identifyPayload } from "../module/client.ts"; import { RequestManager } from "../module/requestManager.ts"; import { requestAllMembers } from "../module/shardingManager.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { Member } from "../structures/member.ts"; +import { Guild } from "../structures/guild.ts"; +import { Member } from "../structures/member.ts"; import { structures } from "../structures/mod.ts"; -import type { ImageFormats, ImageSize } from "../types/cdn.ts"; +import { ImageFormats, ImageSize } from "../types/cdn.ts"; import { ChannelCreatePayload, ChannelTypes } from "../types/channel.ts"; import { Errors } from "../types/errors.ts"; -import type { +import { BannedUser, BanOptions, ChannelCreateOptions, @@ -26,10 +26,10 @@ import type { PrunePayload, UserPayload, } from "../types/guild.ts"; -import type { MemberCreatePayload } from "../types/member.ts"; +import { MemberCreatePayload } from "../types/member.ts"; import { Intents } from "../types/options.ts"; import { Permissions } from "../types/permission.ts"; -import type { RoleData } from "../types/role.ts"; +import { RoleData } from "../types/role.ts"; import { formatImageURL } from "../utils/cdn.ts"; import { Collection } from "../utils/collection.ts"; import { botHasPermission, calculateBits } from "../utils/permissions.ts"; diff --git a/src/handlers/member.ts b/src/handlers/member.ts index 9d31cf4af..8b0faf83e 100644 --- a/src/handlers/member.ts +++ b/src/handlers/member.ts @@ -2,15 +2,12 @@ import { endpoints } from "../constants/discord.ts"; import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import { RequestManager } from "../module/requestManager.ts"; -import type { Member } from "../structures/member.ts"; +import { Member } from "../structures/member.ts"; import { structures } from "../structures/mod.ts"; -import type { ImageFormats, ImageSize } from "../types/cdn.ts"; -import type { - DMChannelCreatePayload, - MessageContent, -} from "../types/channel.ts"; +import { ImageFormats, ImageSize } from "../types/cdn.ts"; +import { DMChannelCreatePayload, MessageContent } from "../types/channel.ts"; import { Errors } from "../types/errors.ts"; -import type { EditMemberOptions } from "../types/member.ts"; +import { EditMemberOptions } from "../types/member.ts"; import { Permissions } from "../types/permission.ts"; import { formatImageURL } from "../utils/cdn.ts"; import { diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 3b99c5b32..243404125 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -3,12 +3,12 @@ import { endpoints } from "../constants/discord.ts"; import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import { RequestManager } from "../module/requestManager.ts"; -import type { Message } from "../structures/message.ts"; +import { Message } from "../structures/message.ts"; import { structures } from "../structures/mod.ts"; -import type { MessageContent } from "../types/channel.ts"; +import { MessageContent } from "../types/channel.ts"; import { Errors } from "../types/errors.ts"; -import type { UserPayload } from "../types/guild.ts"; -import type { MessageCreateOptions } from "../types/message.ts"; +import { UserPayload } from "../types/guild.ts"; +import { MessageCreateOptions } from "../types/message.ts"; import { Permissions } from "../types/permission.ts"; import { botHasChannelPermissions } from "../utils/permissions.ts"; diff --git a/src/handlers/webhook.ts b/src/handlers/webhook.ts index e4b37509a..7bb9400b3 100644 --- a/src/handlers/webhook.ts +++ b/src/handlers/webhook.ts @@ -2,9 +2,9 @@ import { endpoints } from "../constants/discord.ts"; import { RequestManager } from "../module/requestManager.ts"; import { structures } from "../structures/mod.ts"; import { Errors } from "../types/errors.ts"; -import type { MessageCreateOptions } from "../types/message.ts"; +import { MessageCreateOptions } from "../types/message.ts"; import { Permissions } from "../types/permission.ts"; -import type { +import { ExecuteWebhookOptions, WebhookCreateOptions, WebhookPayload, diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index 68b9196ff..ee1a9cc04 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -7,16 +7,15 @@ import { isWebSocketPongEvent, WebSocket, } from "../../deps.ts"; -import type { +import { DiscordBotGatewayData, DiscordHeartbeatPayload, + GatewayOpcode, ReadyPayload, } from "../types/discord.ts"; -import { GatewayOpcode } from "../types/discord.ts"; -import type { FetchMembersOptions } from "../types/guild.ts"; -import type { BotStatusRequest } from "../utils/utils.ts"; -import type { IdentifyPayload } from "./client.ts"; -import { botGatewayData, eventHandlers } from "./client.ts"; +import { FetchMembersOptions } from "../types/guild.ts"; +import { BotStatusRequest } from "../utils/utils.ts"; +import { botGatewayData, eventHandlers, IdentifyPayload } from "./client.ts"; import { handleDiscordPayload } from "./shardingManager.ts"; const basicShards = new Map(); diff --git a/src/module/client.ts b/src/module/client.ts index 53dbcf843..01f311460 100644 --- a/src/module/client.ts +++ b/src/module/client.ts @@ -1,6 +1,6 @@ import { endpoints } from "../constants/discord.ts"; -import type { DiscordBotGatewayData } from "../types/discord.ts"; -import type { ClientOptions, EventHandlers } from "../types/options.ts"; +import { DiscordBotGatewayData } from "../types/discord.ts"; +import { ClientOptions, EventHandlers } from "../types/options.ts"; import { RequestManager } from "./requestManager.ts"; import { spawnShards } from "./shardingManager.ts"; diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index c74abe25c..dbbdabd15 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -2,7 +2,7 @@ import { delay } from "../../deps.ts"; import { baseEndpoints } from "../constants/discord.ts"; import { HttpResponseCode } from "../types/discord.ts"; import { Errors } from "../types/errors.ts"; -import type { RequestMethods } from "../types/fetch.ts"; +import { RequestMethods } from "../types/fetch.ts"; import { authorization, eventHandlers } from "./client.ts"; const pathQueues: { [key: string]: QueuedRequest[] } = {}; diff --git a/src/module/shard.ts b/src/module/shard.ts index c2e864487..8e7353127 100644 --- a/src/module/shard.ts +++ b/src/module/shard.ts @@ -1,13 +1,17 @@ -import type { WebSocket } from "../../deps.ts"; -import { connectWebSocket, delay, isWebSocketCloseEvent } from "../../deps.ts"; -import type { +import { + connectWebSocket, + delay, + isWebSocketCloseEvent, + WebSocket, +} from "../../deps.ts"; +import { DiscordBotGatewayData, DiscordHeartbeatPayload, + GatewayOpcode, ReadyPayload, } from "../types/discord.ts"; -import { GatewayOpcode } from "../types/discord.ts"; -import type { FetchMembersOptions } from "../types/guild.ts"; -import type { DebugArg } from "../types/options.ts"; +import { FetchMembersOptions } from "../types/guild.ts"; +import { DebugArg } from "../types/options.ts"; let shardSocket: WebSocket; diff --git a/src/module/shardingManager.ts b/src/module/shardingManager.ts index 4b1cb2d31..e95ed6c0d 100644 --- a/src/module/shardingManager.ts +++ b/src/module/shardingManager.ts @@ -1,21 +1,25 @@ import { delay } from "../../deps.ts"; import { controllers } from "../controllers/mod.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { +import { Guild } from "../structures/guild.ts"; +import { DiscordBotGatewayData, DiscordPayload, + GatewayOpcode, } from "../types/discord.ts"; -import { GatewayOpcode } from "../types/discord.ts"; -import type { FetchMembersOptions } from "../types/guild.ts"; +import { FetchMembersOptions } from "../types/guild.ts"; import { cache } from "../utils/cache.ts"; -import type { BotStatusRequest } from "../utils/utils.ts"; +import { BotStatusRequest } from "../utils/utils.ts"; import { botGatewayStatusRequest, createBasicShard, requestGuildMembers, } from "./basicShard.ts"; -import type { IdentifyPayload } from "./client.ts"; -import { botGatewayData, eventHandlers, identifyPayload } from "./client.ts"; +import { + botGatewayData, + eventHandlers, + IdentifyPayload, + identifyPayload, +} from "./client.ts"; let shardCounter = 0; let basicSharding = false; diff --git a/src/structures/channel.ts b/src/structures/channel.ts index 00e28eaff..acc29ebb4 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -1,6 +1,6 @@ import { cacheHandlers } from "../controllers/cache.ts"; -import type { ChannelCreatePayload } from "../types/channel.ts"; -import type { Unpromise } from "../types/misc.ts"; +import { ChannelCreatePayload } from "../types/channel.ts"; +import { Unpromise } from "../types/misc.ts"; import { calculatePermissions } from "../utils/permissions.ts"; export async function createChannel( diff --git a/src/structures/guild.ts b/src/structures/guild.ts index 70f391c7f..3cde3638f 100644 --- a/src/structures/guild.ts +++ b/src/structures/guild.ts @@ -1,7 +1,7 @@ -import type { CreateGuildPayload } from "../types/guild.ts"; -import type { Unpromise } from "../types/misc.ts"; +import { CreateGuildPayload } from "../types/guild.ts"; +import { Unpromise } from "../types/misc.ts"; import { Collection } from "../utils/collection.ts"; -import type { Member } from "./member.ts"; +import { Member } from "./member.ts"; import { structures } from "./mod.ts"; export async function createGuild(data: CreateGuildPayload, shardID: number) { diff --git a/src/structures/member.ts b/src/structures/member.ts index a62391876..97e91e832 100644 --- a/src/structures/member.ts +++ b/src/structures/member.ts @@ -1,5 +1,5 @@ -import type { MemberCreatePayload } from "../types/member.ts"; -import type { Unpromise } from "../types/misc.ts"; +import { MemberCreatePayload } from "../types/member.ts"; +import { Unpromise } from "../types/misc.ts"; export async function createMember(data: MemberCreatePayload, guildID: string) { const { diff --git a/src/structures/message.ts b/src/structures/message.ts index bd41e48ed..3c2fab5e5 100644 --- a/src/structures/message.ts +++ b/src/structures/message.ts @@ -1,5 +1,5 @@ -import type { MessageCreateOptions } from "../types/message.ts"; -import type { Unpromise } from "../types/misc.ts"; +import { MessageCreateOptions } from "../types/message.ts"; +import { Unpromise } from "../types/misc.ts"; export async function createMessage(data: MessageCreateOptions) { const { diff --git a/src/structures/role.ts b/src/structures/role.ts index 6aaba4e5a..8f8f87e3d 100644 --- a/src/structures/role.ts +++ b/src/structures/role.ts @@ -1,5 +1,5 @@ -import type { Unpromise } from "../types/misc.ts"; -import type { RoleData } from "../types/role.ts"; +import { Unpromise } from "../types/misc.ts"; +import { RoleData } from "../types/role.ts"; export async function createRole(data: RoleData) { return { diff --git a/src/types/channel.ts b/src/types/channel.ts index f4892bad2..d81d8c810 100644 --- a/src/types/channel.ts +++ b/src/types/channel.ts @@ -1,5 +1,5 @@ -import type { Overwrite, RawOverwrite } from "./guild.ts"; -import type { Embed } from "./message.ts"; +import { Overwrite, RawOverwrite } from "./guild.ts"; +import { Embed } from "./message.ts"; export interface ChannelEditOptions { /** 2-100 character channel name. All */ diff --git a/src/types/discord.ts b/src/types/discord.ts index 58e08b343..d750d9e24 100644 --- a/src/types/discord.ts +++ b/src/types/discord.ts @@ -1,7 +1,7 @@ -import type { PartialUser, UserPayload } from "./guild.ts"; -import type { MemberCreatePayload } from "./member.ts"; -import type { Activity } from "./message.ts"; -import type { ClientStatusPayload } from "./presence.ts"; +import { PartialUser, UserPayload } from "./guild.ts"; +import { MemberCreatePayload } from "./member.ts"; +import { Activity } from "./message.ts"; +import { ClientStatusPayload } from "./presence.ts"; export interface DiscordPayload { /** OP code for the payload */ diff --git a/src/types/guild.ts b/src/types/guild.ts index 8e35d70d2..7bcd4991e 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -1,10 +1,10 @@ -import type { ChannelCreatePayload, ChannelTypes } from "./channel.ts"; -import type { Emoji, StatusType } from "./discord.ts"; -import type { MemberCreatePayload } from "./member.ts"; -import type { Activity } from "./message.ts"; -import type { Permission } from "./permission.ts"; -import type { ClientStatusPayload } from "./presence.ts"; -import type { RoleData } from "./role.ts"; +import { ChannelCreatePayload, ChannelTypes } from "./channel.ts"; +import { Emoji, StatusType } from "./discord.ts"; +import { MemberCreatePayload } from "./member.ts"; +import { Activity } from "./message.ts"; +import { Permission } from "./permission.ts"; +import { ClientStatusPayload } from "./presence.ts"; +import { RoleData } from "./role.ts"; export interface GuildRolePayload { /** The id of the guild */ diff --git a/src/types/member.ts b/src/types/member.ts index a68f7c887..199e0fef5 100644 --- a/src/types/member.ts +++ b/src/types/member.ts @@ -1,4 +1,4 @@ -import type { UserPayload } from "./guild.ts"; +import { UserPayload } from "./guild.ts"; export interface EditMemberOptions { /** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */ diff --git a/src/types/message.ts b/src/types/message.ts index 8bb2fdd18..1e631d3cc 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -1,7 +1,7 @@ -import type { Channel } from "../structures/channel.ts"; -import type { ChannelType } from "./channel.ts"; -import type { UserPayload } from "./guild.ts"; -import type { MemberCreatePayload } from "./member.ts"; +import { Channel } from "../structures/channel.ts"; +import { ChannelType } from "./channel.ts"; +import { UserPayload } from "./guild.ts"; +import { MemberCreatePayload } from "./member.ts"; export interface MentionedUser extends UserPayload { member: MemberCreatePayload; diff --git a/src/types/options.ts b/src/types/options.ts index 641432ada..f3c66fc01 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -1,9 +1,9 @@ -import type { Channel } from "../structures/channel.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { Member } from "../structures/member.ts"; -import type { Message } from "../structures/message.ts"; -import type { Role } from "../structures/role.ts"; -import type { +import { Channel } from "../structures/channel.ts"; +import { Guild } from "../structures/guild.ts"; +import { Member } from "../structures/member.ts"; +import { Message } from "../structures/message.ts"; +import { Role } from "../structures/role.ts"; +import { DiscordPayload, Emoji, PresenceUpdatePayload, @@ -11,8 +11,8 @@ import type { TypingStartPayload, VoiceStateUpdatePayload, } from "./discord.ts"; -import type { UserPayload } from "./guild.ts"; -import type { +import { UserPayload } from "./guild.ts"; +import { Attachment, BaseMessageReactionPayload, Embed, diff --git a/src/types/presence.ts b/src/types/presence.ts index 1efc05220..e2ebd6f73 100644 --- a/src/types/presence.ts +++ b/src/types/presence.ts @@ -1,4 +1,4 @@ -import type { StatusType } from "./discord.ts"; +import { StatusType } from "./discord.ts"; export interface ClientStatusPayload { /** The user's status set for an active desktop (Windows, Linux, Mac) application session */ diff --git a/src/types/webhook.ts b/src/types/webhook.ts index 81adb0c13..8974e6575 100644 --- a/src/types/webhook.ts +++ b/src/types/webhook.ts @@ -1,5 +1,5 @@ -import type { UserPayload } from "./guild.ts"; -import type { Embed } from "./message.ts"; +import { UserPayload } from "./guild.ts"; +import { Embed } from "./message.ts"; export interface WebhookPayload { /** The id of the webhook */ diff --git a/src/utils/cache.ts b/src/utils/cache.ts index aec07ede7..dbd89b898 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -1,7 +1,7 @@ -import type { Channel } from "../structures/channel.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { Message } from "../structures/message.ts"; -import type { PresenceUpdatePayload } from "../types/discord.ts"; +import { Channel } from "../structures/channel.ts"; +import { Guild } from "../structures/guild.ts"; +import { Message } from "../structures/message.ts"; +import { PresenceUpdatePayload } from "../types/discord.ts"; import { Collection } from "./collection.ts"; export interface CacheData { diff --git a/src/utils/cdn.ts b/src/utils/cdn.ts index b4748e219..6c5275ac5 100644 --- a/src/utils/cdn.ts +++ b/src/utils/cdn.ts @@ -1,4 +1,4 @@ -import type { ImageFormats, ImageSize } from "../types/cdn.ts"; +import { ImageFormats, ImageSize } from "../types/cdn.ts"; export const formatImageURL = ( url: string, diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index f69ec570b..b9b21abe1 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -1,9 +1,8 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; -import type { Guild } from "../structures/guild.ts"; -import type { Role } from "../structures/role.ts"; -import type { Permission } from "../types/permission.ts"; -import { Permissions } from "../types/permission.ts"; +import { Guild } from "../structures/guild.ts"; +import { Role } from "../structures/role.ts"; +import { Permission, Permissions } from "../types/permission.ts"; /** Checks if the member has this permission. If the member is an owner or has admin perms it will always be true. */ export async function memberIDHasPermission( diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 78591d522..c73a6033f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,7 +1,7 @@ import { encode } from "../../deps.ts"; import { sendGatewayCommand } from "../module/shardingManager.ts"; import { ActivityType } from "../types/activity.ts"; -import type { StatusType } from "../types/discord.ts"; +import { StatusType } from "../types/discord.ts"; export const sleep = (timeout: number) => { return new Promise((resolve) => setTimeout(resolve, timeout)); From 8cb9bfe9de2acea15d68e57c141711a0027ef1f5 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 10:08:27 -0400 Subject: [PATCH 054/123] eggs --- egg.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/egg.yml b/egg.yml index 3af7f3b38..4e7f2b76a 100644 --- a/egg.yml +++ b/egg.yml @@ -2,9 +2,9 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.12 +version: 9.0.15 stable: true -entry: mod.ts +entry: /mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' files: - ./src/**/* @@ -13,5 +13,6 @@ files: - tsconfig.json - ./deps.ts - mod.ts + - mod.ts checkAll: false unlisted: false From 01c04e03a6815209933f4ad635f0df18cd3a4d92 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 10:21:13 -0400 Subject: [PATCH 055/123] fix: some tests --- tests/mod.test.ts | 50 +++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index bfa3169e7..5d6b1ba24 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -1,4 +1,4 @@ -import { assert, assertArrayIncludes, assertEquals, delay } from "../deps.ts"; +import { assert, assertEquals, delay } from "../deps.ts"; import { botID, cache, @@ -18,8 +18,12 @@ import { Role, sendMessage, } from "../mod.ts"; -import { editChannel } from "../src/handlers/channel.ts"; +import { + channelOverwriteHasPermission, + editChannel, +} from "../src/handlers/channel.ts"; import { getChannel } from "../src/handlers/guild.ts"; +import { Permissions } from "../src/types/permission.ts"; // TODO: add DISCORD_TOKEN variable to GitHub secrets const token = Deno.env.get("DISCORD_TOKEN"); @@ -143,11 +147,19 @@ Deno.test({ async fn() { const channel = await editChannel(data.channelID, { name: "edited channel", + overwrites: [ + { + id: data.roleID, + type: OverwriteType.ROLE, + allow: ["VIEW_CHANNEL", "SEND_MESSAGES"], + deny: ["USE_EXTERNAL_EMOJIS"], + }, + ], }) as Channel; + const editedChannel = await getChannel(data.channelID); assert(channel); - - data.channelID = channel.id; + assertEquals(editedChannel.name, "edited channel"); }, }); @@ -156,20 +168,24 @@ Deno.test({ async fn() { const channel = cache.channels.get(data.channelID); if (!channel) throw "Channel not found"; - assertArrayIncludes(channel.permission_overwrites!, [ - { - id: data.roleID, - type: OverwriteType.ROLE, - // The type for Channel#permission_overwrites is "RawOverwrite[] | undefined" - // not "Overwrite[]"; therefore, permission strings cannot be used. - // allow: ["VIEW_CHANNEL", "SEND_MESSAGES"], - // deny: ["USE_EXTERNAL_EMOJIS"], - }, - ]); - // THIS TEST CASE SHOULD BE REFACTORED AND IMPROVED - // CURRENTLY, IT USES Channel#permission_overwrites - // but preferably, it should use the channelOverwriteHasPermission() + if (!channel.permission_overwrites) throw "Channel overwrites not found."; + + const hasPerm = channelOverwriteHasPermission( + data.guildID, + data.roleID, + channel.permission_overwrites, + [Permissions.VIEW_CHANNEL, Permissions.SEND_MESSAGES], + ); + const missingPerm = channelOverwriteHasPermission( + data.guildID, + data.roleID, + channel.permission_overwrites, + [Permissions.USE_EXTERNAL_EMOJIS] + ) + + assertEquals(hasPerm, true); + assertEquals(missingPerm, false); }, ...testOptions, }); From 26bc78103601993a129391c8ec7a57f3896ffae4 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 10:22:10 -0400 Subject: [PATCH 056/123] fix --- egg.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/egg.yml b/egg.yml index 4e7f2b76a..79b0633d1 100644 --- a/egg.yml +++ b/egg.yml @@ -4,7 +4,7 @@ description: >- Discord Team) https://discordeno.netlify.app version: 9.0.15 stable: true -entry: /mod.ts +entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' files: - ./src/**/* @@ -13,6 +13,5 @@ files: - tsconfig.json - ./deps.ts - mod.ts - - mod.ts checkAll: false unlisted: false From e8f391d547ef591497eebd832732a6278fd86a1b Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 10:22:32 -0400 Subject: [PATCH 057/123] remove todo --- tests/mod.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 5d6b1ba24..fb745596e 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -25,7 +25,6 @@ import { import { getChannel } from "../src/handlers/guild.ts"; import { Permissions } from "../src/types/permission.ts"; -// TODO: add DISCORD_TOKEN variable to GitHub secrets const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw "Token is not provided"; From b1001b0af53e279d63397cdc6df4a23205167b44 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 18:58:09 -0400 Subject: [PATCH 058/123] test fix for test 14 --- tests/mod.test.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index fb745596e..ae21564fe 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -144,8 +144,8 @@ Deno.test({ Deno.test({ name: "edit a channel in a guild", async fn() { - const channel = await editChannel(data.channelID, { - name: "edited channel", + await editChannel(data.channelID, { + name: "edited-channel", overwrites: [ { id: data.roleID, @@ -154,11 +154,12 @@ Deno.test({ deny: ["USE_EXTERNAL_EMOJIS"], }, ], - }) as Channel; + }); + // Wait 5 seconds for it to update + await delay(5000); const editedChannel = await getChannel(data.channelID); - assert(channel); - assertEquals(editedChannel.name, "edited channel"); + assertEquals(editedChannel.name, "edited-channel"); }, }); From 3e1d9258e1143bab2bddb9f1849dcb97cec25263 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 19:01:51 -0400 Subject: [PATCH 059/123] fix test exiting --- tests/mod.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index ae21564fe..93828808a 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -2,7 +2,6 @@ import { assert, assertEquals, delay } from "../deps.ts"; import { botID, cache, - Channel, createClient, createGuildChannel, createGuildRole, @@ -144,7 +143,7 @@ Deno.test({ Deno.test({ name: "edit a channel in a guild", async fn() { - await editChannel(data.channelID, { + await editChannel(data.channelID, { name: "edited-channel", overwrites: [ { @@ -181,8 +180,8 @@ Deno.test({ data.guildID, data.roleID, channel.permission_overwrites, - [Permissions.USE_EXTERNAL_EMOJIS] - ) + [Permissions.USE_EXTERNAL_EMOJIS], + ); assertEquals(hasPerm, true); assertEquals(missingPerm, false); @@ -248,7 +247,7 @@ Deno.test({ Deno.test({ name: "exit the process forcefully after all the tests are done", async fn() { - Deno.exit(1); + Deno.exit(0); }, ...testOptions, }); From 8ea1c8c51f387550d8e419385f621b20cd01d771 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 29 Oct 2020 19:02:37 -0400 Subject: [PATCH 060/123] 0 be default --- tests/mod.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mod.test.ts b/tests/mod.test.ts index 93828808a..263519312 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -247,7 +247,7 @@ Deno.test({ Deno.test({ name: "exit the process forcefully after all the tests are done", async fn() { - Deno.exit(0); + Deno.exit(); }, ...testOptions, }); From 98b335fa635f20673ad28f6f20f223ea64eb4de7 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Fri, 30 Oct 2020 03:19:15 -0700 Subject: [PATCH 061/123] Update dependencies in deps.ts --- deps.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps.ts b/deps.ts index ddc71fbf2..e2fe08a38 100644 --- a/deps.ts +++ b/deps.ts @@ -1,5 +1,3 @@ -export { delay } from "https://deno.land/std@0.67.0/async/delay.ts"; -export { encode } from "https://deno.land/std@0.67.0/encoding/base64.ts"; export { connectWebSocket, isWebSocketCloseEvent, @@ -7,9 +5,11 @@ export { isWebSocketPongEvent, } from "https://deno.land/std@0.67.0/ws/mod.ts"; export type { WebSocket } from "https://deno.land/std@0.67.0/ws/mod.ts"; +export { delay } from "https://deno.land/std@0.75.0/async/delay.ts"; +export { encode } from "https://deno.land/std@0.75.0/encoding/base64.ts"; export { assert, assertArrayIncludes, assertEquals, } from "https://deno.land/std@0.75.0/testing/asserts.ts"; -export { decompress_with as inflate } from "https://unpkg.com/@evan/wasm@0.0.11/target/zlib/deno.js"; +export { decompress_with as inflate } from "https://unpkg.com/@evan/wasm@0.0.12/target/zlib/deno.js"; From f32f1dec1497656e44233c7f07960afd95080d46 Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 2 Nov 2020 09:25:12 -0800 Subject: [PATCH 062/123] Add moveMember function to member handler Closes #164 --- src/handlers/member.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/handlers/member.ts b/src/handlers/member.ts index 8b0faf83e..803a83cec 100644 --- a/src/handlers/member.ts +++ b/src/handlers/member.ts @@ -183,3 +183,17 @@ export function editMember( options, ); } + +/** + * Move a member from a voice channel to another. + * @param guildID the id of the guild which the channel exists in + * @param memberID the id of the member to move. + * @param channelID id of channel to move user to (if they are connected to voice) + */ +export function moveMember( + guildID: string, + memberID: string, + channelID: string, +) { + return editMember(guildID, memberID, { channel_id: channelID }); +} From 7537ed6065278357d511f01896efb06a9b5f4d2a Mon Sep 17 00:00:00 2001 From: Jonathan <54381371+jz3r01@users.noreply.github.com> Date: Tue, 3 Nov 2020 15:29:12 -0500 Subject: [PATCH 063/123] Update to reflect new way of running mod.ts --- docs/content/stepbystep/createbot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/stepbystep/createbot.md b/docs/content/stepbystep/createbot.md index 6a38c32b0..de7179eb2 100644 --- a/docs/content/stepbystep/createbot.md +++ b/docs/content/stepbystep/createbot.md @@ -113,7 +113,7 @@ Oh my god! You now have a bot with a bunch of features already! You don't believ 3. Run the script below: ```shell -deno run --allow-net --allow-read mod.ts +deno run --allow-net --allow-read --no-check --config tsconfig.json mod.ts ``` The first time you run it, you may see a lot of files being loaded. This is preparing all the magic behind the scene. Once it is ready, you will see something like this: From 121f307ad172c26ca6e1a596893a06521b16b569 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Tue, 3 Nov 2020 15:38:10 -0500 Subject: [PATCH 064/123] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index bd5888489..d3f46b134 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,9 @@ [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=dark)](https://discord.gg/J4NqJ72) ![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) +![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) -[WIP] ![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg) - ## Why Discordeno? ### Beginner Developers From 08af964a52bb219d264edd014d5772bb1c4f0f3a Mon Sep 17 00:00:00 2001 From: Jonathan <54381371+jz3r01@users.noreply.github.com> Date: Tue, 3 Nov 2020 17:29:11 -0500 Subject: [PATCH 065/123] Update createcommand.md --- docs/content/stepbystep/createcommand.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/stepbystep/createcommand.md b/docs/content/stepbystep/createcommand.md index c89fdd706..2e6001cf4 100644 --- a/docs/content/stepbystep/createcommand.md +++ b/docs/content/stepbystep/createcommand.md @@ -66,7 +66,7 @@ Let's add a custom description to our invite command. 🎉 It's that simple. So let's restart the bot and see how it changed. Use **CTRL + C** to shut down the bot. Then run the command from earlier. ```shell -deno run --allow-net --allow-read mod.ts +deno run --allow-net --allow-read --no-check --config tsconfig.json mod.ts ``` To access this easily, most likely all you need to do is press the **UP ARROW** key. Feel free to copy paste this if it doesn't work. From 81acfed1ce84d53d3a5e9b15b49e9c2540958618 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 3 Nov 2020 21:30:06 -0800 Subject: [PATCH 066/123] Update README.md --- README.md | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index d3f46b134..77af7bf20 100644 --- a/README.md +++ b/README.md @@ -13,39 +13,13 @@ Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots. -If you are a beginner developer, please use this official boilerplate: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! +If you are a beginner developer, you may check out these awesome official and unofficial boilerplates: -**Modular commands, arguments, events, inhibitors, monitors, tasks.** - -- Clean and powerful commands system - - Powerful argument handling including validating, parsing and modifications. - - Easily create custom arguments for your specific needs. - - Command aliases. - - Cooldowns and allowed uses before cooldown triggers. - - Author and bot permission checks in server AND in channel! -- Clean and powerful events system - - Simple functions that are called when an event occurs. - - Easily reloadable! - - No possible memory leaks due to incorrect EventEmitter usage! - - Useful events available to help debug! -- Clean and powerful inhibitors system - - Stops a command from running if a requirement fails. - - Easily add custom inhibitors! -- Clean and powerful monitors system. - - Runs a function on every message sent. Useful for stuff like auto-moderation or tags. - - Easily ignore bots, users, edits, dms. - - Powerful permission checks. -- Clean and powerful tasks system. - - Runs a function at a certain interval. Useful for things like unmute and updating bot lists etc. - - Can be used for cache sweeping to keep your cache optimized for exactly what you want. - - Botlists code already made for most botlists. Just add your api tokens for each site and magic! -- Clean and powerful languages system. - - Built in multi-lingual support. - - Uses i18next, one of the best localization tools available. - - Supports nested folders to keep cleaner translation files - -- **Hot Reloadable**: Easily update your code without having to restart the bot everytime. -- **Step By Step Guide**: There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website! +- Official Discordeno Boilerplate + - [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) + - [Features](https://github.com/Skillz4Killz/Discordeno-bot-template#features) + +If you do not wish to use a boilerplate, you may continue reading. ### Advanced Developers From 1cc8ac12c6b160ec2673a722d10779c2e5fdb9eb Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 3 Nov 2020 21:33:26 -0800 Subject: [PATCH 067/123] Revert "Update README.md" This reverts commit 81acfed1ce84d53d3a5e9b15b49e9c2540958618. --- README.md | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 77af7bf20..d3f46b134 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,39 @@ Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots. -If you are a beginner developer, you may check out these awesome official and unofficial boilerplates: +If you are a beginner developer, please use this official boilerplate: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! -- Official Discordeno Boilerplate - - [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) - - [Features](https://github.com/Skillz4Killz/Discordeno-bot-template#features) - -If you do not wish to use a boilerplate, you may continue reading. +**Modular commands, arguments, events, inhibitors, monitors, tasks.** + +- Clean and powerful commands system + - Powerful argument handling including validating, parsing and modifications. + - Easily create custom arguments for your specific needs. + - Command aliases. + - Cooldowns and allowed uses before cooldown triggers. + - Author and bot permission checks in server AND in channel! +- Clean and powerful events system + - Simple functions that are called when an event occurs. + - Easily reloadable! + - No possible memory leaks due to incorrect EventEmitter usage! + - Useful events available to help debug! +- Clean and powerful inhibitors system + - Stops a command from running if a requirement fails. + - Easily add custom inhibitors! +- Clean and powerful monitors system. + - Runs a function on every message sent. Useful for stuff like auto-moderation or tags. + - Easily ignore bots, users, edits, dms. + - Powerful permission checks. +- Clean and powerful tasks system. + - Runs a function at a certain interval. Useful for things like unmute and updating bot lists etc. + - Can be used for cache sweeping to keep your cache optimized for exactly what you want. + - Botlists code already made for most botlists. Just add your api tokens for each site and magic! +- Clean and powerful languages system. + - Built in multi-lingual support. + - Uses i18next, one of the best localization tools available. + - Supports nested folders to keep cleaner translation files + +- **Hot Reloadable**: Easily update your code without having to restart the bot everytime. +- **Step By Step Guide**: There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website! ### Advanced Developers From dec6b1fa9c64cfe113323b5a15ff3052ce2fb6b0 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 3 Nov 2020 21:37:31 -0800 Subject: [PATCH 068/123] Remove unnecessary clutter and features --- README.md | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index d3f46b134..6573060f0 100644 --- a/README.md +++ b/README.md @@ -12,40 +12,13 @@ ### Beginner Developers Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots. +If you are a beginner developer, you may check out these awesome official and unofficial boilerplates: -If you are a beginner developer, please use this official boilerplate: [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) but there will be more listed on the website. It is a beautiful website indeed! Check it out! +- Official Discordeno Boilerplate + - [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template) + - [Features](https://github.com/Skillz4Killz/Discordeno-bot-template#features) -**Modular commands, arguments, events, inhibitors, monitors, tasks.** - -- Clean and powerful commands system - - Powerful argument handling including validating, parsing and modifications. - - Easily create custom arguments for your specific needs. - - Command aliases. - - Cooldowns and allowed uses before cooldown triggers. - - Author and bot permission checks in server AND in channel! -- Clean and powerful events system - - Simple functions that are called when an event occurs. - - Easily reloadable! - - No possible memory leaks due to incorrect EventEmitter usage! - - Useful events available to help debug! -- Clean and powerful inhibitors system - - Stops a command from running if a requirement fails. - - Easily add custom inhibitors! -- Clean and powerful monitors system. - - Runs a function on every message sent. Useful for stuff like auto-moderation or tags. - - Easily ignore bots, users, edits, dms. - - Powerful permission checks. -- Clean and powerful tasks system. - - Runs a function at a certain interval. Useful for things like unmute and updating bot lists etc. - - Can be used for cache sweeping to keep your cache optimized for exactly what you want. - - Botlists code already made for most botlists. Just add your api tokens for each site and magic! -- Clean and powerful languages system. - - Built in multi-lingual support. - - Uses i18next, one of the best localization tools available. - - Supports nested folders to keep cleaner translation files - -- **Hot Reloadable**: Easily update your code without having to restart the bot everytime. -- **Step By Step Guide**: There is a step by step walkthrough to learn how to create Discord bots with Discordeno on our website! +If you do not wish to use a boilerplate, you may continue reading. ### Advanced Developers From b2a9db2b91b480ae05d6d8ef0ddf181003a21f8d Mon Sep 17 00:00:00 2001 From: ayntee Date: Wed, 4 Nov 2020 07:07:28 -0800 Subject: [PATCH 069/123] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6573060f0..98f27eb16 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ### Beginner Developers -Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues wit pre-existing libraries, such as discord.js, and issues that I had when I first started out coding bots. +Don't worry a lot of developers start out coding their first projects as a Discord bot (I did 😉) and it is not so easy to do so. Discordeno is built considering all the issues with pre-existing libraries and issues that I had when I first started out coding bots. If you are a beginner developer, you may check out these awesome official and unofficial boilerplates: - Official Discordeno Boilerplate From 717d8cd3e397da46a8c248d9f86feebccfc3bb0c Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 5 Nov 2020 23:16:33 -0800 Subject: [PATCH 070/123] Lower the time limit for ready event activation --- src/controllers/misc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/misc.ts b/src/controllers/misc.ts index 54f60991d..66eb2d94b 100644 --- a/src/controllers/misc.ts +++ b/src/controllers/misc.ts @@ -26,8 +26,8 @@ export async function handleInternalReady( // Triggered on each shard eventHandlers.shardReady?.(shardID); if (payload.shard && shardID === payload.shard[1] - 1) { - // Wait 10 seconds to allow all guild create events to be processed - await delay(10000); + // Wait for 5 seconds to allow all guild create events to be processed + await delay(5000); cache.isReady = true; eventHandlers.ready?.(); } From 4254a37467a5bc747302ac93a025361fe2d47bf4 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 6 Nov 2020 09:16:33 -0800 Subject: [PATCH 071/123] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98f27eb16..8c29a044c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The instructions below are meant for advanced developers! Starting with Discordeno is very simple, you can start from scratch without any boilerplates/frameworks: Add this snippet of code into a new TypeScript file: ```typescript -import StartBot, { sendMessage, Intents } from "https://x.nest.land/Discordeno@9.0.1/mod.ts"; +import StartBot, { sendMessage, Intents } from "https://x.nest.land/Discordeno@9.0.15/mod.ts"; import config from "./config.ts"; StartBot({ From efcf567db06ea2a7ee1a20c1a42db7b019f1537a Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 6 Nov 2020 23:16:41 -0800 Subject: [PATCH 072/123] Resolve promise for all botHasChannelPermissions() --- src/handlers/channel.ts | 106 ++++++++++++++++++++++++++++------------ src/handlers/message.ts | 78 ++++++++++++++++++++--------- src/handlers/webhook.ts | 9 ++-- 3 files changed, 137 insertions(+), 56 deletions(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index fa5d7b6dc..8a77101e4 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -43,16 +43,22 @@ export async function getMessage( channelID: string, id: string, ) { + const hasViewChannelPerm = await botHasChannelPermissions( + channelID, + [Permissions.VIEW_CHANNEL], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.VIEW_CHANNEL]) + !hasViewChannelPerm ) { throw new Error(Errors.MISSING_VIEW_CHANNEL); } + + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.READ_MESSAGE_HISTORY], - ) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -72,16 +78,22 @@ export async function getMessages( | GetMessagesAround | GetMessages, ) { + const hasViewChannelPerm = await botHasChannelPermissions( + channelID, + [Permissions.VIEW_CHANNEL], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.VIEW_CHANNEL]) + !hasViewChannelPerm ) { throw new Error(Errors.MISSING_VIEW_CHANNEL); } + + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.READ_MESSAGE_HISTORY], - ) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -109,24 +121,34 @@ export async function sendMessage( content: string | MessageContent, ) { if (typeof content === "string") content = { content }; + const hasSendMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.SEND_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.SEND_MESSAGES]) + !hasSendMessagesPerm ) { throw new Error(Errors.MISSING_SEND_MESSAGES); } + + const hasSendTtsMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.SEND_TTS_MESSAGES], + ); if ( content.tts && - !botHasChannelPermissions( - channelID, - [Permissions.SEND_TTS_MESSAGES], - ) + !hasSendTtsMessagesPerm ) { throw new Error(Errors.MISSING_SEND_TTS_MESSAGE); } + const hasEmbedLinksPerm = await botHasChannelPermissions( + channelID, + [Permissions.EMBED_LINKS], + ); if ( content.embed && - !botHasChannelPermissions(channelID, [Permissions.EMBED_LINKS]) + !hasEmbedLinksPerm ) { throw new Error(Errors.MISSING_EMBED_LINKS); } @@ -183,13 +205,17 @@ export async function sendMessage( } /** Delete messages from the channel. 2-100. Requires the MANAGE_MESSAGES permission */ -export function deleteMessages( +export async function deleteMessages( channelID: string, ids: string[], reason?: string, ) { + const hasManageMessages = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessages ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -210,9 +236,13 @@ export function deleteMessages( } /** Gets the invites for this channel. Requires MANAGE_CHANNEL */ -export function getChannelInvites(channelID: string) { +export async function getChannelInvites(channelID: string) { + const hasManagaChannels = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_CHANNELS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_CHANNELS]) + !hasManagaChannels ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } @@ -220,12 +250,16 @@ export function getChannelInvites(channelID: string) { } /** Creates a new invite for this channel. Requires CREATE_INSTANT_INVITE */ -export function createInvite(channelID: string, options: CreateInviteOptions) { +export async function createInvite( + channelID: string, + options: CreateInviteOptions, +) { + const hasCreateInstantInvitePerm = await botHasChannelPermissions( + channelID, + [Permissions.CREATE_INSTANT_INVITE], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.CREATE_INSTANT_INVITE], - ) + !hasCreateInstantInvitePerm ) { throw new Error(Errors.MISSING_CREATE_INSTANT_INVITE); } @@ -233,9 +267,13 @@ export function createInvite(channelID: string, options: CreateInviteOptions) { } /** Gets the webhooks for this channel. Requires MANAGE_WEBHOOKS */ -export function getChannelWebhooks(channelID: string) { +export async function getChannelWebhooks(channelID: string) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_WEBHOOKS]) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_WEBHOOKS); } @@ -288,12 +326,16 @@ function processEditChannelQueue() { } } -export function editChannel( +export async function editChannel( channelID: string, options: ChannelEditOptions, ) { + const hasManageChannelsPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_CHANNELS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_CHANNELS]) + !hasManageChannelsPerm ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } @@ -356,8 +398,12 @@ export async function followChannel( sourceChannelID: string, targetChannelID: string, ) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + targetChannelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions(targetChannelID, [Permissions.MANAGE_WEBHOOKS]) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 243404125..f592568e0 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -38,11 +38,12 @@ export async function deleteMessage( ) { if (message.author.id !== botID) { // This needs to check the channels permission not the guild permission + const hasManageMessages = await botHasChannelPermissions( + message.channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions( - message.channelID, - [Permissions.MANAGE_MESSAGES], - ) + !hasManageMessages ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -57,9 +58,13 @@ export async function deleteMessage( } /** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */ -export function pin(channelID: string, messageID: string) { +export async function pin(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -67,9 +72,13 @@ export function pin(channelID: string, messageID: string) { } /** Unpin a message in a channel. Requires MANAGE_MESSAGES. */ -export function unpin(channelID: string, messageID: string) { +export async function unpin(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -79,17 +88,25 @@ export function unpin(channelID: string, messageID: string) { } /** Create a reaction for the message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. Requires READ_MESSAGE_HISTORY and ADD_REACTIONS */ -export function addReaction( +export async function addReaction( channelID: string, messageID: string, reaction: string, ) { - if (!botHasChannelPermissions(channelID, [Permissions.ADD_REACTIONS])) { + const hasAddReactionsPerm = await botHasChannelPermissions( + channelID, + [Permissions.ADD_REACTIONS], + ); + if (!hasAddReactionsPerm) { throw new Error(Errors.MISSING_ADD_REACTIONS); } + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.READ_MESSAGE_HISTORY]) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -143,13 +160,17 @@ export function removeReaction( } /** Removes a reaction from the specified user on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ -export function removeUserReaction( +export async function removeUserReaction( channelID: string, messageID: string, reaction: string, userID: string, ) { - if (!botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES])) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); + if (!hasManageMessagesPerm) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -164,9 +185,13 @@ export function removeUserReaction( } /** Removes all reactions for all emojis on this message. */ -export function removeAllReactions(channelID: string, messageID: string) { +export async function removeAllReactions(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -176,13 +201,17 @@ export function removeAllReactions(channelID: string, messageID: string) { } /** Removes all reactions for a single emoji on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ -export function removeReactionEmoji( +export async function removeReactionEmoji( channelID: string, messageID: string, reaction: string, ) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -216,18 +245,23 @@ export async function editMessage( if (typeof content === "string") content = { content }; + const hasSendMessagesPerm = await botHasChannelPermissions( + message.channelID, + [Permissions.SEND_MESSAGES], + ); if ( - !botHasChannelPermissions(message.channelID, [Permissions.SEND_MESSAGES]) + !hasSendMessagesPerm ) { throw new Error(Errors.MISSING_SEND_MESSAGES); } + const hasSendTtsMessagesPerm = await botHasChannelPermissions( + message.channelID, + [Permissions.SEND_TTS_MESSAGES], + ); if ( content.tts && - !botHasChannelPermissions( - message.channelID, - [Permissions.SEND_TTS_MESSAGES], - ) + !hasSendTtsMessagesPerm ) { throw new Error(Errors.MISSING_SEND_TTS_MESSAGE); } diff --git a/src/handlers/webhook.ts b/src/handlers/webhook.ts index 7bb9400b3..cc7365db7 100644 --- a/src/handlers/webhook.ts +++ b/src/handlers/webhook.ts @@ -20,11 +20,12 @@ export async function createWebhook( channelID: string, options: WebhookCreateOptions, ) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.MANAGE_WEBHOOKS], - ) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_WEBHOOKS); } From 9c3a42e10610ea2e089cb51428c4df745d1cc2f5 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 7 Nov 2020 21:30:17 -0800 Subject: [PATCH 073/123] Convert the License section text to hyperlink --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c29a044c..3cd062456 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,4 @@ Alternatively, you can use boilerplate template repositories that were created b ## License -MIT © Skillz4Killz +[MIT © Skillz4Killz](https://github.com/Skillz4Killz/Discordeno/blob/master/LICENSE) From be27976baeeec02b9b767da7122835dc066584ca Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 14:41:08 -0500 Subject: [PATCH 074/123] much faster rest --- src/module/requestManager.ts | 90 +++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index dbbdabd15..4f14fa456 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -64,56 +64,60 @@ async function cleanupQueues() { } async function processQueue() { - if ( - (Object.keys(pathQueues).length) && !globallyRateLimited - ) { - await Promise.allSettled( - Object.values(pathQueues).map(async (pathQueue) => { - const request = pathQueue.shift(); - if (!request) return; + // Putting this code inside a function like this allows us to use tail recursion like a while loop without hitting the max stack error. + async function avoidMaxStackError() { + if ( + (Object.keys(pathQueues).length) && !globallyRateLimited + ) { + await Promise.allSettled( + Object.values(pathQueues).map(async (pathQueue) => { + const request = pathQueue.shift(); + if (!request) return; - const rateLimitedURLResetIn = await checkRatelimits(request.url); + const rateLimitedURLResetIn = await checkRatelimits(request.url); - if (request.bucketID) { - const rateLimitResetIn = await checkRatelimits(request.bucketID); - if (rateLimitResetIn) { - // This request is still rate limited readd to queue - addToQueue(request); - } else if (rateLimitedURLResetIn) { - // This URL is rate limited readd to queue - addToQueue(request); + if (request.bucketID) { + const rateLimitResetIn = await checkRatelimits(request.bucketID); + if (rateLimitResetIn) { + // This request is still rate limited readd to queue + addToQueue(request); + } else if (rateLimitedURLResetIn) { + // This URL is rate limited readd to queue + addToQueue(request); + } else { + // This request is not rate limited so it should be run + const result = await request.callback(); + if (result && result.rateLimited) { + addToQueue( + { ...request, bucketID: result.bucketID || request.bucketID }, + ); + } + } } else { - // This request is not rate limited so it should be run - const result = await request.callback(); - if (result && result.rateLimited) { - addToQueue( - { ...request, bucketID: result.bucketID || request.bucketID }, - ); + if (rateLimitedURLResetIn) { + // This URL is rate limited readd to queue + addToQueue(request); + } else { + // This request has no bucket id so it should be processed + const result = await request.callback(); + if (request && result && result.rateLimited) { + addToQueue( + { ...request, bucketID: result.bucketID || request.bucketID }, + ); + } } } - } else { - if (rateLimitedURLResetIn) { - // This URL is rate limited readd to queue - addToQueue(request); - } else { - // This request has no bucket id so it should be processed - const result = await request.callback(); - if (request && result && result.rateLimited) { - addToQueue( - { ...request, bucketID: result.bucketID || request.bucketID }, - ); - } - } - } - }), - ); + }), + ); + } + + if (Object.keys(pathQueues).length) { + avoidMaxStackError(); + cleanupQueues(); + } else queueInProcess = false; } - if (Object.keys(pathQueues).length) { - await delay(1000); - processQueue(); - cleanupQueues(); - } else queueInProcess = false; + return avoidMaxStackError() } processRateLimitedPaths(); From 7f0d52e5ba25561865efacf86a478b844b39ce12 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 16:11:01 -0500 Subject: [PATCH 075/123] fmt --- src/module/requestManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index 4f14fa456..ee96700da 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -117,7 +117,7 @@ async function processQueue() { } else queueInProcess = false; } - return avoidMaxStackError() + return avoidMaxStackError(); } processRateLimitedPaths(); From 2530054b6560a3ec005e1748447196a71be26d56 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 16:20:42 -0500 Subject: [PATCH 076/123] use recommended publishing on nes.land --- .github/workflows/nestland.yml | 9 +++++---- egg.yml | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nestland.yml b/.github/workflows/nestland.yml index 6625cc71c..fbb97d5d9 100644 --- a/.github/workflows/nestland.yml +++ b/.github/workflows/nestland.yml @@ -1,8 +1,8 @@ name: Ship Nest.Land on: - release: - types: [published] + create: + ref_type: "tag" jobs: release: @@ -16,5 +16,6 @@ jobs: - name: Publish module run: | - deno run -A --unstable https://x.nest.land/eggs@0.2.1/mod.ts link ${{ secrets.NESTAPIKEY }} - deno run -A --unstable https://x.nest.land/eggs@0.2.1/mod.ts publish --version ${{ github.event.inputs.tags }} + deno install -A --unstable https://x.nest.land/eggs@0.3.2/eggs.ts + eggs link ${{ secrets.NESTAPIKEY }} + eggs publish --yes --no-check --version $(git describe --tags $(git rev-list --tags --max-count=1)) diff --git a/egg.yml b/egg.yml index 79b0633d1..c25ed8734 100644 --- a/egg.yml +++ b/egg.yml @@ -2,7 +2,6 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.15 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' From a3b41f0e26dda1cc1dcc0978869d5d1c2cad2ed2 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:21:05 +0400 Subject: [PATCH 077/123] Add Discordeno bot tutorial series to useful links section --- docs/content/gettingstarted.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index 6ee051f24..f26820c9c 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -16,6 +16,7 @@ This website serves as the purpose for introducing Discordeno to developers. The - [GitHub Repository](https://github.com/Skillz4Killz/Discordeno) - [Deno Page](https://deno.land/x/discordeno) - [Website](https://discordeno.js.org/) +- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) ## Requirements From 5adf6b49cead71c7c924ef8d9e6d15da9ee2c2fd Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:23:07 +0400 Subject: [PATCH 078/123] Add Discordeno bot tutorials to YouTube tutorials section --- docs/content/gettingstarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index f26820c9c..8ff950890 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -16,7 +16,6 @@ This website serves as the purpose for introducing Discordeno to developers. The - [GitHub Repository](https://github.com/Skillz4Killz/Discordeno) - [Deno Page](https://deno.land/x/discordeno) - [Website](https://discordeno.js.org/) -- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) ## Requirements @@ -91,6 +90,7 @@ Web-Mystery Tutorials: - Running a Discord bot written in Deno in Docker YouTube Tutorials: +- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) - Coming soon to [NTM Development](https://www.youtube.com/channel/UCkOFck-WCQtolha4NJuK7zA/) --- From 1dd7472934c350679805755b67bdff4a8b018175 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:24:14 +0400 Subject: [PATCH 079/123] Remove link to cease free advertising --- docs/content/gettingstarted.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index 8ff950890..4892df5f2 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -91,7 +91,6 @@ Web-Mystery Tutorials: YouTube Tutorials: - [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) -- Coming soon to [NTM Development](https://www.youtube.com/channel/UCkOFck-WCQtolha4NJuK7zA/) --- From 1fa5d08370b5b529db0b39a469674891d79bb945 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 12 Nov 2020 08:32:32 -0500 Subject: [PATCH 080/123] editBotProfile --- src/constants/discord.ts | 1 + src/handlers/member.ts | 34 +++++++++++++++++++++++++++++++++- src/types/errors.ts | 4 ++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/constants/discord.ts b/src/constants/discord.ts index fe9a98da6..fa334574b 100644 --- a/src/constants/discord.ts +++ b/src/constants/discord.ts @@ -96,6 +96,7 @@ export const endpoints = { // User endpoints USER: (id: string) => `${baseEndpoints.BASE_URL}/users/${id}`, + USER_BOT: `${baseEndpoints.BASE_URL}/users/@me`, USER_AVATAR: (id: string, icon: string) => `${baseEndpoints.CDN_URL}/avatars/${id}/${icon}`, USER_DEFAULT_AVATAR: (icon: number) => diff --git a/src/handlers/member.ts b/src/handlers/member.ts index 803a83cec..0949e65a4 100644 --- a/src/handlers/member.ts +++ b/src/handlers/member.ts @@ -15,6 +15,7 @@ import { higherRolePosition, highestRole, } from "../utils/permissions.ts"; +import { urlToBase64 } from "../utils/utils.ts"; import { sendMessage } from "./channel.ts"; /** The users custom avatar or the default avatar if you don't have a member object. */ @@ -184,7 +185,7 @@ export function editMember( ); } -/** +/** * Move a member from a voice channel to another. * @param guildID the id of the guild which the channel exists in * @param memberID the id of the member to move. @@ -197,3 +198,34 @@ export function moveMember( ) { return editMember(guildID, memberID, { channel_id: channelID }); } + +/** Modifies the bot's username or avatar. + * NOTE: username: if changed may cause the bot's discriminator to be randomized. + */ +export function editBotProfile(username?: string, avatarURL?: string) { + // Nothing was edited + if (!username && !avatarURL) return; + // Check username requirements if username was provided + if (username) { + if (username.length > 32) { + throw new Error(Errors.USERNAME_MAX_LENGTH); + } + if (username.length < 2) { + throw new Error(Errors.USERNAME_MIN_LENGTH); + } + if (["@", "#", ":", "```"].some((char) => username.includes(char))) { + throw new Error(Errors.USERNAME_INVALID_CHARACTER); + } + if (["discordtag", "everyone", "here"].includes(username)) { + throw new Error(Errors.USERNAME_INVALID_USERNAME); + } + } + + RequestManager.patch( + endpoints.USER_BOT, + { + username: username?.trim(), + avatar: avatarURL ? urlToBase64(avatarURL) : undefined, + }, + ); +} diff --git a/src/types/errors.ts b/src/types/errors.ts index 98df112d2..5ed296520 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -33,4 +33,8 @@ export enum Errors { INVALID_WEBHOOK_OPTIONS = "INVALID_WEBHOOK_OPTIONS", CHANNEL_NOT_FOUND = "CHANNEL_NOT_FOUND", CHANNEL_NOT_TEXT_BASED = "CHANNEL_NOT_TEXT_BASED", + USERNAME_MAX_LENGTH = "USERNAME_MAX_LENGTH", + USERNAME_MIN_LENGTH = "USERNAME_MIN_LENGTH", + USERNAME_INVALID_CHARACTER = "USERNAME_INVALID_CHARACTER", + USERNAME_INVALID_USERNAME = "USERNAME_INVALID_USERNAME", } From 4ec74fb36d1e589a4bbff73038f018098d032fdc Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:21:33 +0400 Subject: [PATCH 081/123] Add reason parameter to editChannel() --- src/handlers/channel.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 8a77101e4..d8ce6333b 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -329,6 +329,7 @@ function processEditChannelQueue() { export async function editChannel( channelID: string, options: ChannelEditOptions, + reason: string, ) { const hasManageChannelsPerm = await botHasChannelPermissions( channelID, @@ -389,7 +390,10 @@ export async function editChannel( return RequestManager.patch( endpoints.GUILD_CHANNEL(channelID), - payload, + { + ...payload, + reason, + }, ); } From 67b9dc96b443f899696dc14eb601da614b1e1398 Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:25:00 +0400 Subject: [PATCH 082/123] Make reason parameter optional --- src/handlers/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index d8ce6333b..23803aef4 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -329,7 +329,7 @@ function processEditChannelQueue() { export async function editChannel( channelID: string, options: ChannelEditOptions, - reason: string, + reason?: string, ) { const hasManageChannelsPerm = await botHasChannelPermissions( channelID, From b7d8b30b1f3eaaffe92925b839d669a3ba0c781f Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:30:51 +0400 Subject: [PATCH 083/123] Testing/Linting -> Lint --- .github/workflows/deno.yml | 27 ++++----------------------- README.md | 2 +- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/.github/workflows/deno.yml b/.github/workflows/deno.yml index f34093188..68641aeaa 100644 --- a/.github/workflows/deno.yml +++ b/.github/workflows/deno.yml @@ -1,35 +1,16 @@ -# This is a basic workflow to help you get started with Actions - -name: Testing/Linting - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch +name: Lint on: push: branches: [master] pull_request: branches: [master] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: - # The type of runner that the job will run on runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - - - name: Setup Deno environment - uses: denolib/setup-deno@master - - - name: Deno Fetch + - uses: denolib/setup-deno@master + - name: Cache the dependencies run: deno cache mod.ts - - - name: Deno Format Check + - name: Run format script with --check run: deno fmt *.ts --check - - - name: Deno Format Check src/ - run: deno fmt src/* --check diff --git a/README.md b/README.md index 3cd062456..1f59e2281 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > Discord API library wrapper in Deno [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=dark)](https://discord.gg/J4NqJ72) -![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) +![Lint](https://github.com/Skillz4Killz/Discordeno/workflows/Lint/badge.svg) ![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) From 0ea9dbc7c45a7500b60827b5c9e0e4f856ab8cb5 Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:31:25 +0400 Subject: [PATCH 084/123] deno.yml -> lint.yml --- .github/workflows/{deno.yml => lint.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{deno.yml => lint.yml} (100%) diff --git a/.github/workflows/deno.yml b/.github/workflows/lint.yml similarity index 100% rename from .github/workflows/deno.yml rename to .github/workflows/lint.yml From bf0f32769161223ea74e67ccc7373057e117df75 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 12 Nov 2020 22:49:45 -0500 Subject: [PATCH 085/123] add dispatchRequirements --- src/module/shardingManager.ts | 1 + src/types/options.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/module/shardingManager.ts b/src/module/shardingManager.ts index e95ed6c0d..478c216c5 100644 --- a/src/module/shardingManager.ts +++ b/src/module/shardingManager.ts @@ -90,6 +90,7 @@ export async function handleDiscordPayload( shardID: number, ) { eventHandlers.raw?.(data); + await eventHandlers.dispatchRequirements?.(data); switch (data.op) { case GatewayOpcode.HeartbeatACK: diff --git a/src/types/options.ts b/src/types/options.ts index f3c66fc01..ddcd8ce38 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -83,6 +83,7 @@ export interface EventHandlers { channelUpdate?: (channel: Channel, cachedChannel: Channel) => unknown; channelDelete?: (channel: Channel) => unknown; debug?: (args: DebugArg) => unknown; + dispatchRequirements?: (data: DiscordPayload) => unknown; guildBanAdd?: (guild: Guild, user: Member | UserPayload) => unknown; guildBanRemove?: (guild: Guild, user: Member | UserPayload) => unknown; guildCreate?: (guild: Guild) => unknown; From c866d127a99cccdf68b8d6c3cc37f3e41a633412 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 13:10:44 +0400 Subject: [PATCH 086/123] Idk --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 68641aeaa..f16d35b38 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,4 +13,4 @@ jobs: - name: Cache the dependencies run: deno cache mod.ts - name: Run format script with --check - run: deno fmt *.ts --check + run: deno fmt --ignore=./docs --check From cb8a9353eb912863b27cd302f0646298309bf079 Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 08:29:20 -0500 Subject: [PATCH 087/123] add getGuild function --- src/handlers/guild.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 385b2c017..a0865d759 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -24,6 +24,7 @@ import { PositionSwap, PruneOptions, PrunePayload, + UpdateGuildPayload, UserPayload, } from "../types/guild.ts"; import { MemberCreatePayload } from "../types/member.ts"; @@ -607,3 +608,14 @@ export function getWebhooks(guildID: string) { export function getUser(userID: string) { return RequestManager.get(endpoints.USER(userID)) as Promise; } + +/** + * ⚠️ **If you need this, you are probably doing something wrong. Always use cache.guilds.get() + * + * Advanced Devs: + * This function fetches a guild's data. This is not the same data as a GUILD_CREATE. + * So it does not cache the guild, you must do it manually. + * */ +export function getGuild(guildID: string, counts = true) { + return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise +} From d73cd38c6c7de579b5fe23c5a3f139d2f734c200 Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 08:38:31 -0500 Subject: [PATCH 088/123] add shardID to dispatch event --- src/module/shardingManager.ts | 2 +- src/types/options.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/shardingManager.ts b/src/module/shardingManager.ts index 478c216c5..e955bb12e 100644 --- a/src/module/shardingManager.ts +++ b/src/module/shardingManager.ts @@ -90,7 +90,7 @@ export async function handleDiscordPayload( shardID: number, ) { eventHandlers.raw?.(data); - await eventHandlers.dispatchRequirements?.(data); + await eventHandlers.dispatchRequirements?.(data, shardID); switch (data.op) { case GatewayOpcode.HeartbeatACK: diff --git a/src/types/options.ts b/src/types/options.ts index ddcd8ce38..75f6f739d 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -83,7 +83,7 @@ export interface EventHandlers { channelUpdate?: (channel: Channel, cachedChannel: Channel) => unknown; channelDelete?: (channel: Channel) => unknown; debug?: (args: DebugArg) => unknown; - dispatchRequirements?: (data: DiscordPayload) => unknown; + dispatchRequirements?: (data: DiscordPayload, shardID: number) => unknown; guildBanAdd?: (guild: Guild, user: Member | UserPayload) => unknown; guildBanRemove?: (guild: Guild, user: Member | UserPayload) => unknown; guildCreate?: (guild: Guild) => unknown; From e73a09918c2ef330c533bc15dd33a548c2326ba3 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 18:04:07 +0400 Subject: [PATCH 089/123] New function isChannelSynced(channelID: string) --- src/handlers/channel.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 23803aef4..b74965be7 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -421,3 +421,30 @@ export async function followChannel( return data.webhook_id; } + +/** + * Checks whether a channel is synchronized with its parent/category channel or not. + * @param channelID The ID of the channel to test for synchronization + * @return Returns `true` if the channel is synchronized, otherwise `false`. Returns `false` if the channel is not cached. + */ +export async function isChannelSynced(channelID: string) { + const channel = await cacheHandlers.get("channels", channelID); + if (!channel?.parentID) return false; + + const parentChannel = await cacheHandlers.get("channels", channel.parentID); + if (!parentChannel) return false; + + return channel.permission_overwrites?.every((overwrite) => { + const permission = parentChannel.permission_overwrites?.find((ow) => + ow.id === overwrite.id + ); + if (!permission) return false; + if ( + overwrite.allow !== permission.allow || overwrite.deny !== permission.deny + ) { + return false; + } + + return true; + }); +} From 49815b579dd45f70be49cce704056d206031f7d4 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 18:09:27 +0400 Subject: [PATCH 090/123] Linted code --- src/handlers/guild.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index a0865d759..47385b112 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -617,5 +617,8 @@ export function getUser(userID: string) { * So it does not cache the guild, you must do it manually. * */ export function getGuild(guildID: string, counts = true) { - return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise + return RequestManager.get( + endpoints.GUILD(guildID), + { with_counts: counts }, + ) as Promise; } From a3d0c02d679e032078f57a2d6e91553813c0fa6a Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 12:24:04 -0500 Subject: [PATCH 091/123] fmt --- src/handlers/guild.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index a0865d759..47385b112 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -617,5 +617,8 @@ export function getUser(userID: string) { * So it does not cache the guild, you must do it manually. * */ export function getGuild(guildID: string, counts = true) { - return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise + return RequestManager.get( + endpoints.GUILD(guildID), + { with_counts: counts }, + ) as Promise; } From f9fddf7621a619860ddc681aa41604b535878561 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 22:53:54 +0400 Subject: [PATCH 092/123] =?UTF-8?q?Server=20Templates=20=F0=9F=8E=89?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/handlers/guild.ts | 28 ++++++++++++++++++++++++++++ src/types/guild.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 47385b112..8db3f76ea 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -622,3 +622,31 @@ export function getGuild(guildID: string, counts = true) { { with_counts: counts }, ) as Promise; } + +/** + * Get a template by its code + * @param code The code of the template + */ +export function getTemplate(code: string) { + const endpoint = `${endpoints.GUILDS}/templates/${code}`; + return RequestManager.get(endpoint); +} + +/** + * Create a new guild based on a template. + * NOTE: This endpoint can be used only by bots in less than 10 guilds. + * @param code the code of the template to create a new guild from + * @param name name of the guild (2-100 characters) + * @param icon base64 128x128 image for the guild icon + */ +export function createGuildFromTemplate( + code: string, + name: string, + icon?: any, +) { + const endpoint = `${endpoints.GUILDS}/templates/${code}`; + return RequestManager.post(endpoint, { + name, + icon, + }); +} diff --git a/src/types/guild.ts b/src/types/guild.ts index 7bcd4991e..e1a903fe7 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -1,3 +1,4 @@ +import { Guild } from "../structures/guild.ts"; import { ChannelCreatePayload, ChannelTypes } from "./channel.ts"; import { Emoji, StatusType } from "./discord.ts"; import { MemberCreatePayload } from "./member.ts"; @@ -606,3 +607,29 @@ export interface CreateServerOptions { /** the id of the channel where guild notices such as welcome messages and boost events are posted */ system_channel_id?: string; } + +// https://discord.com/developers/docs/resources/template#template-object +export interface GuildTemplate { + /** the template code (unique ID) */ + code: string; + /** template name */ + name: string; + /** the description for the template */ + description: string | null; + /** number of times this template has been used */ + usage_count: number; + /** the ID of the user who created the template */ + creator_id: string; + /** the user who created the template */ + user: UserPayload; + /** when this template was created */ + created_at: string; + /** when this template was last synced to the source guild */ + updated_at: string; + /** the ID of the guild this template is based on */ + source_guild_id: string; + /** the guild snapshot this template contains */ + serialized_source_guild: Guild; + /** whether the template has unsynced changes */ + is_dirty: boolean | null; +} From 985a4358f91071ba3e116e39edb303202c78c78d Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 23:41:41 +0400 Subject: [PATCH 093/123] Rename GuildTemplate interface to Template --- src/types/guild.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/guild.ts b/src/types/guild.ts index e1a903fe7..b3d64044a 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -609,7 +609,7 @@ export interface CreateServerOptions { } // https://discord.com/developers/docs/resources/template#template-object -export interface GuildTemplate { +export interface Template { /** the template code (unique ID) */ code: string; /** template name */ From 1f2c5853de273d2599f7fda24833800eaa06e265 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 00:10:13 +0400 Subject: [PATCH 094/123] =?UTF-8?q?=F0=9F=8E=89=20Server=20Templates=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/discord.ts | 3 ++ src/handlers/guild.ts | 101 ++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/constants/discord.ts b/src/constants/discord.ts index fa334574b..3cf526388 100644 --- a/src/constants/discord.ts +++ b/src/constants/discord.ts @@ -89,6 +89,9 @@ export const endpoints = { `${baseEndpoints.CDN_URL}/splashes/${id}/${icon}`, GUILD_VANITY_URL: (id: string) => `${GUILDS_BASE(id)}/vanity-url`, GUILD_WEBHOOKS: (id: string) => `${GUILDS_BASE(id)}/webhooks`, + GUILD_TEMPLATE: (code: string) => + `${baseEndpoints.BASE_URL}/guilds/templates/${code}`, + GUILD_TEMPLATES: (id: string) => `${GUILDS_BASE(id)}/templates`, WEBHOOK: (id: string, token: string) => `${baseEndpoints.BASE_URL}/webhooks/${id}/${token}`, diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 8db3f76ea..e3919cd22 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -623,30 +623,99 @@ export function getGuild(guildID: string, counts = true) { ) as Promise; } -/** - * Get a template by its code - * @param code The code of the template +/** + * Returns the guild template if it exists + * @param guildID The ID of the guild + * @param code The code of the template to get */ -export function getTemplate(code: string) { - const endpoint = `${endpoints.GUILDS}/templates/${code}`; +export function getGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; return RequestManager.get(endpoint); } /** - * Create a new guild based on a template. + * Create a new guild based on a template * NOTE: This endpoint can be used only by bots in less than 10 guilds. - * @param code the code of the template to create a new guild from - * @param name name of the guild (2-100 characters) - * @param icon base64 128x128 image for the guild icon + * @param code The code of the template to create a guild from */ export function createGuildFromTemplate( code: string, - name: string, - icon?: any, + data: CreateGuildFromTemplate, ) { - const endpoint = `${endpoints.GUILDS}/templates/${code}`; - return RequestManager.post(endpoint, { - name, - icon, - }); + return RequestManager.post(endpoints.GUILD_TEMPLATE(code), data); +} + +export interface CreateGuildFromTemplate { + /** name of the guild (2-100 characters) */ + name: string; + /** base64 128x128 image for the guild icon */ + icon?: string; +} + +/** + * Returns an array of guild templates + * @param guildID The ID of the guild + */ +export function getGuildTemplates(guildID: string) { + return RequestManager.get(endpoints.GUILD_TEMPLATES(guildID)); +} + +/** + * Deletes a template from a guild + * @param guildID The guild ID to delete the template from + */ +export function deleteGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.delete(endpoint); +} + +/** + * Creates a template for the guild + * @param guildID The ID of the guild to create a template in + * @param name name of the template (1-100 characters) + * @param description description for the template (0-120 characters + */ +export function createGuildTemplate( + guildID: string, + data: CreateGuildTemplate, +) { + return RequestManager.post(endpoints.GUILD_TEMPLATES(guildID), data); +} + +export interface CreateGuildTemplate { + /** name of the template (1-100 characters) */ + name: string; + /** description for the template (0-120 characters) */ + description?: string | null; +} + +/** + * Syncs the template to the guild's current state + * @param guildID The ID of the guild + * @param code The code of the template to sync + */ +export function syncGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.put(endpoint); +} + +/** + * Edit a template's metadata + * @param guildID The ID of the guild + * @param code The code of the template to edit + */ +export function editGuildTemplate( + guildID: string, + code: string, + data: EditGuildTemplate, +) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.patch(endpoint, data); +} + +export interface EditGuildTemplate { + /** name of the template (1-100 characters) */ + name?: string; + /** description for the template (0-120 characters) */ + description?: string | null; } From dd60de628c011c295453d8dfa1d32267148d593d Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 00:41:25 +0400 Subject: [PATCH 095/123] Rename code parameter to templateCode to reduce ambiguity --- src/handlers/guild.ts | 49 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index e3919cd22..979492b63 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -623,26 +623,21 @@ export function getGuild(guildID: string, counts = true) { ) as Promise; } -/** - * Returns the guild template if it exists - * @param guildID The ID of the guild - * @param code The code of the template to get - */ -export function getGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Returns the guild template if it exists */ +export function getGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.get(endpoint); } /** * Create a new guild based on a template * NOTE: This endpoint can be used only by bots in less than 10 guilds. - * @param code The code of the template to create a guild from */ export function createGuildFromTemplate( - code: string, + templateCode: string, data: CreateGuildFromTemplate, ) { - return RequestManager.post(endpoints.GUILD_TEMPLATE(code), data); + return RequestManager.post(endpoints.GUILD_TEMPLATE(templateCode), data); } export interface CreateGuildFromTemplate { @@ -652,20 +647,14 @@ export interface CreateGuildFromTemplate { icon?: string; } -/** - * Returns an array of guild templates - * @param guildID The ID of the guild - */ +/** Returns an array of guild templates */ export function getGuildTemplates(guildID: string) { return RequestManager.get(endpoints.GUILD_TEMPLATES(guildID)); } -/** - * Deletes a template from a guild - * @param guildID The guild ID to delete the template from - */ -export function deleteGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Deletes a template from a guild */ +export function deleteGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.delete(endpoint); } @@ -689,27 +678,19 @@ export interface CreateGuildTemplate { description?: string | null; } -/** - * Syncs the template to the guild's current state - * @param guildID The ID of the guild - * @param code The code of the template to sync - */ -export function syncGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Syncs the template to the guild's current state */ +export function syncGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.put(endpoint); } -/** - * Edit a template's metadata - * @param guildID The ID of the guild - * @param code The code of the template to edit - */ +/** Edit a template's metadata */ export function editGuildTemplate( guildID: string, - code: string, + templateCode: string, data: EditGuildTemplate, ) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.patch(endpoint, data); } From 9c5031259f7bf89b496e4190579389f5e8f86d7a Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 10:43:08 +0400 Subject: [PATCH 096/123] Embed endpoint into function instead of assigning to var --- src/handlers/guild.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 979492b63..df17cff35 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -625,8 +625,9 @@ export function getGuild(guildID: string, counts = true) { /** Returns the guild template if it exists */ export function getGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.get(endpoint); + return RequestManager.get( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** @@ -654,8 +655,9 @@ export function getGuildTemplates(guildID: string) { /** Deletes a template from a guild */ export function deleteGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.delete(endpoint); + return RequestManager.delete( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** @@ -680,8 +682,9 @@ export interface CreateGuildTemplate { /** Syncs the template to the guild's current state */ export function syncGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.put(endpoint); + return RequestManager.put( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** Edit a template's metadata */ @@ -690,8 +693,10 @@ export function editGuildTemplate( templateCode: string, data: EditGuildTemplate, ) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.patch(endpoint, data); + return RequestManager.patch( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + data, + ); } export interface EditGuildTemplate { From d31cf09c64a2927c22e2979b7b128026a1c43c12 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 10:44:58 +0400 Subject: [PATCH 097/123] Better types for getGuildTemplate() --- src/handlers/guild.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index df17cff35..1d227f79d 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -24,6 +24,7 @@ import { PositionSwap, PruneOptions, PrunePayload, + Template, UpdateGuildPayload, UserPayload, } from "../types/guild.ts"; @@ -624,10 +625,13 @@ export function getGuild(guildID: string, counts = true) { } /** Returns the guild template if it exists */ -export function getGuildTemplate(guildID: string, templateCode: string) { +export function getGuildTemplate( + guildID: string, + templateCode: string, +): Promise