diff --git a/apps/rocko/src/index.ts b/apps/rocko/src/index.ts index 5e288785..e09c42d6 100644 --- a/apps/rocko/src/index.ts +++ b/apps/rocko/src/index.ts @@ -7,7 +7,7 @@ class PingCommand extends Command { defer = true async run(interaction: Interaction) { - sleep(7500) + await sleep(7500) interaction.reply({ content: "Pong" }) } } diff --git a/packages/carbon/package.json b/packages/carbon/package.json index c89cdfb6..265e5c7d 100644 --- a/packages/carbon/package.json +++ b/packages/carbon/package.json @@ -10,8 +10,8 @@ }, "license": "MIT", "dependencies": { - "discord-api-types": "^0.37.79", + "discord-api-types": "0.37.79", "discord-verify": "1.2.0", - "hono": "4.2.4" + "itty-router": "5.0.15" } } \ No newline at end of file diff --git a/packages/carbon/src/classes/Client.ts b/packages/carbon/src/classes/Client.ts index c241a40c..a642eaf5 100644 --- a/packages/carbon/src/classes/Client.ts +++ b/packages/carbon/src/classes/Client.ts @@ -1,6 +1,6 @@ import type { ClientOptions } from "../typings.js"; -import { type Context, Hono } from "hono" -import { verify } from "discord-verify"; +import { AutoRouter, StatusError, json, type IRequestStrict } from "itty-router" +import { PlatformAlgorithm, isValidRequest } from "discord-verify"; import { type APIInteraction, InteractionResponseType, InteractionType, MessageFlags, Routes, RouteBases } from "discord-api-types/v10"; import type { Command } from "../structures/Command.js"; import { Interaction } from "./Interaction.js"; @@ -8,11 +8,11 @@ import { Interaction } from "./Interaction.js"; export class Client { options: ClientOptions commands: Command[] - router: Hono + router: ReturnType constructor(options: ClientOptions, commands: Command[]) { this.options = options this.commands = commands - this.router = new Hono() + this.router = AutoRouter() this.setupRoutes() this.deployCommands() } @@ -37,27 +37,26 @@ export class Client { } private setupRoutes() { - this.router.get("/", (c) => { - if (this.options.redirectUrl) return c.redirect(this.options.redirectUrl) - c.status(401) - return c.json({ error: "Unauthorized" }) + this.router.get("/", () => { + if (this.options.redirectUrl) return Response.redirect(this.options.redirectUrl, 302) + throw new StatusError(404) }) - this.router.post("/interaction", async (c) => { - const isValid = await this.validateInteraction(c) + this.router.post("/interaction", async (req: IRequestStrict) => { + const isValid = await this.validateInteraction(req) if (!isValid) { - c.status(401) - return c.json({ error: "Invalid request signature." }) + return new Response("Invalid request signature", { status: 401 }) } - const rawInteraction = c.req.json() as unknown as APIInteraction + const rawInteraction = await req.json() as unknown as APIInteraction + console.log(rawInteraction) if (rawInteraction.type === InteractionType.Ping) { - return c.json({ + return json({ type: InteractionResponseType.Pong }) } if (rawInteraction.type !== InteractionType.ApplicationCommand) { - return c.json({ + return json({ type: InteractionResponseType.ChannelMessageWithSource, data: { content: "Interaction type not supported" @@ -66,18 +65,18 @@ export class Client { } const command = this.commands.find(x => x.name === rawInteraction.data.name) - if (!command) return c.status(400) + if (!command) return new Response(null, { status: 400 }) const interaction = new Interaction(rawInteraction) if (command.defer) { command.run(interaction) - return c.json({ + return json({ type: InteractionResponseType.DeferredChannelMessageWithSource, flags: command.ephemeral ? MessageFlags.Ephemeral : 0 }) } - return c.json({ + return json({ type: InteractionResponseType.ChannelMessageWithSource, content: "Man someone should really implement non-deferred replies huh" }) @@ -87,27 +86,14 @@ export class Client { } - private async validateInteraction(c: Context) { - if (c.req.method !== "POST") { - c.status(405) - return c.json({ error: "Method not allowed." }) + private async validateInteraction(req: IRequestStrict) { + if (req.method !== "POST") { + throw new StatusError(405) } - if ( - !c.req.header("x-signature-ed25519") || - !c.req.header("x-signature-timestamp") - ) { - c.status(401) - return c.json({ error: "Invalid request signature." }) - } - const signature = c.req.header("x-signature-ed25519") - const timestamp = c.req.header("x-signature-timestamp") - const body = JSON.stringify(c.req.json()) - const isValid = await verify( - body, - signature, - timestamp, + const isValid = await isValidRequest( + req, this.options.publicKey, - crypto.subtle + PlatformAlgorithm.NewNode ) return isValid } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2cf5fba..ff8c0010 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,14 +52,14 @@ importers: packages/carbon: dependencies: discord-api-types: - specifier: ^0.37.79 + specifier: 0.37.79 version: 0.37.79 discord-verify: specifier: 1.2.0 version: 1.2.0 - hono: - specifier: 4.2.4 - version: 4.2.4 + itty-router: + specifier: 5.0.15 + version: 5.0.15 packages/nodejs: dependencies: @@ -2044,11 +2044,6 @@ packages: tslib: 2.6.2 dev: true - /hono@4.2.4: - resolution: {integrity: sha512-2T5Ahxh8tT0ISKCrNeA+OIwfD5W4EZ00iIMYBBCuiIivr+sOrZYOphinARSG7wL3nFsY6zkFHMMZbcR9CzEzug==} - engines: {node: '>=16.0.0'} - dev: false - /http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -2316,6 +2311,10 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /itty-router@5.0.15: + resolution: {integrity: sha512-TGpdnAYdzfUWROKBGDXi2d44taRv1j2B1QG0Yt3NeUhwp8QkfdskF2VfZnFHgUMvYx0YpN99ymACq2mVJbLOIg==} + dev: false + /js-tokens@9.0.0: resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} dev: false