Skip to content

Commit 39e2e98

Browse files
initialize
1 parent e4ba11b commit 39e2e98

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+4927
-835
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
package-lock.json
22
node_modules
33
dist
4-
tsconfig.tsbuildinfo
4+
tsconfig.tsbuildinfo
5+
docs/

README.md

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
# Discord.https
22

3+
[![Discord](https://img.shields.io/badge/discord-blue?logo=discord&logoColor=white)](https://discord.gg/pSgfJ4K5ej)
34
[![npm version](https://img.shields.io/npm/v/discord.https.svg)](https://www.npmjs.com/package/discord.https)
45
[![License](https://img.shields.io/npm/l/discord.https.svg)](LICENSE)
5-
[![Downloads](https://img.shields.io/npm/dm/discord.https.svg)](https://www.npmjs.com/package/discord.https/index.default.html)
6+
[![Downloads](https://img.shields.io/npm/dm/discord.https.svg)](https://www.npmjs.com/package/discord.https)
67
[![Docs](https://img.shields.io/badge/docs-latest-blue)](https://discordhttps.github.io/discord.https/)
78

89
**Discord.https** is a robust, modular library for implementing Discord HTTP interactions.
910

1011
It handles various interactions and organizes them into modular routes, making your bot's code cleaner, easier to understand, and easier to maintain. It works seamlessly in both serverless and persistent server environments.
1112

12-
The core is production-ready and can be used in your new HTTP interaction bots.
13-
1413
📄 **Documentation:** [https://discordhttps.github.io/discord.https/](https://discordhttps.github.io/discord.https/)
1514

15+
Need help? Join us on discord [https://discord.gg/pSgfJ4K5ej](https://discord.gg/pSgfJ4K5ej)
16+
1617
```js
1718
import Client, { InteractionResponseType } from "discord.https";
1819
import NodeAdapter from "@discordhttps/nodejs-adapter";
@@ -25,22 +26,7 @@ const client = new Client({
2526

2627
client.command(
2728
(builder) => builder.setName("hi").setDescription("reply hello!"),
28-
async (interaction, client, _, res) => {
29-
res.writeHead(200, {
30-
"Content-Type": "application/json",
31-
});
32-
const username = interaction.user
33-
? interaction.user.global_name
34-
: interaction.member.user.global_name;
35-
res.end(
36-
JSON.stringify({
37-
type: InteractionResponseType.ChannelMessageWithSource,
38-
data: {
39-
content: `Hello! ${username}`,
40-
},
41-
})
42-
);
43-
}
29+
async (interaction) => await interaction.reply("hello!")
4430
);
4531

4632
await client.listen("interactions", 3000, () => {
@@ -56,10 +42,16 @@ await client.listen("interactions", 3000, () => {
5642
5743
> **Note**: Utility methods such as <interaction>.editReply() and <interaction>.deferReply() are currently in development, so you won’t need to manually handle the raw response object in the future.
5844
59-
> **Note(new)**: Utility methods were initially planned to closely follow Discord.js. However, since HTTP interactions are mostly used in a serverless environment, instead of having many layers of objects like Discord.js, an Eris-like approach will be adopted to keep the utilities minimal and lightweight.
45+
> **Note**: Utility methods were initially planned to closely follow Discord.js. However, since HTTP interactions are mostly used in a serverless environment, instead of having many layers of objects like Discord.js, an Eris-like approach will be adopted to keep the utilities minimal and lightweight.
46+
47+
> **Breaking Update (latest note)**: The goal was to stay within the web-standard V8 engine, but `@discord/rest` heavily depends on the Node.js environment. There are two choices: either use `@discord/rest` or build a custom REST handler. For now, `@discord/rest` will be used. The focus is on the Edge network, primarily Cloudflare. However, Cloudflare recently added [native Node.js support](https://blog.cloudflare.com/nodejs-workers-2025/). Previously, Node.js support was polyfilled, which can be inefficient for servers due to extra overhead. Now, Node.js support is native. Hence, from now on, the focus will be on Node.js APIs instead of web-standard/browser-context APIs.
6048
6149
## Examples
6250

51+
>Examples are outdated. You are no longer required to handle the raw response. The core is still there, and you can use these examples as a reference.
52+
53+
Deprecate warning, this example can be serve as a basic idea, but it has been changed quite a lot since, with utility functions.
54+
6355
**You can view example/reference implementations here:**
6456

6557
- Nodejs Runtime: [https://github.com/discordhttps/nodejs-example](https://github.com/discordhttps/nodejs-example)
@@ -84,10 +76,11 @@ npm install discord.https @discordhttps/cloudflare-adapter
8476
- **Discord.https Docs:** [https://discordhttps.github.io/discord.https/](https://discordhttps.github.io/discord.https/)
8577
- **Discord Interaction Docs:** [Responding to an Interaction](https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction)
8678

87-
## Todo
79+
## Todo for v4
8880

89-
- [ ] Build structures
9081
- [ ] Build a simplified `npx create-app` command
9182
- [ ] Implement tests
92-
- [x] HTTP adapters to support all hosting environments. Currently implemented: Node.js adapter for [Node.js runtime](https://github.com/discord-http/nodejs-adapter) and [Cloudflare adapter for V8 isolates runtime](https://github.com/discord-http/cloudflare-adapter)
93-
- [x] Examples
83+
- [ ] Build channel, guild, etc wrapper
84+
- [X] ~~Build interaction wrapper~~
85+
- [x] ~~HTTP adapters to support most hosting environments~~. Currently implemented: Node.js adapter for [Node.js runtime](https://github.com/discord-http/nodejs-adapter) and [Cloudflare adapter for V8 isolates runtime](https://github.com/discord-http/cloudflare-adapter)
86+
- [x] Examples(currently outdated, requires update)

package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,16 @@
3434
"url": "https://github.com/discord-http/discord.https/issues"
3535
},
3636
"homepage": "https://discordhttps.github.io/discord.https",
37-
"engines": {
38-
"node": ">=18"
39-
},
4037
"license": "MIT",
4138
"dependencies": {
4239
"@discordjs/builders": "^1.11.3",
40+
"@discordjs/collection": "^2.1.1",
4341
"@discordjs/rest": "^2.6.0",
4442
"@discordjs/util": "^1.1.1",
4543
"@noble/ed25519": "^3.0.0",
4644
"@sapphire/snowflake": "^3.5.5",
4745
"chalk": "^5.6.0",
48-
"discord-api-types": "^0.38.22"
46+
"discord-api-types": "^0.38.26"
4947
},
5048
"keywords": [
5149
"discord",

src/adapter/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface HttpAdapter {
3030
export interface HttpAdapterSererResponse {
3131
headersSent: boolean;
3232
writeHead(status: number, headers?: Record<string, string>): void;
33-
end(chunk?: string): void;
33+
end(chunk?: string | Uint8Array): void;
3434
}
3535

3636
/**

src/index.ts

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import {
2+
InteractionRouterManager,
3+
userContextCommandBuilder,
4+
messageContextCommandBuilder,
5+
type userContextCommandBuilderType,
6+
type messageContextCommandBuilderType,
7+
} from "./interactionRouter/internal.js";
8+
import { HttpInteractionServer } from "./interactionServer.js";
9+
import type { HttpAdapter, HttpAdapterSererResponse } from "./adapter/index.js";
10+
import { AutoCompleteKeyBuilder } from "./interactionRouter/autoCompleteKeyBuilder.js";
111
import chalk from "chalk";
212
import { REST } from "@discordjs/rest";
313
import { SlashCommandBuilder } from "@discordjs/builders";
414

5-
import HttpInteractionServer from "./interactionServer.js";
6-
import InteractionRouterManger from "./interactionRouter/internal.js";
7-
import AutoCompleteKeyBuilder from "./interactionRouter/autoCompleteKeyBuilder.js";
8-
9-
import type { HttpAdapter, HttpAdapterSererResponse } from "./adapter/index.js";
10-
1115
import {
1216
InteractionType,
1317
InteractionResponseType,
@@ -32,10 +36,10 @@ import type {
3236
CommandMiddleware,
3337
CommandbuilderType,
3438
GenericMiddleware,
39+
UserContextMenuMiddleware,
40+
MessageContextMenuMiddleware,
3541
} from "./interactionRouter/internal.js";
3642

37-
import type { MessageMentionOptions } from "discord.js";
38-
3943
export interface ClientOptions {
4044
token: string;
4145
publicKey: string;
@@ -92,7 +96,7 @@ export interface ClientOptions {
9296

9397
class Client extends HttpInteractionServer {
9498
/** Interaction router manager responsible for routing incoming interactions. */
95-
private router = new InteractionRouterManger();
99+
private router = new InteractionRouterManager();
96100

97101
/**
98102
* REST API client instance used for interacting with Discord's HTTP API.
@@ -141,6 +145,7 @@ class Client extends HttpInteractionServer {
141145
*/
142146

143147
middleware(...fns: GeneralMiddleware[]) {
148+
this.tryAsync(fns);
144149
this.router.middlewares.push(...fns);
145150
}
146151

@@ -150,6 +155,7 @@ class Client extends HttpInteractionServer {
150155
* @param fns - Async Functions executed when no handler matches an interaction. See {@link UnknownMiddleware} for callback parameters.
151156
*/
152157
unknown(...fns: UnknownMiddleware[]) {
158+
this.tryAsync(fns);
153159
this.router._unknownInteraction.push(...fns);
154160
}
155161

@@ -176,14 +182,14 @@ class Client extends HttpInteractionServer {
176182
*
177183
* @param commandbuilder - Function returning a {@link SlashCommandBuilder}.
178184
* @param fns {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function | Async} functions. See {@link GenericMiddleware} for callback parameters.
179-
* @returns {@link AutoCompleteKeyBuilder} for autocomplete options.
185+
* @returns an {@link AutoCompleteKeyBuilder} for autocomplete options.
180186
* @example
181187
*
182188
* ```ts
183189
* router.command(
184190
* (builder) =>
185191
* builder.setName("Ping!").setDescription("Returns Pong!"),
186-
* pongHandle
192+
* async (interaction) => await interaction.reply("Pong!")
187193
* );
188194
* ```
189195
*
@@ -206,7 +212,7 @@ class Client extends HttpInteractionServer {
206212
* @param fns - {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function | Async} functions. See {@link GenericMiddleware} for callback parameters.
207213
* @example
208214
* ```ts
209-
* router.button("custom_button_id", buttonMiddleware);
215+
* router.button("custom_button_id", async (interaction) => await interaction.reply("Button Pressed!"));
210216
* ```
211217
*/
212218
button(customId: string, ...fns: ButtonMiddleware[]) {
@@ -303,20 +309,20 @@ class Client extends HttpInteractionServer {
303309
* @param fns {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function | Async} functions. See {@link GenericMiddleware} for callback parameters.
304310
* @example
305311
* ```ts
306-
* const githubQuery = router.command(
307-
* (builder) =>
312+
* const weather = router.command(
313+
* async(builder) =>
308314
* builder
309-
* .setName("weather") // The command name
310-
* .setDescription("Query weather information!") // The command description
315+
* .setName("weather")
316+
* .setDescription("Query weather information!")
311317
* .addStringOption(option =>
312318
* option
313-
* .setName("city") // Option name
314-
* .setDescription("City to get the weather for") // Option description
319+
* .setName("city") // Option Name
320+
* .setDescription("City to get the weather for")
315321
* .setAutocomplete(true) // Enable autocomplete for this option
316322
* ),
317323
* handler
318324
* );
319-
* router.autocomplete(githubQuery.getAutoCompleteKey("city"), autocompleteMiddleware);
325+
* router.autocomplete(weather.getAutoCompleteKey("city"), autocompleteMiddleware);
320326
* ```
321327
*/
322328

@@ -341,12 +347,20 @@ class Client extends HttpInteractionServer {
341347
* @param fns {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function | Async} functions. See {@link GenericMiddleware} for callback parameters.
342348
* @example
343349
* ```ts
344-
* router.userContextMenu("userContextMenuId", userContextMenuMiddleware);
350+
* router.userContextMenu(builder => builder.setName("Hello"), userContextMenuMiddleware);
345351
* ```
346352
*/
347-
userContextMenu(customId: string, ...fns: ContextMenuMiddleware[]) {
353+
userContextMenu(
354+
commandbuilder: userContextCommandBuilderType,
355+
...fns: UserContextMenuMiddleware[]
356+
) {
348357
this.tryAsync(fns);
349-
this.router._register("userContextMenu", customId, fns);
358+
const builder = userContextCommandBuilder();
359+
const build = commandbuilder(builder);
360+
this.router._register("userContextMenu", build.name, fns);
361+
362+
const commandDefinition = build.toJSON();
363+
this.router.CommandDefinitions.push(commandDefinition);
350364
}
351365

352366
/**
@@ -355,12 +369,20 @@ class Client extends HttpInteractionServer {
355369
* @param fns {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function | Async} functions. See {@link GenericMiddleware} for callback parameters.
356370
* @example
357371
* ```ts
358-
* router.messageContextMenu("messageContextMenu", messageContextMenuMiddleware);
372+
* router.messageContextMenu(builder => builder.setName("Hello"), messageContextMenuMiddleware);
359373
* ```
360374
*/
361-
messageContextMenu(customId: string, ...fns: ContextMenuMiddleware[]) {
375+
messageContextMenu(
376+
commandbuilder: messageContextCommandBuilderType,
377+
...fns: MessageContextMenuMiddleware[]
378+
) {
362379
this.tryAsync(fns);
363-
this.router._register("messageContextMenu", customId, fns);
380+
const builder = messageContextCommandBuilder();
381+
const build = commandbuilder(builder);
382+
this.router._register("messageContextMenu", build.name, fns);
383+
384+
const commandDefinition = build.toJSON();
385+
this.router.CommandDefinitions.push(commandDefinition);
364386
}
365387
/**
366388
* Handles incoming interaction payloads from Discord.
@@ -386,7 +408,7 @@ class Client extends HttpInteractionServer {
386408
}
387409
this.debug("Interaction Request Received");
388410
// this.router.__internal_dispatch(res, body, this.client);
389-
await this.router.__internal_dispatch(res, body, this.rest);
411+
await this.router.__internal_dispatch(res, body, this);
390412
}
391413

392414
/**
@@ -507,5 +529,6 @@ class Client extends HttpInteractionServer {
507529
}
508530

509531
export default Client;
532+
export { AttachmentBuilder } from "./structures/Attachment/AttachmentBuilder.js";
510533
export * from "@discordjs/builders";
511534
export * from "discord-api-types/v10";

src/interactionRouter/autoCompleteKeyBuilder.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import type { CommandDefinitionType } from "./internal.js";
1313
*/
1414

1515
export interface APIApplicationCommandAutocompleteInteractionModified {
16-
/** Type of the option (string, number, boolean, etc.). */
16+
/** Type of the option (string, number, etc.). */
1717
type: ApplicationCommandOptionType;
1818

1919
/** Name of the option. */
2020
name: string;
2121

2222
/** Current value of the option if provided. */
23-
value?: string | number | boolean; // The value of the option (can be string, number, or boolean)
23+
value?: string; // The value of the option (can be string, integer, double, or boolean)
2424

2525
/** Whether this option is currently focused. */
2626
focused?: boolean;
@@ -57,7 +57,7 @@ export interface APIApplicationCommandAutocompleteInteractionModified {
5757
* router.autocomplete(weather.getAutoCompleteKey("city"), autocompleteMiddleware);
5858
*/
5959

60-
class AutoCompleteKeyBuilder {
60+
export class AutoCompleteKeyBuilder {
6161
/** @internal Internal list of the path segments collected so far. */
6262
private path: string[] = []; // Array to store path segment
6363

@@ -310,5 +310,3 @@ class AutoCompleteKeyBuilder {
310310
throw Error("Autocomplete event was fired without any options.");
311311
}
312312
}
313-
314-
export default AutoCompleteKeyBuilder;

0 commit comments

Comments
 (0)