From 19941ac50ed1613e01618165dd57116cadd576a3 Mon Sep 17 00:00:00 2001 From: chroventer Date: Thu, 24 Sep 2020 11:14:12 -0700 Subject: [PATCH 01/74] 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 02/74] 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 03/74] 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 04/74] 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 05/74] 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 06/74] 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 07/74] 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 08/74] 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 09/74] 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 10/74] 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 11/74] =?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 12/74] 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 13/74] 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 14/74] 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 15/74] 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 16/74] 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 17/74] 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 18/74] 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 19/74] 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 82183d67395d940857941dd00530df8224f26c33 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 12 Oct 2020 12:10:40 -0400 Subject: [PATCH 20/74] test fix --- docs/content/gettingstarted.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index 009065154..41621b834 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -74,7 +74,8 @@ Alternatively, you can use boilerplate template repositories that were created b | Official Boilerplate | Skillz4Killz#4500 | [GitHub](https://github.com/Skillz4Killz/Discordeno-bot-template), [Support Server](https://discord.gg/J4NqJ72) | This is a very minimalistic design for a boilerplate for your bot to get you started. | | DenoBot | NTM Nathan#0001 | [GitHub](https://github.com/ntm-development/DenoBot), [Support Server](https://discord.com/invite/G2rb53z) | Another boilerplate example of the first one, with more commands and improvements. | -Open Sourced Bots: +**Open Sourced Bots:** + | Bot Name | Developer | Links | | ----------------- | ---------- | ---------------------------------------------------------- | | discordeno-mattis | Mattis6666 | [Github](https://github.com/Mattis6666/discordeno-mattis/) | From 13ff5f854c14e4ac70eb618b957d383e03d2bd47 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 14 Oct 2020 21:07:01 -0400 Subject: [PATCH 21/74] add user reviews section --- docs/content/introduction.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/content/introduction.md b/docs/content/introduction.md index 29c6b408c..0c2f6524b 100644 --- a/docs/content/introduction.md +++ b/docs/content/introduction.md @@ -19,6 +19,11 @@ Discordeno is a Third Party Deno Library for interacting with the Discord API. - Latest and Greatest JavaScript - Actively Maintained! +### User Reviews + +If you wish to leave a review for other users, please send a PR adding your review to this section! + + ## Read me first... Discordeno is cool right? You could make the next big bot! Who knows, but before we get right into developing our Bot. We want to get started with learning the basics... From d68f5d8ea09d8770a66c4bebcf381d96c643839f Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 14 Oct 2020 21:08:13 -0400 Subject: [PATCH 22/74] ack handling --- src/module/basicShard.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index d55ad72c5..84d4f9c9f 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -20,8 +20,10 @@ import { botGatewayData, eventHandlers } from "./client.ts"; import { handleDiscordPayload } from "./shardingManager.ts"; const basicShards = new Map(); -const heartbeating = new Set(); +const heartbeating = new Map(); const utf8decoder = new TextDecoder(); +const RequestMembersQueue: RequestMemberQueuedRequest[] = []; +let processQueue = false; export interface BasicShard { id: number; @@ -32,9 +34,6 @@ export interface BasicShard { needToResume: boolean; } -const RequestMembersQueue: RequestMemberQueuedRequest[] = []; -let processQueue = false; - interface RequestMemberQueuedRequest { guildID: string; shardID: number; @@ -126,6 +125,9 @@ export async function createBasicShard( ); } break; + case GatewayOpcode.HeartbeatACK: + heartbeating.set(shardID, true); + break; case GatewayOpcode.Reconnect: eventHandlers.debug?.( { type: "reconnect", data: { shardID: basicShard.id } }, @@ -200,7 +202,6 @@ function resume(shard: BasicShard, payload: IdentifyPayload) { })); } -// TODO: If a client does not receive a heartbeat ack between its attempts at sending heartbeats, it should immediately terminate the connection with a non-1000 close code, reconnect, and attempt to resume. async function heartbeat( shard: BasicShard, interval: number, @@ -210,7 +211,13 @@ async function heartbeat( return; } - if (!heartbeating.has(shard.id)) heartbeating.add(shard.id); + if (!heartbeating.has(shard.id)) heartbeating.set(shard.id, false); + else { + const receivedACK = heartbeating.get(shard.id); + if (!receivedACK) { + shard.socket.send(JSON.stringify({ op: 4009 })); + } + } shard.socket.send( JSON.stringify( From 4060dbee2ba63d525ce34b14702bb24dcfd752e3 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 14 Oct 2020 21:17:15 -0400 Subject: [PATCH 23/74] small fixes --- src/module/basicShard.ts | 19 ++++++++++++++++--- src/types/options.ts | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index 84d4f9c9f..ea7de1acd 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -211,14 +211,27 @@ async function heartbeat( return; } - if (!heartbeating.has(shard.id)) heartbeating.set(shard.id, false); - else { + if (heartbeating.has(shard.id)) { const receivedACK = heartbeating.get(shard.id); + // If a ACK response was not received since last heartbeat, issue invalid session close if (!receivedACK) { - shard.socket.send(JSON.stringify({ op: 4009 })); + eventHandlers.debug?.( + { + type: "heartbeatStopped", + data: { + interval, + previousSequenceNumber: shard.previousSequenceNumber, + shardID: shard.id, + }, + }, + ); + return shard.socket.send(JSON.stringify({ op: 4009 })); } } + // Set it to false as we are issuing a new heartbeat + heartbeating.set(shard.id, false); + shard.socket.send( JSON.stringify( { op: GatewayOpcode.Heartbeat, d: shard.previousSequenceNumber }, diff --git a/src/types/options.ts b/src/types/options.ts index 4b57be9f4..641432ada 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -64,6 +64,7 @@ export interface DebugArg { | "requestManagerFetched" | "requestMembersProcessing" | "heartbeat" + | "heartbeatStopped" | "createShard" | "invalidSession" | "reconnect" From 509d60346cb43c2ffb58853e146b196e55f84597 Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 16 Oct 2020 13:04:14 -0400 Subject: [PATCH 24/74] fix dynamic command nsfw stuff --- docs/content/advanced/dynamiccommands.md | 75 ++++++++++++------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/docs/content/advanced/dynamiccommands.md b/docs/content/advanced/dynamiccommands.md index 313ee0719..a68da76e1 100644 --- a/docs/content/advanced/dynamiccommands.md +++ b/docs/content/advanced/dynamiccommands.md @@ -54,43 +54,44 @@ const nekosEndpoints = [ { name: "gecg", path: "/img/gecg", nsfw: false }, { name: "avatar", path: "/img/avatar", nsfw: false }, { name: "waifu", path: "/img/waifu", nsfw: false }, - { name: "randomHentaiGif", path: "/img/Random_hentai_gif", nsfw: true }, - { name: "pussy", path: "/img/pussy", nsfw: true }, - { name: "nekoGif", path: "/img/nsfw_neko_gif", nsfw: true }, - { name: "neko", path: "/img/lewd", nsfw: true }, - { name: "lesbian", path: "/img/les", nsfw: true }, - { name: "kuni", path: "/img/kuni", nsfw: true }, - { name: "cumsluts", path: "/img/cum", nsfw: true }, - { name: "classic", path: "/img/classic", nsfw: true }, - { name: "boobs", path: "/img/boobs", nsfw: true }, - { name: "bJ", path: "/img/bj", nsfw: true }, - { name: "anal", path: "/img/anal", nsfw: true }, - { name: "avatar", path: "/img/nsfw_avatar", nsfw: true }, - { name: "yuri", path: "/img/yuri", nsfw: true }, - { name: "trap", path: "/img/trap", nsfw: true }, - { name: "tits", path: "/img/tits", nsfw: true }, - { name: "girlSoloGif", path: "/img/solog", nsfw: true }, - { name: "girlSolo", path: "/img/solo", nsfw: true }, - { name: "pussyWankGif", path: "/img/pwankg", nsfw: true }, - { name: "pussyArt", path: "/img/pussy_jpg", nsfw: true }, - { name: "kemonomimi", path: "/img/lewdkemo", nsfw: true }, - { name: "kitsune", path: "/img/lewdk", nsfw: true }, - { name: "keta", path: "/img/keta", nsfw: true }, - { name: "holo", path: "/img/hololewd", nsfw: true }, - { name: "holoEro", path: "/img/holoero", nsfw: true }, - { name: "hentai", path: "/img/hentai", nsfw: true }, - { name: "futanari", path: "/img/futanari", nsfw: true }, - { name: "femdom", path: "/img/femdom", nsfw: true }, - { name: "feetGif", path: "/img/feetg", nsfw: true }, - { name: "eroFeet", path: "/img/erofeet", nsfw: true }, - { name: "feet", path: "/img/feet", nsfw: true }, - { name: "ero", path: "/img/ero", nsfw: true }, - { name: "eroKitsune", path: "/img/erok", nsfw: true }, - { name: "eroKemonomimi", path: "/img/erokemo", nsfw: true }, - { name: "eroNeko", path: "/img/eron", nsfw: true }, - { name: "eroYuri", path: "/img/eroyuri", nsfw: true }, - { name: "cumArts", path: "/img/cum_jpg", nsfw: true }, - { name: "blowJob", path: "/img/blowjob", nsfw: true }, + // The follow name and paths have been hidden for this guide as they are NSFW. + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, ]; nekosEndpoints.forEach((endpoint) => { From a804f293b754c205456c741244f3267da7d88524 Mon Sep 17 00:00:00 2001 From: Bryan Berger Date: Fri, 16 Oct 2020 15:15:52 -0400 Subject: [PATCH 25/74] fix: resume connect of shard socket if lost between heartbeats --- src/module/basicShard.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/module/basicShard.ts b/src/module/basicShard.ts index ea7de1acd..959c3f188 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -122,6 +122,7 @@ export async function createBasicShard( heartbeat( basicShard, (data.d as DiscordHeartbeatPayload).heartbeat_interval, + identifyPayload, ); } break; @@ -205,8 +206,12 @@ function resume(shard: BasicShard, payload: IdentifyPayload) { async function heartbeat( shard: BasicShard, interval: number, + payload: IdentifyPayload ) { + // We lost socket connection between heartbeats, resume connection if (shard.socket.isClosed) { + shard.needToResume = true; + resumeConnection(botGatewayData, payload, shard.id); heartbeating.delete(shard.id); return; } @@ -248,7 +253,7 @@ async function heartbeat( }, ); await delay(interval); - heartbeat(shard, interval); + heartbeat(shard, interval, payload); } async function resumeConnection( From 80156b80d153407ea034617b48659dbfaa48e3d0 Mon Sep 17 00:00:00 2001 From: Bryan Berger Date: Fri, 16 Oct 2020 15:33:33 -0400 Subject: [PATCH 26/74] fix: comma --- 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 959c3f188..60717ca3c 100644 --- a/src/module/basicShard.ts +++ b/src/module/basicShard.ts @@ -206,7 +206,7 @@ function resume(shard: BasicShard, payload: IdentifyPayload) { async function heartbeat( shard: BasicShard, interval: number, - payload: IdentifyPayload + payload: IdentifyPayload, ) { // We lost socket connection between heartbeats, resume connection if (shard.socket.isClosed) { From a376d8fe9f5f62e971c9465eac0bde085af94eef Mon Sep 17 00:00:00 2001 From: Skillz Date: Tue, 20 Oct 2020 09:00:01 -0400 Subject: [PATCH 27/74] publish to egs --- egg.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/egg.yml b/egg.yml index aaacd0120..5bf99cdbd 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.1 +version: 9.0.2 stable: true -entry: /mod.ts +entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' files: - ./src/**/* @@ -13,7 +13,5 @@ files: - README.md - tsconfig.json - ./deps.ts - - ./mod.ts - - ./mod.ts checkAll: false unlisted: false From eb6ea07906a1ac2a6efa57bf519ba6333c1d4de3 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 21 Oct 2020 12:38:20 -0400 Subject: [PATCH 28/74] latest eggs --- egg.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egg.yml b/egg.yml index 5bf99cdbd..1c425d705 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.2 +version: 9.0.3 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' From 954931cb1a90cfcb067e8d38e9b6a08f03533dfa Mon Sep 17 00:00:00 2001 From: Lukas Does Dev <51633285+LukasDoesDev@users.noreply.github.com> Date: Fri, 23 Oct 2020 19:51:08 +0300 Subject: [PATCH 29/74] Update introduction.md --- docs/content/introduction.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content/introduction.md b/docs/content/introduction.md index 0c2f6524b..effb978f7 100644 --- a/docs/content/introduction.md +++ b/docs/content/introduction.md @@ -23,6 +23,7 @@ Discordeno is a Third Party Deno Library for interacting with the Discord API. If you wish to leave a review for other users, please send a PR adding your review to this section! +Using the Discord API with types but such a simple language like TypeScript is so easy now. Discordeno is A W E S O M E! -[LukasDoesDev](https://github.com/LukasDoesDev) ## Read me first... Discordeno is cool right? You could make the next big bot! Who knows, but before we get right into developing our Bot. We want to get started with learning the basics... From 2ed1c8b72d367838465221bb92f61cffc2d6c504 Mon Sep 17 00:00:00 2001 From: chroventer Date: Sat, 24 Oct 2020 18:24:37 +0400 Subject: [PATCH 30/74] fix: guildMemberRemove event triggered twice --- src/controllers/members.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/controllers/members.ts b/src/controllers/members.ts index 6d413f90f..0083f158f 100644 --- a/src/controllers/members.ts +++ b/src/controllers/members.ts @@ -41,11 +41,6 @@ export async function handleInternalGuildMemberRemove(data: DiscordPayload) { member || payload.user, ); - eventHandlers.guildMemberRemove?.( - guild, - member || payload.user, - ); - guild.members.delete(payload.user.id); } From 45c8fe668de75f42ceb81fc90a43cba01591d175 Mon Sep 17 00:00:00 2001 From: Skillz Date: Sat, 24 Oct 2020 10:31:32 -0400 Subject: [PATCH 31/74] cleaner type --- src/structures/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/channel.ts b/src/structures/channel.ts index 64e77ef9b..00e28eaff 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -20,7 +20,7 @@ export async function createChannel( const channel = { ...rest, /** The guild id of the channel if it is a guild channel. */ - guildID: guildID || rawGuildID, + guildID: guildID || rawGuildID || "", /** The id of the last message sent in this channel */ lastMessageID, /** The amount of users allowed in this voice channel. */ From 7635c98af127426f2e0427b2ffec1183622ccfcb Mon Sep 17 00:00:00 2001 From: Skillz Date: Sat, 24 Oct 2020 10:33:24 -0400 Subject: [PATCH 32/74] egs --- egg.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egg.yml b/egg.yml index 1c425d705..86ddea0a7 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.3 +version: 9.0.4 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' From a81ceff28f7136517a9b0596876b75c08e729c3d Mon Sep 17 00:00:00 2001 From: chroventer Date: Sun, 25 Oct 2020 09:54:40 +0400 Subject: [PATCH 33/74] 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 34/74] 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 35/74] 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 36/74] 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 37/74] 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 38/74] 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 39/74] 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 40/74] 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 41/74] 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 42/74] 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 43/74] 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 44/74] 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 45/74] 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 46/74] 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 47/74] 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 48/74] 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 49/74] 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 50/74] 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 51/74] 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 52/74] 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 53/74] 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 54/74] 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 55/74] 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 56/74] 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 57/74] 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 58/74] 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 59/74] 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 60/74] 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 61/74] 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 62/74] 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 63/74] 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 64/74] 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 65/74] 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 66/74] 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 67/74] 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 68/74] 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 69/74] 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 70/74] 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 47ede28f5d2f4705a4183ec9ed5583acf47191a3 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Thu, 29 Oct 2020 10:38:40 -0700 Subject: [PATCH 71/74] Rename permission_overwrites to permissionOverwrites --- src/handlers/guild.ts | 2 +- src/structures/channel.ts | 2 +- src/types/guild.ts | 2 +- src/utils/permissions.ts | 2 +- tests/mod.test.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 385b2c017..f80780993 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -105,7 +105,7 @@ export async function createGuildChannel( (await RequestManager.post(endpoints.GUILD_CHANNELS(guild.id), { ...options, name, - permission_overwrites: options?.permission_overwrites?.map((perm) => ({ + permission_overwrites: options?.permissionOverwrites?.map((perm) => ({ ...perm, allow: perm.allow.reduce( diff --git a/src/structures/channel.ts b/src/structures/channel.ts index acc29ebb4..cdd6d347b 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -32,7 +32,7 @@ export async function createChannel( /** The last time when a message was pinned in this channel */ lastPinTimestamp, /** The permission overwrites for this channel */ - permissions: data.permission_overwrites + permissionOverwrites: data.permission_overwrites ? data.permission_overwrites.map((perm) => ({ ...perm, allow: calculatePermissions(BigInt(perm.allow)), diff --git a/src/types/guild.ts b/src/types/guild.ts index 7bcd4991e..590428f64 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -487,7 +487,7 @@ export interface ChannelCreateOptions { /** The sorting position of the channel */ position?: number; /** The channel's permission overwrites */ - permission_overwrites?: Overwrite[]; + permissionOverwrites?: Overwrite[]; /** The id of the parent category for the channel */ parent_id?: string; /** Whether the channel is nsfw */ diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 0c4583a34..1902e3387 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -108,7 +108,7 @@ export async function hasChannelPermissions( let everyoneOverwrite: RawOverwrite | undefined; let rolesOverwrites: RawOverwrite[] = []; - for (const overwrite of channel.permission_overwrites || []) { + for (const overwrite of channel.permissionOverwrites || []) { // If the overwrite on this channel is specific to this member if (overwrite.id === memberID) memberOverwrite = overwrite; // If it is the everyone role overwrite diff --git a/tests/mod.test.ts b/tests/mod.test.ts index bfa3169e7..bd966602e 100644 --- a/tests/mod.test.ts +++ b/tests/mod.test.ts @@ -156,7 +156,7 @@ Deno.test({ async fn() { const channel = cache.channels.get(data.channelID); if (!channel) throw "Channel not found"; - assertArrayIncludes(channel.permission_overwrites!, [ + assertArrayIncludes(channel.permissionOverwrites!, [ { id: data.roleID, type: OverwriteType.ROLE, From b1903b1d8cc957fc6298db0d728b5d0a00cdac37 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Thu, 29 Oct 2020 10:50:52 -0700 Subject: [PATCH 72/74] Add _rawPermissionOverwrites property to Channel --- src/structures/channel.ts | 3 +++ src/utils/permissions.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/structures/channel.ts b/src/structures/channel.ts index cdd6d347b..0405dd03b 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -14,6 +14,7 @@ export async function createChannel( rate_limit_per_user: rateLimitPerUser, parent_id: parentID, last_pin_timestamp: lastPinTimestamp, + permission_overwrites, ...rest } = data; @@ -43,6 +44,8 @@ export async function createChannel( nsfw: data.nsfw || false, /** The mention of the channel */ mention: `<#${data.id}>`, + /** Raw permissions */ + _rawPermissionOverwrites: permission_overwrites, }; cacheHandlers.set("channels", data.id, channel); diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 1902e3387..0a3a39543 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -108,7 +108,7 @@ export async function hasChannelPermissions( let everyoneOverwrite: RawOverwrite | undefined; let rolesOverwrites: RawOverwrite[] = []; - for (const overwrite of channel.permissionOverwrites || []) { + for (const overwrite of channel._rawPermissionOverwrites || []) { // If the overwrite on this channel is specific to this member if (overwrite.id === memberID) memberOverwrite = overwrite; // If it is the everyone role overwrite From 4e39f327a51ffb315e0da31c7cf61b131fa267f9 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Thu, 29 Oct 2020 12:19:57 -0700 Subject: [PATCH 73/74] New PermissionOverwrite interface --- src/structures/channel.ts | 16 +++++++++------- src/types/guild.ts | 6 ++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/structures/channel.ts b/src/structures/channel.ts index 0405dd03b..fe8848cc8 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -1,5 +1,6 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { ChannelCreatePayload } from "../types/channel.ts"; +import { PermissionOverwrite } from "../types/guild.ts"; import { Unpromise } from "../types/misc.ts"; import { calculatePermissions } from "../utils/permissions.ts"; @@ -33,13 +34,14 @@ export async function createChannel( /** The last time when a message was pinned in this channel */ lastPinTimestamp, /** The permission overwrites for this channel */ - permissionOverwrites: data.permission_overwrites - ? data.permission_overwrites.map((perm) => ({ - ...perm, - allow: calculatePermissions(BigInt(perm.allow)), - deny: calculatePermissions(BigInt(perm.deny)), - })) - : [], + permissionOverwrites: + (data.permission_overwrites + ? data.permission_overwrites.map((perm) => ({ + ...perm, + allow: calculatePermissions(BigInt(perm.allow)), + deny: calculatePermissions(BigInt(perm.deny)), + })) + : []) as PermissionOverwrite[], /** Whether this channel is nsfw or not */ nsfw: data.nsfw || false, /** The mention of the channel */ diff --git a/src/types/guild.ts b/src/types/guild.ts index 590428f64..ba52fedfd 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -473,6 +473,12 @@ export interface RawOverwrite { deny: number; } +export interface PermissionOverwrite + extends Omit { + allow: Permission[]; + deny: Permission[]; +} + export interface ChannelCreateOptions { /** The type of the channel */ type?: ChannelTypes; From 3060bb5b33c2cff5bb5ea8fea69b94d7f3dd7767 Mon Sep 17 00:00:00 2001 From: ayyanm Date: Thu, 29 Oct 2020 12:36:19 -0700 Subject: [PATCH 74/74] Remove Channel#_rawPermissionOverwrites --- src/structures/channel.ts | 2 -- src/utils/permissions.ts | 31 +++++++++++++++++++------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/structures/channel.ts b/src/structures/channel.ts index fe8848cc8..b36662d2b 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -46,8 +46,6 @@ export async function createChannel( nsfw: data.nsfw || false, /** The mention of the channel */ mention: `<#${data.id}>`, - /** Raw permissions */ - _rawPermissionOverwrites: permission_overwrites, }; cacheHandlers.set("channels", data.id, channel); diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 0a3a39543..2537f3cf2 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -2,7 +2,7 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { botID } from "../module/client.ts"; import { Guild } from "../structures/guild.ts"; import { Role } from "../structures/role.ts"; -import { RawOverwrite } from "../types/guild.ts"; +import { PermissionOverwrite } from "../types/guild.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. */ @@ -104,11 +104,11 @@ export async function hasChannelPermissions( const member = guild.members.get(memberID); if (!member) return false; - let memberOverwrite: RawOverwrite | undefined; - let everyoneOverwrite: RawOverwrite | undefined; - let rolesOverwrites: RawOverwrite[] = []; + let memberOverwrite: PermissionOverwrite | undefined; + let everyoneOverwrite: PermissionOverwrite | undefined; + let rolesOverwrites: PermissionOverwrite[] = []; - for (const overwrite of channel._rawPermissionOverwrites || []) { + for (const overwrite of channel.permissionOverwrites || []) { // If the overwrite on this channel is specific to this member if (overwrite.id === memberID) memberOverwrite = overwrite; // If it is the everyone role overwrite @@ -121,13 +121,16 @@ export async function hasChannelPermissions( // Member perms override everything so we must check them first if (memberOverwrite) { + const allowBits = calculateBits(memberOverwrite.allow); + const denyBits = calculateBits(memberOverwrite.deny); 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; + if (BigInt(denyBits) & BigInt(perm)) return false; // Already allowed perm if (allowedPermissions.has(perm)) continue; + // This perm is allowed so we save it - if (BigInt(memberOverwrite.allow) & BigInt(perm)) { + if (BigInt(allowBits) & BigInt(perm)) { allowedPermissions.add(perm); } } @@ -139,17 +142,19 @@ export async function hasChannelPermissions( if (allowedPermissions.has(perm)) continue; for (const overwrite of rolesOverwrites) { + const allowBits = calculateBits(overwrite.allow); // This perm is allowed so we save it - if (BigInt(overwrite.allow) & BigInt(perm)) { + if (BigInt(allowBits) & BigInt(perm)) { allowedPermissions.add(perm); break; } + const denyBits = calculateBits(overwrite.deny); // If this role denies it we need to save and check if another role allows it, allows > deny - if (BigInt(overwrite.deny) & BigInt(perm)) { + if (BigInt(denyBits) & 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) + BigInt(calculateBits(o.allow)) & BigInt(perm) ); if (isAllowed) continue; // This permission is in fact denied. Since Roles overrule everything below here we can cancel ou here @@ -159,13 +164,15 @@ export async function hasChannelPermissions( } if (everyoneOverwrite) { + const allowBits = calculateBits(everyoneOverwrite.allow); + const denyBits = calculateBits(everyoneOverwrite.deny); for (const perm of permissions) { // Already allowed perm 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; + if (BigInt(denyBits) & BigInt(perm)) return false; // This perm is allowed so we save it - if (BigInt(everyoneOverwrite.allow) & BigInt(perm)) { + if (BigInt(allowBits) & BigInt(perm)) { allowedPermissions.add(perm); } }