From 717d8cd3e397da46a8c248d9f86feebccfc3bb0c Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 5 Nov 2020 23:16:33 -0800 Subject: [PATCH 01/54] Lower the time limit for ready event activation --- src/controllers/misc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/misc.ts b/src/controllers/misc.ts index 54f60991d..66eb2d94b 100644 --- a/src/controllers/misc.ts +++ b/src/controllers/misc.ts @@ -26,8 +26,8 @@ export async function handleInternalReady( // Triggered on each shard eventHandlers.shardReady?.(shardID); if (payload.shard && shardID === payload.shard[1] - 1) { - // Wait 10 seconds to allow all guild create events to be processed - await delay(10000); + // Wait for 5 seconds to allow all guild create events to be processed + await delay(5000); cache.isReady = true; eventHandlers.ready?.(); } From 4254a37467a5bc747302ac93a025361fe2d47bf4 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 6 Nov 2020 09:16:33 -0800 Subject: [PATCH 02/54] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98f27eb16..8c29a044c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The instructions below are meant for advanced developers! Starting with Discordeno is very simple, you can start from scratch without any boilerplates/frameworks: Add this snippet of code into a new TypeScript file: ```typescript -import StartBot, { sendMessage, Intents } from "https://x.nest.land/Discordeno@9.0.1/mod.ts"; +import StartBot, { sendMessage, Intents } from "https://x.nest.land/Discordeno@9.0.15/mod.ts"; import config from "./config.ts"; StartBot({ From efcf567db06ea2a7ee1a20c1a42db7b019f1537a Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 6 Nov 2020 23:16:41 -0800 Subject: [PATCH 03/54] Resolve promise for all botHasChannelPermissions() --- src/handlers/channel.ts | 106 ++++++++++++++++++++++++++++------------ src/handlers/message.ts | 78 ++++++++++++++++++++--------- src/handlers/webhook.ts | 9 ++-- 3 files changed, 137 insertions(+), 56 deletions(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index fa5d7b6dc..8a77101e4 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -43,16 +43,22 @@ export async function getMessage( channelID: string, id: string, ) { + const hasViewChannelPerm = await botHasChannelPermissions( + channelID, + [Permissions.VIEW_CHANNEL], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.VIEW_CHANNEL]) + !hasViewChannelPerm ) { throw new Error(Errors.MISSING_VIEW_CHANNEL); } + + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.READ_MESSAGE_HISTORY], - ) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -72,16 +78,22 @@ export async function getMessages( | GetMessagesAround | GetMessages, ) { + const hasViewChannelPerm = await botHasChannelPermissions( + channelID, + [Permissions.VIEW_CHANNEL], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.VIEW_CHANNEL]) + !hasViewChannelPerm ) { throw new Error(Errors.MISSING_VIEW_CHANNEL); } + + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.READ_MESSAGE_HISTORY], - ) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -109,24 +121,34 @@ export async function sendMessage( content: string | MessageContent, ) { if (typeof content === "string") content = { content }; + const hasSendMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.SEND_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.SEND_MESSAGES]) + !hasSendMessagesPerm ) { throw new Error(Errors.MISSING_SEND_MESSAGES); } + + const hasSendTtsMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.SEND_TTS_MESSAGES], + ); if ( content.tts && - !botHasChannelPermissions( - channelID, - [Permissions.SEND_TTS_MESSAGES], - ) + !hasSendTtsMessagesPerm ) { throw new Error(Errors.MISSING_SEND_TTS_MESSAGE); } + const hasEmbedLinksPerm = await botHasChannelPermissions( + channelID, + [Permissions.EMBED_LINKS], + ); if ( content.embed && - !botHasChannelPermissions(channelID, [Permissions.EMBED_LINKS]) + !hasEmbedLinksPerm ) { throw new Error(Errors.MISSING_EMBED_LINKS); } @@ -183,13 +205,17 @@ export async function sendMessage( } /** Delete messages from the channel. 2-100. Requires the MANAGE_MESSAGES permission */ -export function deleteMessages( +export async function deleteMessages( channelID: string, ids: string[], reason?: string, ) { + const hasManageMessages = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessages ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -210,9 +236,13 @@ export function deleteMessages( } /** Gets the invites for this channel. Requires MANAGE_CHANNEL */ -export function getChannelInvites(channelID: string) { +export async function getChannelInvites(channelID: string) { + const hasManagaChannels = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_CHANNELS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_CHANNELS]) + !hasManagaChannels ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } @@ -220,12 +250,16 @@ export function getChannelInvites(channelID: string) { } /** Creates a new invite for this channel. Requires CREATE_INSTANT_INVITE */ -export function createInvite(channelID: string, options: CreateInviteOptions) { +export async function createInvite( + channelID: string, + options: CreateInviteOptions, +) { + const hasCreateInstantInvitePerm = await botHasChannelPermissions( + channelID, + [Permissions.CREATE_INSTANT_INVITE], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.CREATE_INSTANT_INVITE], - ) + !hasCreateInstantInvitePerm ) { throw new Error(Errors.MISSING_CREATE_INSTANT_INVITE); } @@ -233,9 +267,13 @@ export function createInvite(channelID: string, options: CreateInviteOptions) { } /** Gets the webhooks for this channel. Requires MANAGE_WEBHOOKS */ -export function getChannelWebhooks(channelID: string) { +export async function getChannelWebhooks(channelID: string) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_WEBHOOKS]) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_WEBHOOKS); } @@ -288,12 +326,16 @@ function processEditChannelQueue() { } } -export function editChannel( +export async function editChannel( channelID: string, options: ChannelEditOptions, ) { + const hasManageChannelsPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_CHANNELS], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_CHANNELS]) + !hasManageChannelsPerm ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } @@ -356,8 +398,12 @@ export async function followChannel( sourceChannelID: string, targetChannelID: string, ) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + targetChannelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions(targetChannelID, [Permissions.MANAGE_WEBHOOKS]) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 243404125..f592568e0 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -38,11 +38,12 @@ export async function deleteMessage( ) { if (message.author.id !== botID) { // This needs to check the channels permission not the guild permission + const hasManageMessages = await botHasChannelPermissions( + message.channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions( - message.channelID, - [Permissions.MANAGE_MESSAGES], - ) + !hasManageMessages ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -57,9 +58,13 @@ export async function deleteMessage( } /** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */ -export function pin(channelID: string, messageID: string) { +export async function pin(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -67,9 +72,13 @@ export function pin(channelID: string, messageID: string) { } /** Unpin a message in a channel. Requires MANAGE_MESSAGES. */ -export function unpin(channelID: string, messageID: string) { +export async function unpin(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -79,17 +88,25 @@ export function unpin(channelID: string, messageID: string) { } /** Create a reaction for the message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. Requires READ_MESSAGE_HISTORY and ADD_REACTIONS */ -export function addReaction( +export async function addReaction( channelID: string, messageID: string, reaction: string, ) { - if (!botHasChannelPermissions(channelID, [Permissions.ADD_REACTIONS])) { + const hasAddReactionsPerm = await botHasChannelPermissions( + channelID, + [Permissions.ADD_REACTIONS], + ); + if (!hasAddReactionsPerm) { throw new Error(Errors.MISSING_ADD_REACTIONS); } + const hasReadMessageHistoryPerm = await botHasChannelPermissions( + channelID, + [Permissions.READ_MESSAGE_HISTORY], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.READ_MESSAGE_HISTORY]) + !hasReadMessageHistoryPerm ) { throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY); } @@ -143,13 +160,17 @@ export function removeReaction( } /** Removes a reaction from the specified user on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ -export function removeUserReaction( +export async function removeUserReaction( channelID: string, messageID: string, reaction: string, userID: string, ) { - if (!botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES])) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); + if (!hasManageMessagesPerm) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -164,9 +185,13 @@ export function removeUserReaction( } /** Removes all reactions for all emojis on this message. */ -export function removeAllReactions(channelID: string, messageID: string) { +export async function removeAllReactions(channelID: string, messageID: string) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -176,13 +201,17 @@ export function removeAllReactions(channelID: string, messageID: string) { } /** Removes all reactions for a single emoji on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ -export function removeReactionEmoji( +export async function removeReactionEmoji( channelID: string, messageID: string, reaction: string, ) { + const hasManageMessagesPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_MESSAGES], + ); if ( - !botHasChannelPermissions(channelID, [Permissions.MANAGE_MESSAGES]) + !hasManageMessagesPerm ) { throw new Error(Errors.MISSING_MANAGE_MESSAGES); } @@ -216,18 +245,23 @@ export async function editMessage( if (typeof content === "string") content = { content }; + const hasSendMessagesPerm = await botHasChannelPermissions( + message.channelID, + [Permissions.SEND_MESSAGES], + ); if ( - !botHasChannelPermissions(message.channelID, [Permissions.SEND_MESSAGES]) + !hasSendMessagesPerm ) { throw new Error(Errors.MISSING_SEND_MESSAGES); } + const hasSendTtsMessagesPerm = await botHasChannelPermissions( + message.channelID, + [Permissions.SEND_TTS_MESSAGES], + ); if ( content.tts && - !botHasChannelPermissions( - message.channelID, - [Permissions.SEND_TTS_MESSAGES], - ) + !hasSendTtsMessagesPerm ) { throw new Error(Errors.MISSING_SEND_TTS_MESSAGE); } diff --git a/src/handlers/webhook.ts b/src/handlers/webhook.ts index 7bb9400b3..cc7365db7 100644 --- a/src/handlers/webhook.ts +++ b/src/handlers/webhook.ts @@ -20,11 +20,12 @@ export async function createWebhook( channelID: string, options: WebhookCreateOptions, ) { + const hasManageWebhooksPerm = await botHasChannelPermissions( + channelID, + [Permissions.MANAGE_WEBHOOKS], + ); if ( - !botHasChannelPermissions( - channelID, - [Permissions.MANAGE_WEBHOOKS], - ) + !hasManageWebhooksPerm ) { throw new Error(Errors.MISSING_MANAGE_WEBHOOKS); } From 9c3a42e10610ea2e089cb51428c4df745d1cc2f5 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 7 Nov 2020 21:30:17 -0800 Subject: [PATCH 04/54] Convert the License section text to hyperlink --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c29a044c..3cd062456 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,4 @@ Alternatively, you can use boilerplate template repositories that were created b ## License -MIT © Skillz4Killz +[MIT © Skillz4Killz](https://github.com/Skillz4Killz/Discordeno/blob/master/LICENSE) From be27976baeeec02b9b767da7122835dc066584ca Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 14:41:08 -0500 Subject: [PATCH 05/54] much faster rest --- src/module/requestManager.ts | 90 +++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index dbbdabd15..4f14fa456 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -64,56 +64,60 @@ async function cleanupQueues() { } async function processQueue() { - if ( - (Object.keys(pathQueues).length) && !globallyRateLimited - ) { - await Promise.allSettled( - Object.values(pathQueues).map(async (pathQueue) => { - const request = pathQueue.shift(); - if (!request) return; + // Putting this code inside a function like this allows us to use tail recursion like a while loop without hitting the max stack error. + async function avoidMaxStackError() { + if ( + (Object.keys(pathQueues).length) && !globallyRateLimited + ) { + await Promise.allSettled( + Object.values(pathQueues).map(async (pathQueue) => { + const request = pathQueue.shift(); + if (!request) return; - const rateLimitedURLResetIn = await checkRatelimits(request.url); + const rateLimitedURLResetIn = await checkRatelimits(request.url); - if (request.bucketID) { - const rateLimitResetIn = await checkRatelimits(request.bucketID); - if (rateLimitResetIn) { - // This request is still rate limited readd to queue - addToQueue(request); - } else if (rateLimitedURLResetIn) { - // This URL is rate limited readd to queue - addToQueue(request); + if (request.bucketID) { + const rateLimitResetIn = await checkRatelimits(request.bucketID); + if (rateLimitResetIn) { + // This request is still rate limited readd to queue + addToQueue(request); + } else if (rateLimitedURLResetIn) { + // This URL is rate limited readd to queue + addToQueue(request); + } else { + // This request is not rate limited so it should be run + const result = await request.callback(); + if (result && result.rateLimited) { + addToQueue( + { ...request, bucketID: result.bucketID || request.bucketID }, + ); + } + } } else { - // This request is not rate limited so it should be run - const result = await request.callback(); - if (result && result.rateLimited) { - addToQueue( - { ...request, bucketID: result.bucketID || request.bucketID }, - ); + if (rateLimitedURLResetIn) { + // This URL is rate limited readd to queue + addToQueue(request); + } else { + // This request has no bucket id so it should be processed + const result = await request.callback(); + if (request && result && result.rateLimited) { + addToQueue( + { ...request, bucketID: result.bucketID || request.bucketID }, + ); + } } } - } else { - if (rateLimitedURLResetIn) { - // This URL is rate limited readd to queue - addToQueue(request); - } else { - // This request has no bucket id so it should be processed - const result = await request.callback(); - if (request && result && result.rateLimited) { - addToQueue( - { ...request, bucketID: result.bucketID || request.bucketID }, - ); - } - } - } - }), - ); + }), + ); + } + + if (Object.keys(pathQueues).length) { + avoidMaxStackError(); + cleanupQueues(); + } else queueInProcess = false; } - if (Object.keys(pathQueues).length) { - await delay(1000); - processQueue(); - cleanupQueues(); - } else queueInProcess = false; + return avoidMaxStackError() } processRateLimitedPaths(); From 7f0d52e5ba25561865efacf86a478b844b39ce12 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 16:11:01 -0500 Subject: [PATCH 06/54] fmt --- src/module/requestManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/requestManager.ts b/src/module/requestManager.ts index 4f14fa456..ee96700da 100644 --- a/src/module/requestManager.ts +++ b/src/module/requestManager.ts @@ -117,7 +117,7 @@ async function processQueue() { } else queueInProcess = false; } - return avoidMaxStackError() + return avoidMaxStackError(); } processRateLimitedPaths(); From 2530054b6560a3ec005e1748447196a71be26d56 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 9 Nov 2020 16:20:42 -0500 Subject: [PATCH 07/54] use recommended publishing on nes.land --- .github/workflows/nestland.yml | 9 +++++---- egg.yml | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nestland.yml b/.github/workflows/nestland.yml index 6625cc71c..fbb97d5d9 100644 --- a/.github/workflows/nestland.yml +++ b/.github/workflows/nestland.yml @@ -1,8 +1,8 @@ name: Ship Nest.Land on: - release: - types: [published] + create: + ref_type: "tag" jobs: release: @@ -16,5 +16,6 @@ jobs: - name: Publish module run: | - deno run -A --unstable https://x.nest.land/eggs@0.2.1/mod.ts link ${{ secrets.NESTAPIKEY }} - deno run -A --unstable https://x.nest.land/eggs@0.2.1/mod.ts publish --version ${{ github.event.inputs.tags }} + deno install -A --unstable https://x.nest.land/eggs@0.3.2/eggs.ts + eggs link ${{ secrets.NESTAPIKEY }} + eggs publish --yes --no-check --version $(git describe --tags $(git rev-list --tags --max-count=1)) diff --git a/egg.yml b/egg.yml index 79b0633d1..c25ed8734 100644 --- a/egg.yml +++ b/egg.yml @@ -2,7 +2,6 @@ name: Discordeno description: >- Discord Deno TypeScript API library wrapper(Officially vetted library by Discord Team) https://discordeno.netlify.app -version: 9.0.15 stable: true entry: mod.ts repository: 'https://github.com/Skillz4Killz/Discordeno' From a3b41f0e26dda1cc1dcc0978869d5d1c2cad2ed2 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:21:05 +0400 Subject: [PATCH 08/54] Add Discordeno bot tutorial series to useful links section --- docs/content/gettingstarted.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index 6ee051f24..f26820c9c 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -16,6 +16,7 @@ This website serves as the purpose for introducing Discordeno to developers. The - [GitHub Repository](https://github.com/Skillz4Killz/Discordeno) - [Deno Page](https://deno.land/x/discordeno) - [Website](https://discordeno.js.org/) +- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) ## Requirements From 5adf6b49cead71c7c924ef8d9e6d15da9ee2c2fd Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:23:07 +0400 Subject: [PATCH 09/54] Add Discordeno bot tutorials to YouTube tutorials section --- docs/content/gettingstarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index f26820c9c..8ff950890 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -16,7 +16,6 @@ This website serves as the purpose for introducing Discordeno to developers. The - [GitHub Repository](https://github.com/Skillz4Killz/Discordeno) - [Deno Page](https://deno.land/x/discordeno) - [Website](https://discordeno.js.org/) -- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) ## Requirements @@ -91,6 +90,7 @@ Web-Mystery Tutorials: - Running a Discord bot written in Deno in Docker YouTube Tutorials: +- [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) - Coming soon to [NTM Development](https://www.youtube.com/channel/UCkOFck-WCQtolha4NJuK7zA/) --- From 1dd7472934c350679805755b67bdff4a8b018175 Mon Sep 17 00:00:00 2001 From: ayntee Date: Tue, 10 Nov 2020 22:24:14 +0400 Subject: [PATCH 10/54] Remove link to cease free advertising --- docs/content/gettingstarted.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/content/gettingstarted.md b/docs/content/gettingstarted.md index 8ff950890..4892df5f2 100644 --- a/docs/content/gettingstarted.md +++ b/docs/content/gettingstarted.md @@ -91,7 +91,6 @@ Web-Mystery Tutorials: YouTube Tutorials: - [Discordeno Bot Tutorials YouTube series](https://youtu.be/rIph9-BGsuQ) -- Coming soon to [NTM Development](https://www.youtube.com/channel/UCkOFck-WCQtolha4NJuK7zA/) --- From 1fa5d08370b5b529db0b39a469674891d79bb945 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 12 Nov 2020 08:32:32 -0500 Subject: [PATCH 11/54] editBotProfile --- src/constants/discord.ts | 1 + src/handlers/member.ts | 34 +++++++++++++++++++++++++++++++++- src/types/errors.ts | 4 ++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/constants/discord.ts b/src/constants/discord.ts index fe9a98da6..fa334574b 100644 --- a/src/constants/discord.ts +++ b/src/constants/discord.ts @@ -96,6 +96,7 @@ export const endpoints = { // User endpoints USER: (id: string) => `${baseEndpoints.BASE_URL}/users/${id}`, + USER_BOT: `${baseEndpoints.BASE_URL}/users/@me`, USER_AVATAR: (id: string, icon: string) => `${baseEndpoints.CDN_URL}/avatars/${id}/${icon}`, USER_DEFAULT_AVATAR: (icon: number) => diff --git a/src/handlers/member.ts b/src/handlers/member.ts index 803a83cec..0949e65a4 100644 --- a/src/handlers/member.ts +++ b/src/handlers/member.ts @@ -15,6 +15,7 @@ import { higherRolePosition, highestRole, } from "../utils/permissions.ts"; +import { urlToBase64 } from "../utils/utils.ts"; import { sendMessage } from "./channel.ts"; /** The users custom avatar or the default avatar if you don't have a member object. */ @@ -184,7 +185,7 @@ export function editMember( ); } -/** +/** * Move a member from a voice channel to another. * @param guildID the id of the guild which the channel exists in * @param memberID the id of the member to move. @@ -197,3 +198,34 @@ export function moveMember( ) { return editMember(guildID, memberID, { channel_id: channelID }); } + +/** Modifies the bot's username or avatar. + * NOTE: username: if changed may cause the bot's discriminator to be randomized. + */ +export function editBotProfile(username?: string, avatarURL?: string) { + // Nothing was edited + if (!username && !avatarURL) return; + // Check username requirements if username was provided + if (username) { + if (username.length > 32) { + throw new Error(Errors.USERNAME_MAX_LENGTH); + } + if (username.length < 2) { + throw new Error(Errors.USERNAME_MIN_LENGTH); + } + if (["@", "#", ":", "```"].some((char) => username.includes(char))) { + throw new Error(Errors.USERNAME_INVALID_CHARACTER); + } + if (["discordtag", "everyone", "here"].includes(username)) { + throw new Error(Errors.USERNAME_INVALID_USERNAME); + } + } + + RequestManager.patch( + endpoints.USER_BOT, + { + username: username?.trim(), + avatar: avatarURL ? urlToBase64(avatarURL) : undefined, + }, + ); +} diff --git a/src/types/errors.ts b/src/types/errors.ts index 98df112d2..5ed296520 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -33,4 +33,8 @@ export enum Errors { INVALID_WEBHOOK_OPTIONS = "INVALID_WEBHOOK_OPTIONS", CHANNEL_NOT_FOUND = "CHANNEL_NOT_FOUND", CHANNEL_NOT_TEXT_BASED = "CHANNEL_NOT_TEXT_BASED", + USERNAME_MAX_LENGTH = "USERNAME_MAX_LENGTH", + USERNAME_MIN_LENGTH = "USERNAME_MIN_LENGTH", + USERNAME_INVALID_CHARACTER = "USERNAME_INVALID_CHARACTER", + USERNAME_INVALID_USERNAME = "USERNAME_INVALID_USERNAME", } From 4ec74fb36d1e589a4bbff73038f018098d032fdc Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:21:33 +0400 Subject: [PATCH 12/54] Add reason parameter to editChannel() --- src/handlers/channel.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 8a77101e4..d8ce6333b 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -329,6 +329,7 @@ function processEditChannelQueue() { export async function editChannel( channelID: string, options: ChannelEditOptions, + reason: string, ) { const hasManageChannelsPerm = await botHasChannelPermissions( channelID, @@ -389,7 +390,10 @@ export async function editChannel( return RequestManager.patch( endpoints.GUILD_CHANNEL(channelID), - payload, + { + ...payload, + reason, + }, ); } From 67b9dc96b443f899696dc14eb601da614b1e1398 Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:25:00 +0400 Subject: [PATCH 13/54] Make reason parameter optional --- src/handlers/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index d8ce6333b..23803aef4 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -329,7 +329,7 @@ function processEditChannelQueue() { export async function editChannel( channelID: string, options: ChannelEditOptions, - reason: string, + reason?: string, ) { const hasManageChannelsPerm = await botHasChannelPermissions( channelID, From b7d8b30b1f3eaaffe92925b839d669a3ba0c781f Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:30:51 +0400 Subject: [PATCH 14/54] Testing/Linting -> Lint --- .github/workflows/deno.yml | 27 ++++----------------------- README.md | 2 +- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/.github/workflows/deno.yml b/.github/workflows/deno.yml index f34093188..68641aeaa 100644 --- a/.github/workflows/deno.yml +++ b/.github/workflows/deno.yml @@ -1,35 +1,16 @@ -# This is a basic workflow to help you get started with Actions - -name: Testing/Linting - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch +name: Lint on: push: branches: [master] pull_request: branches: [master] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: - # The type of runner that the job will run on runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - - - name: Setup Deno environment - uses: denolib/setup-deno@master - - - name: Deno Fetch + - uses: denolib/setup-deno@master + - name: Cache the dependencies run: deno cache mod.ts - - - name: Deno Format Check + - name: Run format script with --check run: deno fmt *.ts --check - - - name: Deno Format Check src/ - run: deno fmt src/* --check diff --git a/README.md b/README.md index 3cd062456..1f59e2281 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > Discord API library wrapper in Deno [![Discord](https://img.shields.io/discord/223909216866402304?color=7289da&logo=discord&logoColor=dark)](https://discord.gg/J4NqJ72) -![Testing/Linting](https://github.com/Skillz4Killz/Discordeno/workflows/Testing/Linting/badge.svg) +![Lint](https://github.com/Skillz4Killz/Discordeno/workflows/Lint/badge.svg) ![Test](https://github.com/Skillz4Killz/Discordeno/workflows/Test/badge.svg) [![nest badge](https://nest.land/badge.svg)](https://nest.land/package/Discordeno) From 0ea9dbc7c45a7500b60827b5c9e0e4f856ab8cb5 Mon Sep 17 00:00:00 2001 From: ayntee Date: Thu, 12 Nov 2020 23:31:25 +0400 Subject: [PATCH 15/54] deno.yml -> lint.yml --- .github/workflows/{deno.yml => lint.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{deno.yml => lint.yml} (100%) diff --git a/.github/workflows/deno.yml b/.github/workflows/lint.yml similarity index 100% rename from .github/workflows/deno.yml rename to .github/workflows/lint.yml From bf0f32769161223ea74e67ccc7373057e117df75 Mon Sep 17 00:00:00 2001 From: Skillz Date: Thu, 12 Nov 2020 22:49:45 -0500 Subject: [PATCH 16/54] add dispatchRequirements --- src/module/shardingManager.ts | 1 + src/types/options.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/module/shardingManager.ts b/src/module/shardingManager.ts index e95ed6c0d..478c216c5 100644 --- a/src/module/shardingManager.ts +++ b/src/module/shardingManager.ts @@ -90,6 +90,7 @@ export async function handleDiscordPayload( shardID: number, ) { eventHandlers.raw?.(data); + await eventHandlers.dispatchRequirements?.(data); switch (data.op) { case GatewayOpcode.HeartbeatACK: diff --git a/src/types/options.ts b/src/types/options.ts index f3c66fc01..ddcd8ce38 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -83,6 +83,7 @@ export interface EventHandlers { channelUpdate?: (channel: Channel, cachedChannel: Channel) => unknown; channelDelete?: (channel: Channel) => unknown; debug?: (args: DebugArg) => unknown; + dispatchRequirements?: (data: DiscordPayload) => unknown; guildBanAdd?: (guild: Guild, user: Member | UserPayload) => unknown; guildBanRemove?: (guild: Guild, user: Member | UserPayload) => unknown; guildCreate?: (guild: Guild) => unknown; From c866d127a99cccdf68b8d6c3cc37f3e41a633412 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 13:10:44 +0400 Subject: [PATCH 17/54] Idk --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 68641aeaa..f16d35b38 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,4 +13,4 @@ jobs: - name: Cache the dependencies run: deno cache mod.ts - name: Run format script with --check - run: deno fmt *.ts --check + run: deno fmt --ignore=./docs --check From cb8a9353eb912863b27cd302f0646298309bf079 Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 08:29:20 -0500 Subject: [PATCH 18/54] add getGuild function --- src/handlers/guild.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 385b2c017..a0865d759 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -24,6 +24,7 @@ import { PositionSwap, PruneOptions, PrunePayload, + UpdateGuildPayload, UserPayload, } from "../types/guild.ts"; import { MemberCreatePayload } from "../types/member.ts"; @@ -607,3 +608,14 @@ export function getWebhooks(guildID: string) { export function getUser(userID: string) { return RequestManager.get(endpoints.USER(userID)) as Promise; } + +/** + * ⚠️ **If you need this, you are probably doing something wrong. Always use cache.guilds.get() + * + * Advanced Devs: + * This function fetches a guild's data. This is not the same data as a GUILD_CREATE. + * So it does not cache the guild, you must do it manually. + * */ +export function getGuild(guildID: string, counts = true) { + return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise +} From d73cd38c6c7de579b5fe23c5a3f139d2f734c200 Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 08:38:31 -0500 Subject: [PATCH 19/54] add shardID to dispatch event --- src/module/shardingManager.ts | 2 +- src/types/options.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/shardingManager.ts b/src/module/shardingManager.ts index 478c216c5..e955bb12e 100644 --- a/src/module/shardingManager.ts +++ b/src/module/shardingManager.ts @@ -90,7 +90,7 @@ export async function handleDiscordPayload( shardID: number, ) { eventHandlers.raw?.(data); - await eventHandlers.dispatchRequirements?.(data); + await eventHandlers.dispatchRequirements?.(data, shardID); switch (data.op) { case GatewayOpcode.HeartbeatACK: diff --git a/src/types/options.ts b/src/types/options.ts index ddcd8ce38..75f6f739d 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -83,7 +83,7 @@ export interface EventHandlers { channelUpdate?: (channel: Channel, cachedChannel: Channel) => unknown; channelDelete?: (channel: Channel) => unknown; debug?: (args: DebugArg) => unknown; - dispatchRequirements?: (data: DiscordPayload) => unknown; + dispatchRequirements?: (data: DiscordPayload, shardID: number) => unknown; guildBanAdd?: (guild: Guild, user: Member | UserPayload) => unknown; guildBanRemove?: (guild: Guild, user: Member | UserPayload) => unknown; guildCreate?: (guild: Guild) => unknown; From e73a09918c2ef330c533bc15dd33a548c2326ba3 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 18:04:07 +0400 Subject: [PATCH 20/54] New function isChannelSynced(channelID: string) --- src/handlers/channel.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/handlers/channel.ts b/src/handlers/channel.ts index 23803aef4..b74965be7 100644 --- a/src/handlers/channel.ts +++ b/src/handlers/channel.ts @@ -421,3 +421,30 @@ export async function followChannel( return data.webhook_id; } + +/** + * Checks whether a channel is synchronized with its parent/category channel or not. + * @param channelID The ID of the channel to test for synchronization + * @return Returns `true` if the channel is synchronized, otherwise `false`. Returns `false` if the channel is not cached. + */ +export async function isChannelSynced(channelID: string) { + const channel = await cacheHandlers.get("channels", channelID); + if (!channel?.parentID) return false; + + const parentChannel = await cacheHandlers.get("channels", channel.parentID); + if (!parentChannel) return false; + + return channel.permission_overwrites?.every((overwrite) => { + const permission = parentChannel.permission_overwrites?.find((ow) => + ow.id === overwrite.id + ); + if (!permission) return false; + if ( + overwrite.allow !== permission.allow || overwrite.deny !== permission.deny + ) { + return false; + } + + return true; + }); +} From 49815b579dd45f70be49cce704056d206031f7d4 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 18:09:27 +0400 Subject: [PATCH 21/54] Linted code --- src/handlers/guild.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index a0865d759..47385b112 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -617,5 +617,8 @@ export function getUser(userID: string) { * So it does not cache the guild, you must do it manually. * */ export function getGuild(guildID: string, counts = true) { - return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise + return RequestManager.get( + endpoints.GUILD(guildID), + { with_counts: counts }, + ) as Promise; } From a3d0c02d679e032078f57a2d6e91553813c0fa6a Mon Sep 17 00:00:00 2001 From: Skillz Date: Fri, 13 Nov 2020 12:24:04 -0500 Subject: [PATCH 22/54] fmt --- src/handlers/guild.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index a0865d759..47385b112 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -617,5 +617,8 @@ export function getUser(userID: string) { * So it does not cache the guild, you must do it manually. * */ export function getGuild(guildID: string, counts = true) { - return RequestManager.get(endpoints.GUILD(guildID), { with_counts: counts }) as Promise + return RequestManager.get( + endpoints.GUILD(guildID), + { with_counts: counts }, + ) as Promise; } From f9fddf7621a619860ddc681aa41604b535878561 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 22:53:54 +0400 Subject: [PATCH 23/54] =?UTF-8?q?Server=20Templates=20=F0=9F=8E=89?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/handlers/guild.ts | 28 ++++++++++++++++++++++++++++ src/types/guild.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 47385b112..8db3f76ea 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -622,3 +622,31 @@ export function getGuild(guildID: string, counts = true) { { with_counts: counts }, ) as Promise; } + +/** + * Get a template by its code + * @param code The code of the template + */ +export function getTemplate(code: string) { + const endpoint = `${endpoints.GUILDS}/templates/${code}`; + return RequestManager.get(endpoint); +} + +/** + * Create a new guild based on a template. + * NOTE: This endpoint can be used only by bots in less than 10 guilds. + * @param code the code of the template to create a new guild from + * @param name name of the guild (2-100 characters) + * @param icon base64 128x128 image for the guild icon + */ +export function createGuildFromTemplate( + code: string, + name: string, + icon?: any, +) { + const endpoint = `${endpoints.GUILDS}/templates/${code}`; + return RequestManager.post(endpoint, { + name, + icon, + }); +} diff --git a/src/types/guild.ts b/src/types/guild.ts index 7bcd4991e..e1a903fe7 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -1,3 +1,4 @@ +import { Guild } from "../structures/guild.ts"; import { ChannelCreatePayload, ChannelTypes } from "./channel.ts"; import { Emoji, StatusType } from "./discord.ts"; import { MemberCreatePayload } from "./member.ts"; @@ -606,3 +607,29 @@ export interface CreateServerOptions { /** the id of the channel where guild notices such as welcome messages and boost events are posted */ system_channel_id?: string; } + +// https://discord.com/developers/docs/resources/template#template-object +export interface GuildTemplate { + /** the template code (unique ID) */ + code: string; + /** template name */ + name: string; + /** the description for the template */ + description: string | null; + /** number of times this template has been used */ + usage_count: number; + /** the ID of the user who created the template */ + creator_id: string; + /** the user who created the template */ + user: UserPayload; + /** when this template was created */ + created_at: string; + /** when this template was last synced to the source guild */ + updated_at: string; + /** the ID of the guild this template is based on */ + source_guild_id: string; + /** the guild snapshot this template contains */ + serialized_source_guild: Guild; + /** whether the template has unsynced changes */ + is_dirty: boolean | null; +} From 985a4358f91071ba3e116e39edb303202c78c78d Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 13 Nov 2020 23:41:41 +0400 Subject: [PATCH 24/54] Rename GuildTemplate interface to Template --- src/types/guild.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/guild.ts b/src/types/guild.ts index e1a903fe7..b3d64044a 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -609,7 +609,7 @@ export interface CreateServerOptions { } // https://discord.com/developers/docs/resources/template#template-object -export interface GuildTemplate { +export interface Template { /** the template code (unique ID) */ code: string; /** template name */ From 1f2c5853de273d2599f7fda24833800eaa06e265 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 00:10:13 +0400 Subject: [PATCH 25/54] =?UTF-8?q?=F0=9F=8E=89=20Server=20Templates=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/discord.ts | 3 ++ src/handlers/guild.ts | 101 ++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/constants/discord.ts b/src/constants/discord.ts index fa334574b..3cf526388 100644 --- a/src/constants/discord.ts +++ b/src/constants/discord.ts @@ -89,6 +89,9 @@ export const endpoints = { `${baseEndpoints.CDN_URL}/splashes/${id}/${icon}`, GUILD_VANITY_URL: (id: string) => `${GUILDS_BASE(id)}/vanity-url`, GUILD_WEBHOOKS: (id: string) => `${GUILDS_BASE(id)}/webhooks`, + GUILD_TEMPLATE: (code: string) => + `${baseEndpoints.BASE_URL}/guilds/templates/${code}`, + GUILD_TEMPLATES: (id: string) => `${GUILDS_BASE(id)}/templates`, WEBHOOK: (id: string, token: string) => `${baseEndpoints.BASE_URL}/webhooks/${id}/${token}`, diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 8db3f76ea..e3919cd22 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -623,30 +623,99 @@ export function getGuild(guildID: string, counts = true) { ) as Promise; } -/** - * Get a template by its code - * @param code The code of the template +/** + * Returns the guild template if it exists + * @param guildID The ID of the guild + * @param code The code of the template to get */ -export function getTemplate(code: string) { - const endpoint = `${endpoints.GUILDS}/templates/${code}`; +export function getGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; return RequestManager.get(endpoint); } /** - * Create a new guild based on a template. + * Create a new guild based on a template * NOTE: This endpoint can be used only by bots in less than 10 guilds. - * @param code the code of the template to create a new guild from - * @param name name of the guild (2-100 characters) - * @param icon base64 128x128 image for the guild icon + * @param code The code of the template to create a guild from */ export function createGuildFromTemplate( code: string, - name: string, - icon?: any, + data: CreateGuildFromTemplate, ) { - const endpoint = `${endpoints.GUILDS}/templates/${code}`; - return RequestManager.post(endpoint, { - name, - icon, - }); + return RequestManager.post(endpoints.GUILD_TEMPLATE(code), data); +} + +export interface CreateGuildFromTemplate { + /** name of the guild (2-100 characters) */ + name: string; + /** base64 128x128 image for the guild icon */ + icon?: string; +} + +/** + * Returns an array of guild templates + * @param guildID The ID of the guild + */ +export function getGuildTemplates(guildID: string) { + return RequestManager.get(endpoints.GUILD_TEMPLATES(guildID)); +} + +/** + * Deletes a template from a guild + * @param guildID The guild ID to delete the template from + */ +export function deleteGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.delete(endpoint); +} + +/** + * Creates a template for the guild + * @param guildID The ID of the guild to create a template in + * @param name name of the template (1-100 characters) + * @param description description for the template (0-120 characters + */ +export function createGuildTemplate( + guildID: string, + data: CreateGuildTemplate, +) { + return RequestManager.post(endpoints.GUILD_TEMPLATES(guildID), data); +} + +export interface CreateGuildTemplate { + /** name of the template (1-100 characters) */ + name: string; + /** description for the template (0-120 characters) */ + description?: string | null; +} + +/** + * Syncs the template to the guild's current state + * @param guildID The ID of the guild + * @param code The code of the template to sync + */ +export function syncGuildTemplate(guildID: string, code: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.put(endpoint); +} + +/** + * Edit a template's metadata + * @param guildID The ID of the guild + * @param code The code of the template to edit + */ +export function editGuildTemplate( + guildID: string, + code: string, + data: EditGuildTemplate, +) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + return RequestManager.patch(endpoint, data); +} + +export interface EditGuildTemplate { + /** name of the template (1-100 characters) */ + name?: string; + /** description for the template (0-120 characters) */ + description?: string | null; } From dd60de628c011c295453d8dfa1d32267148d593d Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 00:41:25 +0400 Subject: [PATCH 26/54] Rename code parameter to templateCode to reduce ambiguity --- src/handlers/guild.ts | 49 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index e3919cd22..979492b63 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -623,26 +623,21 @@ export function getGuild(guildID: string, counts = true) { ) as Promise; } -/** - * Returns the guild template if it exists - * @param guildID The ID of the guild - * @param code The code of the template to get - */ -export function getGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Returns the guild template if it exists */ +export function getGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.get(endpoint); } /** * Create a new guild based on a template * NOTE: This endpoint can be used only by bots in less than 10 guilds. - * @param code The code of the template to create a guild from */ export function createGuildFromTemplate( - code: string, + templateCode: string, data: CreateGuildFromTemplate, ) { - return RequestManager.post(endpoints.GUILD_TEMPLATE(code), data); + return RequestManager.post(endpoints.GUILD_TEMPLATE(templateCode), data); } export interface CreateGuildFromTemplate { @@ -652,20 +647,14 @@ export interface CreateGuildFromTemplate { icon?: string; } -/** - * Returns an array of guild templates - * @param guildID The ID of the guild - */ +/** Returns an array of guild templates */ export function getGuildTemplates(guildID: string) { return RequestManager.get(endpoints.GUILD_TEMPLATES(guildID)); } -/** - * Deletes a template from a guild - * @param guildID The guild ID to delete the template from - */ -export function deleteGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Deletes a template from a guild */ +export function deleteGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.delete(endpoint); } @@ -689,27 +678,19 @@ export interface CreateGuildTemplate { description?: string | null; } -/** - * Syncs the template to the guild's current state - * @param guildID The ID of the guild - * @param code The code of the template to sync - */ -export function syncGuildTemplate(guildID: string, code: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; +/** Syncs the template to the guild's current state */ +export function syncGuildTemplate(guildID: string, templateCode: string) { + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.put(endpoint); } -/** - * Edit a template's metadata - * @param guildID The ID of the guild - * @param code The code of the template to edit - */ +/** Edit a template's metadata */ export function editGuildTemplate( guildID: string, - code: string, + templateCode: string, data: EditGuildTemplate, ) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${code}`; + const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; return RequestManager.patch(endpoint, data); } From 9c5031259f7bf89b496e4190579389f5e8f86d7a Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 10:43:08 +0400 Subject: [PATCH 27/54] Embed endpoint into function instead of assigning to var --- src/handlers/guild.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index 979492b63..df17cff35 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -625,8 +625,9 @@ export function getGuild(guildID: string, counts = true) { /** Returns the guild template if it exists */ export function getGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.get(endpoint); + return RequestManager.get( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** @@ -654,8 +655,9 @@ export function getGuildTemplates(guildID: string) { /** Deletes a template from a guild */ export function deleteGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.delete(endpoint); + return RequestManager.delete( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** @@ -680,8 +682,9 @@ export interface CreateGuildTemplate { /** Syncs the template to the guild's current state */ export function syncGuildTemplate(guildID: string, templateCode: string) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.put(endpoint); + return RequestManager.put( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + ); } /** Edit a template's metadata */ @@ -690,8 +693,10 @@ export function editGuildTemplate( templateCode: string, data: EditGuildTemplate, ) { - const endpoint = `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`; - return RequestManager.patch(endpoint, data); + return RequestManager.patch( + `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, + data, + ); } export interface EditGuildTemplate { From d31cf09c64a2927c22e2979b7b128026a1c43c12 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 14 Nov 2020 10:44:58 +0400 Subject: [PATCH 28/54] Better types for getGuildTemplate() --- src/handlers/guild.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/handlers/guild.ts b/src/handlers/guild.ts index df17cff35..1d227f79d 100644 --- a/src/handlers/guild.ts +++ b/src/handlers/guild.ts @@ -24,6 +24,7 @@ import { PositionSwap, PruneOptions, PrunePayload, + Template, UpdateGuildPayload, UserPayload, } from "../types/guild.ts"; @@ -624,10 +625,13 @@ export function getGuild(guildID: string, counts = true) { } /** Returns the guild template if it exists */ -export function getGuildTemplate(guildID: string, templateCode: string) { +export function getGuildTemplate( + guildID: string, + templateCode: string, +): Promise