From 9ab29b5fc6ba890661d152631811de80d395e009 Mon Sep 17 00:00:00 2001 From: MostProDev <136127316+MostProDev@users.noreply.github.com> Date: Thu, 17 Aug 2023 17:27:14 +0100 Subject: [PATCH 1/5] deploy.ts: Uses Deno.serve() instead of fetch event listener --- deploy.ts | 136 +++++++++++++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/deploy.ts b/deploy.ts index a0b67ff6..8ef3cadd 100644 --- a/deploy.ts +++ b/deploy.ts @@ -5,24 +5,24 @@ import { ApplicationCommandHandler, ApplicationCommandHandlerCallback, AutocompleteHandlerCallback -} from './src/interactions/mod.ts' +} from './src/interactions/mod.ts'; import { InteractionResponseType, InteractionType -} from './src/types/interactions.ts' -import { ApplicationCommandType } from './src/types/applicationCommand.ts' +} from './src/types/interactions.ts'; +import { ApplicationCommandType } from './src/types/applicationCommand.ts'; export interface DeploySlashInitOptions { - env?: boolean - publicKey?: string - token?: string - path?: string + env?: boolean; + publicKey?: string; + token?: string; + path?: string; } /** Current Slash Client being used to handle commands */ -let client: InteractionsClient +let client: InteractionsClient; /** Manage Slash Commands right in Deploy */ -let commands: ApplicationCommandsManager +let commands: ApplicationCommandsManager; /** * Initialize Slash Commands Handler for [Deno Deploy](https://deno.com/deploy). @@ -44,64 +44,61 @@ let commands: ApplicationCommandsManager * * @param options Initialization options */ -export function init(options: { env: boolean; path?: string }): void +export function init(options: { env: boolean; path?: string; }): void; export function init(options: { - publicKey: string - token?: string - path?: string -}): void + publicKey: string; + token?: string; + path?: string; +}): void; export function init(options: DeploySlashInitOptions): void { - if (client !== undefined) throw new Error('Already initialized') + if (client !== undefined) throw new Error('Already initialized'); if (options.env === true) { - options.publicKey = Deno.env.get('PUBLIC_KEY') - options.token = Deno.env.get('TOKEN') + options.publicKey = Deno.env.get('PUBLIC_KEY'); + options.token = Deno.env.get('TOKEN'); } if (options.publicKey === undefined) - throw new Error('Public Key not provided') + throw new Error('Public Key not provided'); client = new InteractionsClient({ token: options.token, publicKey: options.publicKey - }) + }); - commands = client.commands + commands = client.commands; - const cb = async (evt: { - respondWith: CallableFunction - request: Request - }): Promise => { + const requestHandler = async (request: Request): Promise => { if (options.path !== undefined) { - if (new URL(evt.request.url).pathname !== options.path) return + if (new URL(request.url).pathname !== options.path) return new Response('Bad Request', { + status: 400 + }); } try { - // we have to wrap because there are some weird scope errors - const d = await client.verifyFetchEvent({ - respondWith: (...args: unknown[]) => evt.respondWith(...args), - request: evt.request - }) - if (d === false) { - await evt.respondWith( - new Response('Not Authorized', { - status: 400 - }) - ) - return + const interaction = await client.verifyFetchEvent({ request, respondWith: (res: Response) => { return res; } }); + if (!interaction) { + // ... unauthorized + return new Response('Not Authorized', { + status: 400 + }); } - - if (d.type === InteractionType.PING) { - await d.respond({ type: InteractionResponseType.PONG }) - client.emit('ping') - return + if (interaction.type === InteractionType.PING) { + await interaction.respond({ type: InteractionResponseType.PONG }); + await client.emit('ping'); } - await client._process(d) - } catch (e) { - await client.emit('interactionError', e as Error) + await client._process(interaction); + return new Response('Error', { + status: 500 + }); } - } - - addEventListener('fetch', cb as unknown as EventListener) + catch (e) { + client.emit('interactionError', e as Error); + return new Response('Error', { + status: 500 + }); + } + }; + Deno.serve(requestHandler); } /** @@ -132,32 +129,32 @@ export function init(options: DeploySlashInitOptions): void { export function handle( cmd: string, handler: ApplicationCommandHandlerCallback -): void -export function handle(cmd: ApplicationCommandHandler): void +): void; +export function handle(cmd: ApplicationCommandHandler): void; export function handle( cmd: string, handler: ApplicationCommandHandlerCallback, type: ApplicationCommandType | keyof typeof ApplicationCommandType -): void +): void; export function handle( cmd: string | ApplicationCommandHandler, handler?: ApplicationCommandHandlerCallback, type?: ApplicationCommandType | keyof typeof ApplicationCommandType ): void { if (client === undefined) - throw new Error('Interaction Client not initialized. Call `init` first') + throw new Error('Interaction Client not initialized. Call `init` first'); if ( typeof cmd === 'string' && typeof handler === 'function' && typeof type !== 'undefined' ) { - client.handle(cmd, handler, type) + client.handle(cmd, handler, type); } else if (typeof cmd === 'string' && typeof handler === 'function') { - client.handle(cmd, handler) + client.handle(cmd, handler); } else if (typeof cmd === 'object') { - client.handle(cmd) - } else throw new Error('Invalid overload for `handle` function') + client.handle(cmd); + } else throw new Error('Invalid overload for `handle` function'); } export function autocomplete( @@ -165,23 +162,24 @@ export function autocomplete( option: string, callback: AutocompleteHandlerCallback ): void { - client.autocomplete(cmd, option, callback) + client.autocomplete(cmd, option, callback); } /** Listen for Interactions Event */ export function interactions( - cb: (i: Interaction) => unknown | Promise + requestHandler: (i: Interaction) => Promise ): void { - client.on('interaction', cb) + client.on('interaction', requestHandler) } -export { commands, client } -export * from './src/types/applicationCommand.ts' -export * from './src/types/interactions.ts' -export * from './src/structures/applicationCommand.ts' -export * from './src/interactions/mod.ts' -export * from './src/types/channel.ts' -export * from './src/structures/interactions.ts' -export * from './src/structures/message.ts' -export * from './src/structures/embed.ts' -export * from './src/types/messageComponents.ts' +export { commands, client }; +export * from './src/types/applicationCommand.ts'; +export * from './src/types/interactions.ts'; +export * from './src/structures/applicationCommand.ts'; +export * from './src/interactions/mod.ts'; +export * from './src/types/channel.ts'; +export * from './src/structures/interactions.ts'; +export * from './src/structures/message.ts'; +export * from './src/structures/embed.ts'; +export * from './src/types/messageComponents.ts'; + From 5647e6036c91b38a87f8321ee3744b179baee120 Mon Sep 17 00:00:00 2001 From: MostProDev <136127316+MostProDev@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:59:37 +0100 Subject: [PATCH 2/5] Update deploy.ts --- deploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.ts b/deploy.ts index 8ef3cadd..adccf673 100644 --- a/deploy.ts +++ b/deploy.ts @@ -75,7 +75,7 @@ export function init(options: DeploySlashInitOptions): void { } try { const interaction = await client.verifyFetchEvent({ request, respondWith: (res: Response) => { return res; } }); - if (!interaction) { + if (interaction === false) { // ... unauthorized return new Response('Not Authorized', { status: 400 From 31c2b5c3f44fc0084e23c1ee9f65b4affedbe04f Mon Sep 17 00:00:00 2001 From: MostProDev <136127316+MostProDev@users.noreply.github.com> Date: Fri, 18 Aug 2023 11:21:56 +0100 Subject: [PATCH 3/5] Update deploy.ts --- deploy.ts | 305 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 250 insertions(+), 55 deletions(-) diff --git a/deploy.ts b/deploy.ts index adccf673..80be168f 100644 --- a/deploy.ts +++ b/deploy.ts @@ -5,24 +5,24 @@ import { ApplicationCommandHandler, ApplicationCommandHandlerCallback, AutocompleteHandlerCallback -} from './src/interactions/mod.ts'; +} from './src/interactions/mod.ts' import { InteractionResponseType, InteractionType -} from './src/types/interactions.ts'; -import { ApplicationCommandType } from './src/types/applicationCommand.ts'; +} from './src/types/interactions.ts' +import { ApplicationCommandType } from './src/types/applicationCommand.ts' export interface DeploySlashInitOptions { - env?: boolean; - publicKey?: string; - token?: string; - path?: string; + env?: boolean + publicKey?: string + token?: string + path?: string } /** Current Slash Client being used to handle commands */ -let client: InteractionsClient; +let client: InteractionsClient /** Manage Slash Commands right in Deploy */ -let commands: ApplicationCommandsManager; +let commands: ApplicationCommandsManager /** * Initialize Slash Commands Handler for [Deno Deploy](https://deno.com/deploy). @@ -44,61 +44,66 @@ let commands: ApplicationCommandsManager; * * @param options Initialization options */ -export function init(options: { env: boolean; path?: string; }): void; +export function init(options: { env: boolean; path?: string }): void export function init(options: { - publicKey: string; - token?: string; - path?: string; -}): void; + publicKey: string + token?: string + path?: string +}): void export function init(options: DeploySlashInitOptions): void { - if (client !== undefined) throw new Error('Already initialized'); + if (client !== undefined) throw new Error('Already initialized') if (options.env === true) { - options.publicKey = Deno.env.get('PUBLIC_KEY'); - options.token = Deno.env.get('TOKEN'); + options.publicKey = Deno.env.get('PUBLIC_KEY') + options.token = Deno.env.get('TOKEN') } if (options.publicKey === undefined) - throw new Error('Public Key not provided'); + throw new Error('Public Key not provided') client = new InteractionsClient({ token: options.token, publicKey: options.publicKey - }); + }) - commands = client.commands; + commands = client.commands const requestHandler = async (request: Request): Promise => { if (options.path !== undefined) { - if (new URL(request.url).pathname !== options.path) return new Response('Bad Request', { - status: 400 - }); + if (new URL(request.url).pathname !== options.path) + return new Response('Bad Request', { + status: 400 + }) } try { - const interaction = await client.verifyFetchEvent({ request, respondWith: (res: Response) => { return res; } }); - if (interaction === false) { + const interaction = await client.verifyFetchEvent({ + request, + respondWith: (res: Response) => { + return res + } + }) + if (!interaction) { // ... unauthorized return new Response('Not Authorized', { status: 400 - }); + }) } if (interaction.type === InteractionType.PING) { - await interaction.respond({ type: InteractionResponseType.PONG }); - await client.emit('ping'); + await interaction.respond({ type: InteractionResponseType.PONG }) + await client.emit('ping') } - await client._process(interaction); + await client._process(interaction) return new Response('Error', { status: 500 - }); - } - catch (e) { - client.emit('interactionError', e as Error); + }) + } catch (e) { + client.emit('interactionError', e as Error) return new Response('Error', { status: 500 - }); + }) } - }; - Deno.serve(requestHandler); + } + Deno.serve(requestHandler) } /** @@ -129,32 +134,32 @@ export function init(options: DeploySlashInitOptions): void { export function handle( cmd: string, handler: ApplicationCommandHandlerCallback -): void; -export function handle(cmd: ApplicationCommandHandler): void; +): void +export function handle(cmd: ApplicationCommandHandler): void export function handle( cmd: string, handler: ApplicationCommandHandlerCallback, type: ApplicationCommandType | keyof typeof ApplicationCommandType -): void; +): void export function handle( cmd: string | ApplicationCommandHandler, handler?: ApplicationCommandHandlerCallback, type?: ApplicationCommandType | keyof typeof ApplicationCommandType ): void { if (client === undefined) - throw new Error('Interaction Client not initialized. Call `init` first'); + throw new Error('Interaction Client not initialized. Call `init` first') if ( typeof cmd === 'string' && typeof handler === 'function' && typeof type !== 'undefined' ) { - client.handle(cmd, handler, type); + client.handle(cmd, handler, type) } else if (typeof cmd === 'string' && typeof handler === 'function') { - client.handle(cmd, handler); + client.handle(cmd, handler) } else if (typeof cmd === 'object') { - client.handle(cmd); - } else throw new Error('Invalid overload for `handle` function'); + client.handle(cmd) + } else throw new Error('Invalid overload for `handle` function') } export function autocomplete( @@ -162,7 +167,7 @@ export function autocomplete( option: string, callback: AutocompleteHandlerCallback ): void { - client.autocomplete(cmd, option, callback); + client.autocomplete(cmd, option, callback) } /** Listen for Interactions Event */ @@ -172,14 +177,204 @@ export function interactions( client.on('interaction', requestHandler) } -export { commands, client }; -export * from './src/types/applicationCommand.ts'; -export * from './src/types/interactions.ts'; -export * from './src/structures/applicationCommand.ts'; -export * from './src/interactions/mod.ts'; -export * from './src/types/channel.ts'; -export * from './src/structures/interactions.ts'; -export * from './src/structures/message.ts'; -export * from './src/structures/embed.ts'; -export * from './src/types/messageComponents.ts'; +export { commands, client } +export * from './src/types/applicationCommand.ts' +export * from './src/types/interactions.ts' +export * from './src/structures/applicationCommand.ts' +export * from './src/interactions/mod.ts' +export * from './src/types/channel.ts' +export * from './src/structures/interactions.ts' +export * from './src/structures/message.ts' +export * from './src/structures/embed.ts' +export * from './src/types/messageComponents.ts' +alfiecrawford@Alfies-Air harmony-main % npx prettier deploy.ts -o output.txt +[warn] Ignored unknown option -o=output.txt. Did you mean -c? +import { Interaction } from './src/structures/interactions.ts' +import { + ApplicationCommandsManager, + InteractionsClient, + ApplicationCommandHandler, + ApplicationCommandHandlerCallback, + AutocompleteHandlerCallback +} from './src/interactions/mod.ts' +import { + InteractionResponseType, + InteractionType +} from './src/types/interactions.ts' +import { ApplicationCommandType } from './src/types/applicationCommand.ts' + +export interface DeploySlashInitOptions { + env?: boolean + publicKey?: string + token?: string + path?: string +} + +/** Current Slash Client being used to handle commands */ +let client: InteractionsClient +/** Manage Slash Commands right in Deploy */ +let commands: ApplicationCommandsManager + +/** + * Initialize Slash Commands Handler for [Deno Deploy](https://deno.com/deploy). + * Easily create Serverless Slash Commands on the fly. + * + * **Examples** + * + * ```ts + * init({ + * publicKey: "my public key", + * token: "my bot's token", // only required if you want to manage slash commands in code + * }) + * ``` + * + * ```ts + * // takes up `PUBLIC_KEY` and `TOKEN` from ENV + * init({ env: true }) + * ``` + * + * @param options Initialization options + */ +export function init(options: { env: boolean; path?: string }): void +export function init(options: { + publicKey: string + token?: string + path?: string +}): void +export function init(options: DeploySlashInitOptions): void { + if (client !== undefined) throw new Error('Already initialized') + if (options.env === true) { + options.publicKey = Deno.env.get('PUBLIC_KEY') + options.token = Deno.env.get('TOKEN') + } + + if (options.publicKey === undefined) + throw new Error('Public Key not provided') + + client = new InteractionsClient({ + token: options.token, + publicKey: options.publicKey + }) + + commands = client.commands + + const requestHandler = async (request: Request): Promise => { + if (options.path !== undefined) { + if (new URL(request.url).pathname !== options.path) + return new Response('Bad Request', { + status: 400 + }) + } + try { + const interaction = await client.verifyFetchEvent({ + request, + respondWith: (res: Response) => { + return res + } + }) + if (!interaction) { + // ... unauthorized + return new Response('Not Authorized', { + status: 400 + }) + } + if (interaction.type === InteractionType.PING) { + await interaction.respond({ type: InteractionResponseType.PONG }) + await client.emit('ping') + } + + await client._process(interaction) + return new Response('Error', { + status: 500 + }) + } catch (e) { + client.emit('interactionError', e as Error) + return new Response('Error', { + status: 500 + }) + } + } + Deno.serve(requestHandler) +} + +/** + * Register Slash Command handler. + * + * Example: + * + * ```ts + * handle("ping", (interaction) => { + * interaction.reply("Pong!") + * }) + * ``` + * + * Also supports Sub Command and Group handling out of the box! + * ```ts + * handle("command-name group-name sub-command", (i) => { + * // ... + * }) + * + * handle("command-name sub-command", (i) => { + * // ... + * }) + * ``` + * + * @param cmd Command to handle. Either Handler object or command name followed by handler function in next parameter. + * @param handler Handler function (required if previous argument was command name) + */ +export function handle( + cmd: string, + handler: ApplicationCommandHandlerCallback +): void +export function handle(cmd: ApplicationCommandHandler): void +export function handle( + cmd: string, + handler: ApplicationCommandHandlerCallback, + type: ApplicationCommandType | keyof typeof ApplicationCommandType +): void +export function handle( + cmd: string | ApplicationCommandHandler, + handler?: ApplicationCommandHandlerCallback, + type?: ApplicationCommandType | keyof typeof ApplicationCommandType +): void { + if (client === undefined) + throw new Error('Interaction Client not initialized. Call `init` first') + + if ( + typeof cmd === 'string' && + typeof handler === 'function' && + typeof type !== 'undefined' + ) { + client.handle(cmd, handler, type) + } else if (typeof cmd === 'string' && typeof handler === 'function') { + client.handle(cmd, handler) + } else if (typeof cmd === 'object') { + client.handle(cmd) + } else throw new Error('Invalid overload for `handle` function') +} + +export function autocomplete( + cmd: string, + option: string, + callback: AutocompleteHandlerCallback +): void { + client.autocomplete(cmd, option, callback) +} + +/** Listen for Interactions Event */ +export function interactions( + requestHandler: (i: Interaction) => Promise +): void { + client.on('interaction', requestHandler) +} +export { commands, client } +export * from './src/types/applicationCommand.ts' +export * from './src/types/interactions.ts' +export * from './src/structures/applicationCommand.ts' +export * from './src/interactions/mod.ts' +export * from './src/types/channel.ts' +export * from './src/structures/interactions.ts' +export * from './src/structures/message.ts' +export * from './src/structures/embed.ts' +export * from './src/types/messageComponents.ts' From 845a6b866800889347f5b82773b74ed6b0523faa Mon Sep 17 00:00:00 2001 From: MostProDev <136127316+MostProDev@users.noreply.github.com> Date: Fri, 18 Aug 2023 22:21:34 +0100 Subject: [PATCH 4/5] Update deploy.ts --- deploy.ts | 191 ------------------------------------------------------ 1 file changed, 191 deletions(-) diff --git a/deploy.ts b/deploy.ts index 80be168f..9ffc2c2e 100644 --- a/deploy.ts +++ b/deploy.ts @@ -187,194 +187,3 @@ export * from './src/structures/interactions.ts' export * from './src/structures/message.ts' export * from './src/structures/embed.ts' export * from './src/types/messageComponents.ts' -alfiecrawford@Alfies-Air harmony-main % npx prettier deploy.ts -o output.txt -[warn] Ignored unknown option -o=output.txt. Did you mean -c? -import { Interaction } from './src/structures/interactions.ts' -import { - ApplicationCommandsManager, - InteractionsClient, - ApplicationCommandHandler, - ApplicationCommandHandlerCallback, - AutocompleteHandlerCallback -} from './src/interactions/mod.ts' -import { - InteractionResponseType, - InteractionType -} from './src/types/interactions.ts' -import { ApplicationCommandType } from './src/types/applicationCommand.ts' - -export interface DeploySlashInitOptions { - env?: boolean - publicKey?: string - token?: string - path?: string -} - -/** Current Slash Client being used to handle commands */ -let client: InteractionsClient -/** Manage Slash Commands right in Deploy */ -let commands: ApplicationCommandsManager - -/** - * Initialize Slash Commands Handler for [Deno Deploy](https://deno.com/deploy). - * Easily create Serverless Slash Commands on the fly. - * - * **Examples** - * - * ```ts - * init({ - * publicKey: "my public key", - * token: "my bot's token", // only required if you want to manage slash commands in code - * }) - * ``` - * - * ```ts - * // takes up `PUBLIC_KEY` and `TOKEN` from ENV - * init({ env: true }) - * ``` - * - * @param options Initialization options - */ -export function init(options: { env: boolean; path?: string }): void -export function init(options: { - publicKey: string - token?: string - path?: string -}): void -export function init(options: DeploySlashInitOptions): void { - if (client !== undefined) throw new Error('Already initialized') - if (options.env === true) { - options.publicKey = Deno.env.get('PUBLIC_KEY') - options.token = Deno.env.get('TOKEN') - } - - if (options.publicKey === undefined) - throw new Error('Public Key not provided') - - client = new InteractionsClient({ - token: options.token, - publicKey: options.publicKey - }) - - commands = client.commands - - const requestHandler = async (request: Request): Promise => { - if (options.path !== undefined) { - if (new URL(request.url).pathname !== options.path) - return new Response('Bad Request', { - status: 400 - }) - } - try { - const interaction = await client.verifyFetchEvent({ - request, - respondWith: (res: Response) => { - return res - } - }) - if (!interaction) { - // ... unauthorized - return new Response('Not Authorized', { - status: 400 - }) - } - if (interaction.type === InteractionType.PING) { - await interaction.respond({ type: InteractionResponseType.PONG }) - await client.emit('ping') - } - - await client._process(interaction) - return new Response('Error', { - status: 500 - }) - } catch (e) { - client.emit('interactionError', e as Error) - return new Response('Error', { - status: 500 - }) - } - } - Deno.serve(requestHandler) -} - -/** - * Register Slash Command handler. - * - * Example: - * - * ```ts - * handle("ping", (interaction) => { - * interaction.reply("Pong!") - * }) - * ``` - * - * Also supports Sub Command and Group handling out of the box! - * ```ts - * handle("command-name group-name sub-command", (i) => { - * // ... - * }) - * - * handle("command-name sub-command", (i) => { - * // ... - * }) - * ``` - * - * @param cmd Command to handle. Either Handler object or command name followed by handler function in next parameter. - * @param handler Handler function (required if previous argument was command name) - */ -export function handle( - cmd: string, - handler: ApplicationCommandHandlerCallback -): void -export function handle(cmd: ApplicationCommandHandler): void -export function handle( - cmd: string, - handler: ApplicationCommandHandlerCallback, - type: ApplicationCommandType | keyof typeof ApplicationCommandType -): void -export function handle( - cmd: string | ApplicationCommandHandler, - handler?: ApplicationCommandHandlerCallback, - type?: ApplicationCommandType | keyof typeof ApplicationCommandType -): void { - if (client === undefined) - throw new Error('Interaction Client not initialized. Call `init` first') - - if ( - typeof cmd === 'string' && - typeof handler === 'function' && - typeof type !== 'undefined' - ) { - client.handle(cmd, handler, type) - } else if (typeof cmd === 'string' && typeof handler === 'function') { - client.handle(cmd, handler) - } else if (typeof cmd === 'object') { - client.handle(cmd) - } else throw new Error('Invalid overload for `handle` function') -} - -export function autocomplete( - cmd: string, - option: string, - callback: AutocompleteHandlerCallback -): void { - client.autocomplete(cmd, option, callback) -} - -/** Listen for Interactions Event */ -export function interactions( - requestHandler: (i: Interaction) => Promise -): void { - client.on('interaction', requestHandler) -} - -export { commands, client } -export * from './src/types/applicationCommand.ts' -export * from './src/types/interactions.ts' -export * from './src/structures/applicationCommand.ts' -export * from './src/interactions/mod.ts' -export * from './src/types/channel.ts' -export * from './src/structures/interactions.ts' -export * from './src/structures/message.ts' -export * from './src/structures/embed.ts' -export * from './src/types/messageComponents.ts' From 7ee5739dcbfad647ca97cb15e22e6c2cb1fa284c Mon Sep 17 00:00:00 2001 From: MostProDev <136127316+MostProDev@users.noreply.github.com> Date: Fri, 18 Aug 2023 22:24:26 +0100 Subject: [PATCH 5/5] Update deploy.ts --- deploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.ts b/deploy.ts index 9ffc2c2e..283bb8e4 100644 --- a/deploy.ts +++ b/deploy.ts @@ -81,7 +81,7 @@ export function init(options: DeploySlashInitOptions): void { return res } }) - if (!interaction) { + if (interaction === false) { // ... unauthorized return new Response('Not Authorized', { status: 400