### Navigate to an example Source: https://honocord.thelukez.com/examples Change directory to the cloudflare-workers example. ```bash cd examples/cloudflare-workers ``` -------------------------------- ### Install dependencies with pnpm Source: https://honocord.thelukez.com/examples Install project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Usage Example Source: https://honocord.thelukez.com/reference/classes/AutocompleteHelper A code example demonstrating how to instantiate AutocompleteHelper, add choices, and call the response method with filter fields. ```APIDOC ## Usage Example ### Description Example demonstrating how to create an AutocompleteHelper, add choices, and retrieve filtered results based on the input value. ### Code ```ts const helper = new AutocompleteHelper("apple").addChoices( { name: "Apple", value: "apple" }, { name: "Banana", value: "banana" }, { name: "Cherry", value: "cherry" }, { name: "Something else", value: "applejuice" } ); // Returns only the "Apple" choice because "applejuice" is a value and not a name const results = helper.response(["name"]); ``` ``` -------------------------------- ### getApp Usage Example Source: https://honocord.thelukez.com/reference/classes/WebhookEventHandler Example of using getApp in standard mode. Creates a WebhookEventHandler, adds a handler that returns a JSON response, and mounts the returned Hono app under the /discord route. ```typescript import { Hono } from "hono"; const handler = new WebhookEventHandler(ApplicationWebhookEventType.LobbyMessageCreate); handler.addHandler(async (c) => { return c.json({ received: true }); }); // Mount in Hono app const app = new Hono(); app.route("/discord", handler.getApp()); ``` -------------------------------- ### Environment variables for Honocord examples Source: https://honocord.thelukez.com/examples Each example requires these environment variables. Set IS_CF_WORKER to true only when deploying to Cloudflare Workers. ```bash DISCORD_APPLICATION_ID=your_application_id DISCORD_TOKEN=your_bot_token DISCORD_PUBLIC_KEY=your_public_key IS_CF_WORKER=true # omit if not deploying to Cloudflare Workers ``` -------------------------------- ### Custom Redis cache adapter for Honocord Source: https://honocord.thelukez.com/guides/caching Extend the abstract BaseCacheAdapter class and implement the required methods to create a custom cache adapter. This example uses the iovalkey client for both Valkey and Redis, with a ready promise to ensure connection before operations. The adapter supports get, set, mset, delete, and clear, with optional TTL in milliseconds. Then use it with Honocord by passing a factory function to withCache, optionally connecting manually to catch startup errors. ```typescript import Redis from "iovalkey"; // works for both Valkey AND Redis export class RedisCacheAdapter implements CacheAdapter { private client: Redis; private ready: Promise; constructor(urlOrOptions: string | Redis.RedisOptions) { this.client = new Redis(urlOrOptions as any); this.ready = new Promise((resolve, reject) => { this.client.once("ready", resolve); this.client.once("error", reject); }); } async connect(): Promise { await this.ready; return this; } async get(key: string): Promise { await this.ready; const val = await this.client.get(key); if (!val) return null; return JSON.parse(val) as T; } async set(key: string, value: T, ttlMs?: number): Promise { await this.ready; const serialized = JSON.stringify(value); if (ttlMs) { await this.client.set(key, serialized, "PX", ttlMs); // PX = milliseconds TTL } else { await this.client.set(key, serialized); } } async mset(entries: { key: string; value: unknown; ttlMs?: number }[]): Promise { await this.ready; if (entries.length === 0) return; const pipeline = this.client.pipeline(); for (const { key, value, ttlMs } of entries) { const serialized = JSON.stringify(value); if (ttlMs) { pipeline.set(key, serialized, "PX", ttlMs); } else { pipeline.set(key, serialized); } } await pipeline.exec(); } async delete(key: string): Promise { await this.ready; await this.client.del(key); } async clear(): Promise { await this.ready; await this.client.flushdb(); } } ``` ```typescript import { Honocord } from "honocord"; import { RedisCacheAdapter } from "./RedisCacheAdapter"; const cache = new RedisCacheAdapter(process.env.REDIS_URL!, { namespace: "my-bot", ttl: 300, // 5-minute default TTL }); await cache.connect(); // You can also don't do this and let Honocord handle connecting, but doing it yourself allows you to catch connection errors at startup const bot = new Honocord().withCache(() => cache); ``` -------------------------------- ### Install honocord beta with npm, pnpm, yarn, bun, or poop Source: https://honocord.thelukez.com/guides/beta Install the beta version of the honocord package using various package managers. The command 'poop add honocord@beta' is included as displayed in the source. ```bash npm install honocord@beta pnpm add honocord@beta yarn add honocord@beta bun add honocord@beta poop add honocord@beta ``` -------------------------------- ### Install Honocord with npm, pnpm, yarn, bun, or poop Source: https://honocord.thelukez.com/guides/getting-started Install the Honocord package using your preferred package manager. The commands are shown for npm, pnpm, yarn, bun, and poop. ```bash npm install honocord pnpm add honocord yarn add honocord bun add honocord poop add honocord ``` -------------------------------- ### MiddlewareFunction Example Source: https://honocord.thelukez.com/reference/types/MiddlewareFunction An example of defining and using a middleware function with Honocord's bot.use method. ```APIDOC ## MiddlewareFunction Example ### Description Demonstrates how to define a middleware function and register it with the bot using the `use` method. ### Example Code ```typescript const myMiddleware: MiddlewareFunction = async (c, next) => { console.log(`Received interaction: ${c.req.method} ${c.req.path}`); await next(); }; bot.use(myMiddleware); ``` ### Usage - Define a middleware function with the `MiddlewareFunction` type. - Use `bot.use(myMiddleware)` to register it. - The middleware logs the request method and path before calling `next()`. ``` -------------------------------- ### Usage examples for WebhookEventHandler Source: https://honocord.thelukez.com/reference/classes/WebhookEventHandler Provides examples for standard mode, custom environment types, and worker mode. Standard mode requires a Response return. Worker mode allows any return type. For custom Env or Variables, specify T explicitly. ```typescript import { WebhookEventHandler } from "honocord"; import { ApplicationWebhookEventType } from "discord-api-types/v10"; interface MyEnv { DISCORD_PUBLIC_KEY: string; DATABASE: D1Database; } // Standard mode - handler must return Response // T is inferred from constructor argument const standardHandler = new WebhookEventHandler(ApplicationWebhookEventType.EntitlementCreate); // With custom environment types const typedHandler = new WebhookEventHandler( ApplicationWebhookEventType.EntitlementCreate ); // Worker mode - handler can return anything const workerHandler = new WebhookEventHandler(ApplicationWebhookEventType.EntitlementCreate, true); ``` -------------------------------- ### Install Honocord cache adapters Source: https://honocord.thelukez.com/guides/caching Install the cache adapter packages for Honocord. The mongoose package is a peer dependency for the Mongo adapter, and @honocord/cache-base is needed for custom adapters. ```bash pnpm add @honocord/cache-memory pnpm add @honocord/cache-do pnpm add @honocord/cache-mongo mongoose # mongoose is a peer dependency pnpm add @honocord/cache-base # for custom adapters ``` -------------------------------- ### Run local development server Source: https://honocord.thelukez.com/guides/cloudflare-workers Starts the Worker locally at http://localhost:8787. ```bash wrangler dev # Runs at http://localhost:8787 ``` -------------------------------- ### Webhook Handler Setup with Honocord Source: https://honocord.thelukez.com/guides/handlers Setup for webhook handler with Honocord. Load handlers using bot.loadHandlers(). Webhook endpoint automatically mounted at /webhook. Configure Discord webhook URL to point to https://your-domain.com/webhook. ```typescript const bot = new Honocord({ isCFWorker: true }); // Enable CF Workers mode bot.loadHandlers(messageHandler); // Webhook available at /webhook // On CF Workers: responds immediately with 200, processes async // On other platforms: waits for handler to return Response export default bot.getApp(); ``` -------------------------------- ### Install Hono peer dependency Source: https://honocord.thelukez.com/guides/getting-started Install the required peer dependency `hono` using your preferred package manager. Honocord requires `hono@^4.13.1` or higher. ```bash npm install hono pnpm add hono yarn add hono bun add hono ``` -------------------------------- ### Initialize Cloudflare Worker project Source: https://honocord.thelukez.com/guides/cloudflare-workers Commands to create a new Cloudflare Worker project and install Honocord and Hono dependencies. ```bash pnpm create cloudflare@latest my-discord-bot cd my-discord-bot pnpm add honocord hono ``` -------------------------------- ### Run the bot locally with Bun Source: https://honocord.thelukez.com/guides/quickstart Starts the bot locally with Bun in hot-reload mode for development. ```shell bun --hot src/index.ts ``` -------------------------------- ### addHandler Usage Examples (Standard and Worker Mode) Source: https://honocord.thelukez.com/reference/classes/WebhookEventHandler Two usage examples for addHandler. In standard mode, the handler must return a Response (e.g., c.json({ ok: true })). In worker mode, the return value is ignored and can be omitted. ```typescript // Standard mode standardHandler.addHandler(async (c) => { const data = c.var.data; console.log("Received event:", data); return c.json({ ok: true }); // ✅ Required }); // Worker mode workerHandler.addHandler(async (c) => { const data = c.var.data; console.log("Received event:", data); // No return required ✅ }); ``` -------------------------------- ### parseCustomId usage example Source: https://honocord.thelukez.com/reference/functions/parseCustomId Demonstrates parsing a custom ID with path and parameters, and parsing with onlyPrefix set to true to return just the prefix. ```javascript import { parseCustomId } from "@utils"; parseCustomId("modal/user/profile?123/abc"); // { // compPath: ["modal","user","profile"], // prefix: "modal", // lastPathItem: "profile", // component: "user", // params: ["123","abc"], // firstParam: "123", // lastParam: "abc" // } parseCustomId("button/click?123", true); // -> "button" ``` -------------------------------- ### Run the bot locally with Node.js Source: https://honocord.thelukez.com/guides/quickstart Starts the bot locally with Node.js via tsx in hot-reload mode for development. ```shell npx tsx --hot src/index.ts ``` -------------------------------- ### fetch Getter Usage Example Source: https://honocord.thelukez.com/reference/classes/WebhookEventHandler Example of using the fetch getter in standard mode. Creates a WebhookEventHandler, adds a handler that returns a JSON response, and exports the fetch handler bound to the handler instance. ```typescript const handler = new WebhookEventHandler( ApplicationWebhookEventType.EntitlementCreate // Standard mode (default) ); handler.addHandler(async (c) => { return c.json({ ok: true }); }); // Use as fetch handler export default { fetch: handler.fetch.bind(handler), }; ``` -------------------------------- ### Example slash command handler Source: https://honocord.thelukez.com/guides/cloudflare-workers Defines a ping command handler that replies with a pong message. ```typescript import { SlashCommandHandler } from "honocord"; export const pingCommand = new SlashCommandHandler() .setName("ping") .setDescription("Check bot latency") .addHandler(async (interaction) => { await interaction.reply("🏓 Pong!"); }); ``` -------------------------------- ### Expose local server with ngrok Source: https://honocord.thelukez.com/guides/quickstart Starts an ngrok tunnel to expose the local server on port 3000, providing an HTTPS URL for the Discord Interactions Endpoint. ```shell ngrok http 3000 ``` -------------------------------- ### Run a quick tunnel with cloudflared Source: https://honocord.thelukez.com/guides/cloudflare-tunnel Instantly exposes a local Worker (typically on port 8787) via a randomly generated trycloudflare.com subdomain. No setup or authentication is required. ```bash cloudflared tunnel --url http://localhost:8787 ``` -------------------------------- ### MiddlewareFunction usage example Source: https://honocord.thelukez.com/reference/types/MiddlewareFunction Shows a middleware that logs the request method and path, then calls await next() to continue. The middleware is registered with bot.use(). ```typescript const myMiddleware: MiddlewareFunction = async (c, next) => { console.log(`Received interaction: ${c.req.method} ${c.req.path}`); await next(); }; bot.use(myMiddleware); ``` -------------------------------- ### getApp(options?: { interactionsPath?: string; webhookPath?: string }): Hono<{ Variables: BaseVariables }> Source: https://honocord.thelukez.com/reference/classes/Honocord Returns a Hono application with a health GET on all routes, the interactions POST mounted at `/` and `options.interactionsPath` (default `/interactions`) when command handlers are registered, and the webhook POST at `options.webhookPath` (default `/webhook`) when webhook handlers are registered. ```APIDOC ## getApp(options?: { interactionsPath?: string; webhookPath?: string }): Hono<{ Variables: BaseVariables }> ### Description Returns a Hono application with a health GET on all routes, the interactions POST mounted at `/` and `options.interactionsPath` (default `/interactions`) when command handlers are registered, and the webhook POST at `options.webhookPath` (default `/webhook`) when webhook handlers are registered. ### Method getApp ### Parameters #### Options - **interactionsPath** (string) - Optional - Path for the interactions POST endpoint. Defaults to `/interactions`. - **webhookPath** (string) - Optional - Path for the webhook POST endpoint. Defaults to `/webhook`. ### Returns - **Hono<{ Variables: BaseVariables }>** - The Hono application. ``` -------------------------------- ### Create a User context menu command with ContextCommandHandler Source: https://honocord.thelukez.com/guides/handlers Creates a User context menu command named "Get ID" that replies with the target user's ID. Requires the honocord package and uses ContextCommandType.User. ```typescript import { ContextCommandHandler, ContextCommandType } from "honocord"; const userContext = new ContextCommandHandler(ContextCommandType.User).setName("Get ID").addHandler(async (ctx) => { await ctx.reply(`The user's ID is ${ctx.targetId}`); }); ``` -------------------------------- ### Run named tunnel with cloudflared Source: https://honocord.thelukez.com/guides/cloudflare-tunnel Starts the named tunnel, making the local service available at the configured custom domain. ```bash cloudflared tunnel run mytunnel ``` -------------------------------- ### Instantiate SlashCommandHandler Source: https://honocord.thelukez.com/reference/classes/SlashCommandHandler Creates a new SlashCommandHandler instance. Use this constructor to start defining a Discord slash command. ```javascript new SlashCommandHandler(); ``` -------------------------------- ### Import Colors from honocord and use Colors.Blue in an embed Source: https://honocord.thelukez.com/reference/constants/colors Import the Colors object from the honocord package and use a color constant (e.g., Colors.Blue) when constructing an embed object. The snippet shows the required import and a minimal embed example. ```typescript import { Colors } from "honocord"; // Example usage: const embed = { color: Colors.Blue, title: "Hello World", }; ``` -------------------------------- ### Use DurableObjectCacheAdapter with Worker setup Source: https://honocord.thelukez.com/guides/caching Set up the DurableObjectCacheAdapter on Cloudflare Workers. The Honocord instance uses a factory that receives the environment and creates the adapter with the MY_CACHE_DO binding. You must export the HonocordCacheDO class from your index.ts and configure the durable_objects bindings and migrations in wrangler.jsonc. The migrations are required to create the Durable Object namespace. ```typescript import { Honocord } from "honocord"; import { DurableObjectCacheAdapter } from "@honocord/cache-do"; const bot = new Honocord().withCache((env) => new DurableObjectCacheAdapter(env.MY_CACHE_DO)); export default bot.getApp(); export { HonocordCacheDO } from "@honocord/cache-do"; // You need to export the Durable Object class so you can use it ``` ```json { // ... other config options "durable_objects": { "bindings": [ { "name": "MY_CACHE_DO", // This is the binding name that is used by the `env` in the factory function "class_name": "HonocordCacheDO" // This is the class you exported from your index.ts file } ] }, "migrations": [ { "tag": "v1", "new_sqlite_classes": ["HonocordCacheDO"] // This is the class you exported from your index.ts file } ] } ``` -------------------------------- ### Copy and configure environment file Source: https://honocord.thelukez.com/examples Copy the .env.example file to .env and edit it with your Discord credentials. ```bash cp .env.example .env # Edit .env with your Discord credentials ``` -------------------------------- ### Clone the repository Source: https://honocord.thelukez.com/examples Clone the honocord-examples repository and navigate into the directory. ```bash git clone https://github.com/The-LukeZ/honocord-examples.git cd honocord-examples ``` -------------------------------- ### Create .env file with Discord credentials Source: https://honocord.thelukez.com/guides/getting-started Create a `.env` file in your project root with your Discord application ID, public key, and bot token. ```plaintext DISCORD_APPLICATION_ID=your_application_id_here DISCORD_PUBLIC_KEY=your_public_key_here DISCORD_TOKEN=your_bot_token_here ``` -------------------------------- ### Run the registration script with Node, Bun, or tsx Source: https://honocord.thelukez.com/guides/quickstart Runs the registration script with Node.js, Bun, or tsx, loading environment variables from a .env file. Choose the command that matches your runtime. ```shell node --env-file=.env src/register.ts bun --env-file=.env src/register.ts npx tsx --env-file=.env src/register.ts ``` -------------------------------- ### Create a basic Honocord bot with a ping command Source: https://honocord.thelukez.com/guides/quickstart Creates a minimal Honocord bot with a single slash command named "ping" that replies with "🏓 Pong!". The bot is initialized, the command is loaded, and the app is exported as the default export. ```typescript import { Honocord, SlashCommandHandler } from "honocord"; // Initialize Honocord const bot = new Honocord(); // Create a simple command const pingCommand = new SlashCommandHandler() .setName("ping") .setDescription("Replies with Pong!") .addHandler(async (interaction) => { await interaction.reply("🏓 Pong!"); }); // Load the command bot.loadHandlers(pingCommand); // Export the app export default bot.getApp(); ``` -------------------------------- ### use(...middleware: MiddlewareFunction[]): this Source: https://honocord.thelukez.com/reference/classes/Honocord Registers middleware functions that run in-order before handlers. Middleware signature: `async (c, next) => Promise`. Use `c.get`/`c.set` to share data. ```APIDOC ## use(...middleware: MiddlewareFunction[]): this ### Description Registers middleware functions that run in-order before handlers. Middleware signature: `async (c, next) => Promise`. Use `c.get`/`c.set` to share data. ### Method use ### Parameters #### Middleware - **middleware** (MiddlewareFunction[]) - Required - Middleware functions to register. ``` -------------------------------- ### Use MongoCacheAdapter with Honocord Source: https://honocord.thelukez.com/guides/caching Set up the MongoCacheAdapter with a MongoDB URI from the environment. You must call connect() before using the adapter. The adapter is passed to the Honocord instance via withCache. ```typescript import { Honocord } from "honocord"; import { MongoCacheAdapter } from "@honocord/cache-mongo"; const cache = new MongoCacheAdapter(process.env.MONGO_URI!); await cache.connect(); // You need to connect to the database before using the cache adapter const bot = new Honocord().withCache(() => cache); ``` -------------------------------- ### registerCommands(token?, applicationId?, ...handlers) Source: https://honocord.thelukez.com/reference/functions/registerCommands Deploys application commands to Discord. It filters handlers to only those with handlerType 'slash' or 'context', and registers them either globally or to specific guilds based on the presence of guildIds. If token or applicationId is missing, it logs a warning and skips registration. ```APIDOC ## registerCommands(token?, applicationId?, ...handlers) ### Description Deploys application commands (Slash Commands and Context Menus) to Discord. It automatically handles the distinction between global commands and guild-specific commands based on the handler configuration. ### Parameters - **token** (string) - Optional - Your Discord bot token. - **applicationId** (string) - Optional - Your Discord application ID. - **...handlers** (FlatOrNestedArray) - Required - Rest parameter containing individual handlers or arrays of handlers. ### Behavior - **Internal Filtering**: The function automatically extracts handlers with a `handlerType` of `slash` or `context`. Other handler types are ignored during registration. - **Global vs Guild**: - If a command is marked as a guild command (via `guildIds`), it will be registered specifically to those guilds using `bulkOverwriteGuildCommands`. - Otherwise, it is registered globally via `bulkOverwriteGlobalCommands`. - **Validation**: If `token` or `applicationId` is missing, the function logs a warning and skips registration. These can be `undefined` because your types may be not working. ### Example ```javascript import { registerCommands } from "honocord"; import { myCommands } from "./commands"; await registerCommands(process.env.DISCORD_TOKEN, process.env.APPLICATION_ID, ...myCommands); ``` ``` -------------------------------- ### Run tests with pnpm Source: https://honocord.thelukez.com/github Commands to run the test suite with Vitest. The first runs all tests, the second enables watch mode for development. ```bash pnpm test # Run all tests pnpm test --watch # Run in watch mode ``` -------------------------------- ### Apply custom context type to SlashCommandHandler and ComponentHandler Source: https://honocord.thelukez.com/guides/typings Shows how to pass MyContext as a generic parameter to SlashCommandHandler and ComponentHandler to get fully typed ctx.env and ctx.var in handlers. ```typescript import { SlashCommandHandler, ComponentHandler } from "honocord"; import { ComponentType } from "discord-api-types/v10"; import type { MyContext } from "./types"; // Slash Commands const command = new SlashCommandHandler().setName("greet").addHandler(async (ctx) => { // ctx.env and ctx.var are now fully typed! const db = ctx.env.DATABASE; }); // Component Handlers const button = new ComponentHandler("my_id", ComponentType.Button).addHandler(async (ctx) => { const userId = ctx.get("user_id"); }); ``` -------------------------------- ### Using AutocompleteHelper to filter choices Source: https://honocord.thelukez.com/guides/handlers Uses AutocompleteHelper with addChoices and responds with choices filtered to those starting with the user's input. The response method takes an array of properties to use as the name. ```typescript import { AutocompleteHelper } from "honocord"; command.addAutocompleteHandler(async (ctx) => { const focused = ctx.options.getFocused()!; const helper = new AutocompleteHelper(focused.value).addChoices( { name: "Apple", value: "apple" }, { name: "Banana", value: "banana" }, { name: "Cherry", value: "cherry" } ); // Automatically filters choices that start with the user's input await ctx.respond(helper.response(["name"])); }); ``` -------------------------------- ### Send a modal with ModalBuilder Source: https://honocord.thelukez.com/guides/modals Use interaction.showModal() with a ModalBuilder instance to send a modal. This example creates a modal with a label component containing a text input. Note that the builders do not support the new checkbox, checkbox-group, and radio-group components. ```typescript import { ModalBuilder, LabelBuilder, TextInputStyle } from "honocord"; const modal = new ModalBuilder() .setCustomId("my-modal") .setTitle("My Modal") .addLabelComponents( new LabelBuilder() .setLabel("Name") .setDescription("Enter your name") .setTextInputComponent((tiBuilder) => tiBuilder.setCustomId("name").setStyle(TextInputStyle.Short).setRequired(true)) ); interaction.showModal(modal); ``` -------------------------------- ### new Honocord(options?: { isCFWorker?: boolean; debugRest?: boolean; cacheTtlMs?: number }) Source: https://honocord.thelukez.com/reference/classes/Honocord Creates a new Honocord instance with optional configuration for Cloudflare Workers, REST debugging, and cache TTL. ```APIDOC ## new Honocord(options?: { isCFWorker?: boolean; debugRest?: boolean; cacheTtlMs?: number }) ### Description Creates a new Honocord instance with optional configuration for Cloudflare Workers, REST debugging, and cache TTL. ### Constructor ```typescript new Honocord(options?: { isCFWorker?: boolean; debugRest?: boolean; cacheTtlMs?: number; }) ``` ### Parameters #### Options - **isCFWorker** (boolean) - Optional - Enable Cloudflare Workers async processing (also detected via env `c.env.IS_CF_WORKER === "true"`). - **debugRest** (boolean) - Optional - Enable REST debug listeners to log requests/responses. - **cacheTtlMs** (number) - Optional - Default TTL in milliseconds for cached entities when a cache adapter is registered via `withCache`. Set `0` to disable expiration. ``` -------------------------------- ### Handle button interactions with ComponentHandler prefix matching Source: https://honocord.thelukez.com/guides/handlers Creates a button component handler that matches any button whose custom_id starts with "vote:". It splits the custom_id to extract the candidate and replies with the vote confirmation. ```typescript import { ComponentHandler } from "honocord"; import { ComponentType } from "discord-api-types/v10"; // Matches any button with a custom_id starting with "vote:" const voteButton = new ComponentHandler("vote", ComponentType.Button).addHandler(async (ctx) => { const [_, candidate] = ctx.customId.split(":"); await ctx.reply(`You voted for ${candidate}!`); }); ``` -------------------------------- ### Creating Component and Context Command Handlers Source: https://honocord.thelukez.com/guides/handlers Shows how to instantiate ComponentHandler and ContextCommandHandler. The type must be passed twice: as a generic and constructor parameter. The type argument ensures IDE IntelliSense; the constructor parameter is used for validation and routing. ```typescript // Component Handlers const mySelect = new ComponentHandler("role_select", ComponentType.RoleSelect); // Context Menu Commands const myMessageCommand = new ContextCommandHandler(ContextCommandType.Message); ``` -------------------------------- ### Send a modal with raw ModalInteractionResponseCallbackData Source: https://honocord.thelukez.com/guides/modals Use interaction.showModal() with a raw ModalInteractionResponseCallbackData object to send a modal. This is required for using the new checkbox, checkbox-group, and radio-group components, as the builders do not support them. The example includes a label, a checkbox group, and a radio group. ```typescript import type { ModalInteractionResponseCallbackData } from "honocord"; const modalData: ModalInteractionResponseCallbackData = { title: "Test Modal", custom_id: "test_modal", components: [ { type: ComponentType.Label, label: "This is a label", component: { type: ComponentType.Checkbox, custom_id: "checkbox_1", }, }, { type: ComponentType.Label, label: "This is a text input", component: { type: ComponentType.CheckboxGroup, custom_id: "checkbox_group_1", options: [ { label: "Option 1", description: "This is option 1", value: "option_1", }, { label: "Option 2", value: "option_2", }, ], }, }, { type: ComponentType.Label, label: "This is a select menu", component: { type: ComponentType.RadioGroup, custom_id: "radio_group_1", options: [ { label: "Option A", description: "This is option A", value: "option_a", }, { label: "Option B", value: "option_b", }, ], }, }, ], }; interaction.showModal(modalData); ``` -------------------------------- ### new CacheManager(adapter, defaultTtlMs?) Source: https://honocord.thelukez.com/reference/classes/CacheManager Creates a new CacheManager instance with a cache adapter and optional default TTL. ```APIDOC ## Constructor ### Description Creates a new CacheManager instance. ### Parameters - **adapter** (BaseCacheAdapter) - Required - The cache backend to use. - **defaultTtlMs** (number) - Optional - Fallback TTL in milliseconds for all set/mset calls that do not supply their own TTL. Defaults to 300000 (5 minutes). ### Example ```ts const cache = new CacheManager(adapter, 300000); ``` ``` -------------------------------- ### new ComponentHandler(prefix, componentType, handler?) Source: https://honocord.thelukez.com/reference/classes/ComponentHandler Creates a new ComponentHandler instance with a prefix, component type, and optional initial handler function. ```APIDOC ## Constructor ### Description Creates a new ComponentHandler instance. ### Signature ``` new ComponentHandler( prefix: string, componentType: CType, handler?: (interaction: MessageComponentInteractionObj) => Promise | any ) ``` ### Parameters - **prefix** (string) - Required - The unique prefix of the `custom_id` to match this handler. - **componentType** (CType) - Required - The type of component (e.g., `ComponentType.Button`, `ComponentType.StringSelect`). - **handler** (function) - Optional - An optional initial handler function. ``` -------------------------------- ### Use MemoryCacheAdapter with Honocord Source: https://honocord.thelukez.com/guides/caching Set up the MemoryCacheAdapter with a TTL of 300 seconds and a cleanup interval of 600 seconds. The cleanupInterval is only supported by this adapter. The adapter is passed to the Honocord instance via withCache. ```typescript import { Honocord } from "honocord"; import { MemoryCacheAdapter } from "@honocord/cache-memory"; const cache = new MemoryCacheAdapter({ ttl: 300, cleanupInterval: 600, // Interval in seconds for automatic cleanup of expired entries. This is only supported by this adapter as of now. }); const bot = new Honocord().withCache(() => cache); ``` -------------------------------- ### Build and typecheck with pnpm Source: https://honocord.thelukez.com/github Build and type-check commands for the monorepo. Use pnpm build for the root package, pnpm build:all for all cache packages, and pnpm typecheck for type checking. ```bash pnpm build # Build the root package pnpm build:all # Build root and all cache packages pnpm typecheck # Type check the root package ``` -------------------------------- ### withCache(factory: (env: TheEnv) => BaseCacheAdapter): this Source: https://honocord.thelukez.com/reference/classes/Honocord Registers a cache adapter factory. The factory receives the request environment and returns a `BaseCacheAdapter` instance. Called once per unique environment on first use. ```APIDOC ## withCache(factory: (env: TheEnv) => BaseCacheAdapter): this ### Description Registers a cache adapter factory. The factory receives the request environment and returns a `BaseCacheAdapter` instance. Called once per unique environment on first use. ### Method withCache ### Parameters #### Factory - **factory** ((env: TheEnv) => BaseCacheAdapter) - Required - Factory function that receives the request environment and returns a cache adapter. ``` -------------------------------- ### getApp() (method) Source: https://honocord.thelukez.com/reference/classes/WebhookEventHandler Returns the internal Hono app for standalone usage in standard mode. Throws an error if called in worker mode. ```APIDOC ## getApp() (method) ### Description Returns the internal Hono app for standalone usage. Only available in standard mode (`ForWorker = false`). ### Method getApp ### Throws Error if called in worker mode. ### Example ```typescript import { Hono } from "hono"; const handler = new WebhookEventHandler(ApplicationWebhookEventType.LobbyMessageCreate); handler.addHandler(async (c) => { return c.json({ received: true }); }); // Mount in Hono app const app = new Hono(); app.route("/discord", handler.getApp()); ``` ``` -------------------------------- ### Create button and handler with prefix matching Source: https://honocord.thelukez.com/guides/custom-id-system Demonstrates creating a button with a custom ID that includes a prefix and a parameter, and registering a handler that matches by prefix. The handler uses parseCustomId to extract the component path, first parameter, and full component path. Note the 100-character limit for custom IDs. ```typescript import { ComponentHandler, ButtonBuilder, parseCustomId } from "honocord"; new ButtonBuilder().setCustomId("report/user?123456789").setLabel("Report User"); // Handler matches by prefix const reportHandler = new ComponentHandler("report").addHandler(async (interaction) => { const { component, firstParam, compPath } = parseCustomId(interaction.custom_id); // component = "user" // firstParam = "123456789" // compPath = ["report", "user"] }); ``` -------------------------------- ### Bot entry point for Cloudflare Workers Source: https://honocord.thelukez.com/guides/cloudflare-workers Creates a Honocord instance with isCFWorker true, loads handlers, and exports the app as a Worker fetch handler. ```typescript import { Honocord } from "honocord"; import * as handlers from "./handlers"; const bot = new Honocord({ isCFWorker: true }); // Auto-detected via IS_CF_WORKER bot.loadHandlers(...Object.values(handlers)); export default bot.getApp(); // Export as Worker fetch handler ``` -------------------------------- ### Expose local server with tunnel Source: https://honocord.thelukez.com/guides/cloudflare-workers Commands to expose the local server publicly for Discord verification using cloudflared or ngrok. ```bash cloudflared tunnel --url http://localhost:8787 # Recommended # or ngrok http 8787 ``` -------------------------------- ### Test directory structure Source: https://honocord.thelukez.com/github Shows the test directory structure under src/tests/, mirroring the module layout. Use it to locate test files for interactions and utilities. ```text src/ ├── tests/ │ ├── interactions/ │ │ └── BaseInteraction.test.ts │ └── utils/ │ └── Autocomplete.test.ts ├── interactions/ ├── utils/ └── ... ``` -------------------------------- ### Load the handler into Honocord Source: https://honocord.thelukez.com/guides/webhook-events Loads the webhook event handler into a Honocord bot and exposes the app. The webhook will be available at the /webhook endpoint. Use this after creating the handler to make it active. ```typescript import { Honocord } from "honocord"; const bot = new Honocord(); bot.loadHandlers(entitlementHandler); export default bot.getApp(); // Webhook available at /webhook ``` -------------------------------- ### Configure wrangler.jsonc for Honocord Source: https://honocord.thelukez.com/guides/cloudflare-workers Required wrangler configuration with nodejs_compat flag and IS_CF_WORKER variable. Without nodejs_compat, Workers will throw an error when building due to node:path usage. ```json { "name": "my-discord-bot", "main": "src/index.ts", "compatibility_date": "2024-01-01", "compatibility_flags": ["nodejs_compat"], "vars": { "IS_CF_WORKER": "true", }, } ``` -------------------------------- ### Deploy Discord commands with registerCommands Source: https://honocord.thelukez.com/reference/functions/registerCommands Use this snippet to deploy your application commands to Discord. It imports the registerCommands utility and your command handlers, then calls registerCommands with your bot token, application ID, and the spread of your commands. The function automatically handles global vs guild-specific commands based on handler configuration. ```typescript import { registerCommands } from "honocord"; import { myCommands } from "./commands"; await registerCommands(process.env.DISCORD_TOKEN, process.env.APPLICATION_ID, ...myCommands); ``` -------------------------------- ### Standalone WebhookEventHandler usage with fetch or Hono app Source: https://honocord.thelukez.com/guides/webhook-events Use WebhookEventHandler standalone in standard mode. Create a handler for EntitlementCreate, add an event handler, then expose it either as a fetch handler or mount it in a Hono app. Worker mode cannot use fetch() or getApp(); it must use Honocord's webhookHandler. ```javascript import { Hono } from "hono"; import { WebhookEventHandler } from "honocord"; const handler = new WebhookEventHandler(ApplicationWebhookEventType.EntitlementCreate); handler.addHandler(async (c) => { // Process event return c.json({ ok: true }); }); // Option 1: As a fetch handler export default { fetch: handler.fetch.bind(handler), }; // Option 2: Mount in Hono app const app = new Hono(); app.route("/webhooks", handler.getApp()); export default app; ``` -------------------------------- ### new AutocompleteHelper(value, user?) Source: https://honocord.thelukez.com/reference/classes/AutocompleteHelper Creates a new AutocompleteHelper instance with the current user input value and an optional user object for localized results. The user object is used to provide localized results if available. ```APIDOC ## Constructor: new AutocompleteHelper(value, user?) ### Description Creates a new AutocompleteHelper instance to manage and filter autocomplete choices for Discord application commands. The value parameter is the current input from the user, and an optional user object allows for localized results. ### Parameters - `value` (T) - Required - The current input value from the user to filter against. - `user?` (APIUser) - Optional - The user object, used to provide localized results if available. ``` -------------------------------- ### Fetcher Source: https://honocord.thelukez.com/reference/classes/Fetcher Documentation for the Fetcher class, a cache-first REST wrapper available on interaction objects. ```APIDOC ## Fetcher ### Description `Fetcher` is a cache-first REST wrapper available on every interaction object as `interaction.fetcher`. It checks the `CacheManager` before making a live Discord API request, and writes the result back to the cache automatically. If no cache adapter is configured, `Fetcher` bypasses the cache and always fetches from the API. ### Constructor `Fetcher` is instantiated internally by `BaseInteraction` — you do not construct it directly. ### Public properties #### `api: API` (readonly) The raw `@discordjs/core` `API` instance. Use this for any Discord REST call not covered by the named accessors. ```js await interaction.fetcher.api.stickers.get(stickerId); ``` ### Namespaced accessors #### `users` ##### `get(userId: string): Promise` Fetches a user by ID. Returns the cached value if available, otherwise fetches from Discord and caches the result. #### `channels` ##### `get(channelId: string): Promise` Fetches a channel by ID. Returns the cached value if available, otherwise fetches from Discord and caches the result. #### `dmChannels` ##### `get(userId: string): Promise` Fetches a DM channel for a user. Returns the cached value if available, otherwise creates a new DM channel via Discord and caches the result. #### `guilds` ##### `get(guildId: string): Promise` Fetches a guild by ID. Returns the cached value if available, otherwise fetches from Discord and caches the result. #### `roles` ##### `get(guildId: string, roleId: string): Promise` Fetches a single role. If not cached, fetches **all** roles for the guild via `guilds.getRoles` and returns the matching one. ##### `list(guildId: string): Promise` Fetches **all** roles for a guild. Returns cached roles if available (via `CacheManager.getGuildRoles`), otherwise fetches from Discord and bulk-caches the result. #### `members` ##### `get(guildId: string, userId: string): Promise` Fetches a guild member by user ID. Returns the cached value if available, otherwise fetches from Discord and caches the result. ``` -------------------------------- ### Honocord constructor options Source: https://honocord.thelukez.com/reference/classes/Honocord Constructor for the Honocord class. Accepts optional configuration: isCFWorker enables Cloudflare Workers async processing (also detected via env c.env.IS_CF_WORKER === "true"), debugRest enables REST debug listeners, and cacheTtlMs sets the default TTL in milliseconds for cached entities when a cache adapter is registered via withCache. Set cacheTtlMs to 0 to disable expiration. ```typescript new Honocord(options?: { isCFWorker?: boolean; debugRest?: boolean; cacheTtlMs?: number; }) ``` -------------------------------- ### Fetch a user with ctx.fetcher.users.get Source: https://honocord.thelukez.com/guides/caching Fetches a user by ID through the Fetcher utility. The Fetcher first checks the cache and returns the cached user if present; otherwise it fetches from the Discord API, caches the result, and returns it. ```javascript const user = await ctx.fetcher.users.get(userId); ```