{"id":15420032,"url":"https://github.com/ianeli1/discordjs-diy","last_synced_at":"2026-01-24T01:31:37.058Z","repository":{"id":39915281,"uuid":"352185099","full_name":"ianeli1/discordjs-diy","owner":"ianeli1","description":"Easy to use, do-it-yourself Discord.js mini-framework","archived":false,"fork":false,"pushed_at":"2023-10-04T23:20:50.000Z","size":601,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T08:51:13.516Z","etag":null,"topics":["bot","chatbot","discord","discordjs","library"],"latest_commit_sha":null,"homepage":"https://ianeli1.github.io/discordjs-diy/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ianeli1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-27T21:54:03.000Z","updated_at":"2022-09-03T13:16:50.000Z","dependencies_parsed_at":"2024-10-20T01:33:21.441Z","dependency_job_id":"b9b9e413-eb25-4201-95d3-17d3e2262a38","html_url":"https://github.com/ianeli1/discordjs-diy","commit_stats":{"total_commits":162,"total_committers":5,"mean_commits":32.4,"dds":"0.24691358024691357","last_synced_commit":"37b93f6325fbe0d598f8bec52d416ba1788f9a1c"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianeli1%2Fdiscordjs-diy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianeli1%2Fdiscordjs-diy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianeli1%2Fdiscordjs-diy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianeli1%2Fdiscordjs-diy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ianeli1","download_url":"https://codeload.github.com/ianeli1/discordjs-diy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249718225,"owners_count":21315083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","chatbot","discord","discordjs","library"],"created_at":"2024-10-01T17:27:56.902Z","updated_at":"2026-01-24T01:31:37.028Z","avatar_url":"https://github.com/ianeli1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Discord.js - DIY\n\n[![npm](https://img.shields.io/npm/v/discordjs-diy)]()\n\nEasy to use, do-it-yourself Discord.js mini-framework\n\nYou can find [the full reference wiki here.](https://ianeli1.github.io/discordjs-diy/)\n\n### What can I use it for\n\nMaking Discord.JS bots when you're in a run. You can get started with only 2 lines! (incluiding the import)!\n\n### How do I use it\n\nAll you need to get started is install it using `npm install discordjs-diy` and import it into your project.\n\n```ts\nimport { Bot } from \"discordjs-diy\";\n\nconst bot = new Bot(\"\u003cyour Discord API token\u003e\", { prefix: \"!\" });\nbot.registerAction(\"ping\", \"pong\"); //!ping =\u003e pong\n```\n\n### What if I want my bot to do cool stuff?\n\n```ts\nimport { Bot } from \"discordjs-diy\";\nconst bot = new Bot(\"\u003cyour Discord API token\u003e\", { prefix: \"?\" });\nbot.registerAction(\n  \"rate\",\n  ({ args }) =\u003e\n    `You want me to rate ${args}? Ok... ${Math.floor(Math.random() * 10)}/10`\n); //?rate something =\u003e The bot replies!\n```\n\n```ts\nimport { Bot } from \"discordjs-diy\";\nconst bot = new Bot(\"\u003cyour Discord API token\u003e\", { prefix: \"*\" });\nbot.registerAction(\"reactAndReply\", {\n  response: \"Hello!\",\n  reaction: () =\u003e \"🤓\",\n}); //*reactAndReply =\u003e The bot can also react to messages and reply!\n```\n\n```ts\nimport { Bot } from \"discordjs-diy\";\nconst bot = new Bot(\"\u003cyour Discord API token\u003e\", { prefix: \"*\", ignoreCaps });\nbot.registerAction(\"await\", {\n  response: async ({ msg }) =\u003e await waitForResponse(msg.author),\n}); //*AWAIT =\u003e bot can ignore caps and use async/await!\n```\n\n### Updating Discord presence\n\nThe bot can also easily update presence information\n\n```ts\nconst bot = new Bot(\"\u003cyou know the deal\u003e\", { prefix: \"!\" });\nbot.setPresence([\"a game\", \"PLAYING\"]);\n//or, in case you want it to change every 10 minutes\nbot.setPresence([\n  [\"a game\", \"PLAYING\"],\n  [\"a movie\", \"WATCHING\"],\n]);\n//you can also set your own time (in ms)\nbot.setPresence(\n  [\n    [\"a game\", \"PLAYING\"],\n    [\"a movie\", \"WATCHING\"],\n  ],\n  5 * 60 * 1000\n);\n```\n\n### What if I want to do my own thing\n\nYou can always access the normal client object from Discord.JS\n\n```ts\nconst bot = new Bot(\"\u003cyou know the deal\u003e\", { prefix: \"!\" });\nbot.client.on(\"\u003csome action\u003e\", () =\u003e \"\u003cdo something\u003e\");\n```\n\n### Using embeds\n\nDiscordjs-diy tries to make using embeds a little easier. You first need to create an `Embed` object\n\n```ts\nimport { Embed } from \"discordjs-diy\";\n\nconst embed = new Embed({\n  //you can customize the Embed here, all parameters are optional\n  color: \"#0000FF\", //blue\n});\n```\n\nTo use your embeds in your bot you can pass the object to your bot's object\n\n```ts\nconst embed = new Embed({});\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nbot.registerAction(\"test\", ({ args, createEmbed }) =\u003e\n  createEmbed({ desc: args })\n);\n//!test hello =\u003e embed containing hello as a description\n```\n\nBots will usually use a collection of images to represent emotions, you can use them easily with the `embed.registerImage` method\n\n```ts\nconst embed = new Embed({});\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nembed.registerImage(\"happy\", \"\u003curl to image\u003e\");\nbot.registerAction(\"test\", ({ args, createEmbed }) =\u003e\n  createEmbed({ desc: args, sideImage: \"happy\" })\n);\n//!test hello =\u003e embed containing hello as a description and the image \"test\"\n```\n\nIn case your bot requires it, you can set a custom format for the embed description and the footer\n\n```ts\nconst embed = new Embed({\n  descTransform: (desc: string) =\u003e `${desc}, hello!`, //hello =\u003e hello, hello!\n  refTransform: (user: User) =\u003e [\n    `User: ${user.username}`,\n    user.avatarURL() ?? undefined,\n  ],\n});\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nbot.registerAction(\"test\", ({ msg, args, createEmbed }) =\u003e\n  createEmbed({ desc: args, reference: msg.author })\n);\n//!test hello =\u003e embed containing \"hello, hello!\" as a description and the footer containing \"User: \u003cname\u003e\"\n```\n\nAlso your embeds can contain the avatar and name of the bot\n\n```ts\nconst embed = new Embed({\n  author: bot.user,\n});\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nbot.registerAction(\"test\", ({ args, createEmbed }) =\u003e\n  createEmbed({ desc: args })\n);\n```\n\n### Handling typos\n\nYour users can be overwhelmed and confused by your bot's syntax. To aid them in the process, djs-diy offers a way to immediately point out which options they might have meant to type instead.\n\n```ts\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nbot.on(\"test\", \"hi there!\");\nbot.onTypo(\n  ({ author }, [first, ...rest]) =\u003e\n    `Hey there, ${\n      author.username\n    }! Did you mean to type !${first}? Other options: ${rest.join(\", \")}`\n);\n```\n\n`Bot#onTypo` can set a callback for an scenario where an user types \"tsst\" or something similar as any other trigger.\nShould be noted that onTypo is available router-wise and will always attempt to fetch a callback from any parent router (incluiding the Bot object's)\n\n`onTypo` can take a second argument in the form of an object\n\n```ts\n{\n  maxDistance: number;\n  maxSuggestions: number;\n}\n```\n\n`maxDistance`: Maximum [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) allowed\n`maxSuggestions`: Max amount of suggestions to be provided to the callback\n\n### Routing\n\nSometimes you may want a command to contain a subcommand. This is where routers come in. To use them, create a new Router object then assign commands to it. Finally assign it as an action in your main `Bot` object. Don't worry about the constructor parameters, they'll be filled in for you.\n\n```ts\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\" });\n\nconst helpRouter = new Router();\nhelpRouter.on(\"info\", \"lorem ipsum\");\n\nbot.on(\"help\", helpRouter);\n//Bot will now respond to `!help info` with \"lorem ipsum\"\n```\n\nRouters have their own error handling too.\n\n```ts\nhelpRouter.onError(\"Oh no!\");\n//if any of the commands under help router fail, \"Oh no!\" will be sent instead\n```\n\nRouters also have full support for slash commands.\n\n### Expecting replies\n\nYou can easily do a 2 part command, expecting a reply from the same user\n\nFor example, a simple conversation could go like\n\n```ts\n(user) =\u003e \"!wakeMeUp\";\n(bot) =\u003e \"When should I wake you up?\";\n(user) =\u003e \"When September ends\";\n(bot) =\u003e \"Ok, I'll wake you up When September ends\";\n```\n\nThis can be easily achieved with the `expectReply` method the action toolkit provides\n\n```ts\nbot.registerAction(\"wakeMeUp\", async ({ expectReply }) =\u003e {\n  //built in Promise handling!\n  const reply = await expectReply(\"When should I wake you up?\", true); //You can choose if the bot should delete this message or not by setting the second parameter\n  return `Ok, I'll wake you up ${reply?.content}`;\n});\n```\n\nThe `expectReply()` promise will resolve to `undefined` if there's a timeout\n\n### Automatic Slash Command Support\n\nDiscordjs-DIY comes with integrated slash command generation. When you execute the `.registerAction` method, the library automatically generates a slash command JSON to be sent to the API.\n\nThe default is a command with no parameters and a description of \"A command\"\n\nTo specify parameters manually, add a `parameters` property or a third parameter to `.registerAction`.\n\nExample parameters array:\n\n```ts\n[\n  {\n    name: \"key\",\n    type: \"STRING\" /*optional, defaults to STRING*/,\n    description: \"Hello\" /*optional, defaults to \"A command\"*/,\n  },\n  { name: \"value\" },\n];\n```\n\nThe `Bot` object now provides a `Bot#commands.register` method. On its own, it'll register the commands globally (Read about the implications [here](https://discordjs.guide/interactions/registering-slash-commands.html#global-commands)). You can pass an array of strings if you only want to register the commands on certain guild IDs (for development, etc).\n\n```ts\nbot.on(\"debug_register\", async ({ guild }) =\u003e\n  (await bot.commands.register(guild.id)) ? \"Done\" : \"Something went wrong\"\n); //registers all the available slash commands , in the guild this message was sent in\n```\n\nBe sure to call this method _AFTER_ all of your commands and routers have been registered. For troubleshooting, `Bot#compileCommands` will return the objects that will then be passed to the Discord API (via `Bot#commands.overwriteCommands`)\n\nDJS-diy will automatically create subcommands in the case of routers. Be mindful of the [nesting limitations](https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups).\n\n### Slash command timeout prevention\n\nRouters (and the Bot object) support having a loading action be executed for any slash command interactions that may take longer than 2.5s to execute [(Discord's official timeout is 3s)](https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction).\n\nThis action is a sendable message, meaning it can be a string or a function which receives ActionParameters. Do note that for performance reasons, this action can't be `async`\n\n```ts\nbot.onLoading(({ author }) =\u003e `I'm working on it, ${author.username}!`);\nrouter1.onLoading(\"Hold tight!!!\");\n```\n\n### Async Jobs\n\nDJS-diy offers a small addon for running jobs _after_ a response has been issued.\nYou can enqueue these jobs by calling `asyncEffect` from the `ActionParameters` received by an action.\nShould be noted that `msg` in the passed `ActionParameters` object will contain the newly created response.\n\n```ts\nbot.registerAction(\"image\", async ({ createEmbed, asyncEffect }) =\u003e {\n  asyncEffect(async ({ msg }) =\u003e {\n    await msg.edit({\n      content: \"Hello there\",\n    });\n  });\n\n  return \"This message will change\";\n});\n```\n\n### Triggering actions inside actions\n\nActionParameters include a `runAction` callback which can be used to manually invoke an action through the DJS pipeline, thus fully supporting `asyncEffect` and message component subscriptions.\n\nYou need a `ResponseAction` and `ActionParameters` to call this. You may reuse the action's `ActionParameters`, be aware that reusing `asyncEffect` or `subscribe`'s `ActionParameters` will have the side-effect of making it seem like the Bot is the one calling the action (ergo, making components unclickable to users)\n\n```ts\n//test action can include asyncEffect calls and components!\nconst testAction = () =\u003e \"hello!\";\nbot.on(\"coolAction\", (params) =\u003e {\n  const { subscribe, createEmbed } = params;\n  /* `runAction` is also available here! ^*/\n\n  const buttonRow = subscribe(\n    {\n      label: \"Press me\",\n      style: \"PRIMARY\",\n    },\n    ({ runAction }) =\u003e {\n      runAction(testAction, params);\n    }\n  );\n  return createEmbed({\n    desc: \"Press the button to be greeted\",\n    components: [buttonRow],\n  });\n});\n```\n\n### Error handling\n\nDJS-diy offers per-action and global approaches to error handling.\n\nTo handle any exception using the same action:\n\n```ts\nbot.setErrorAction({\n  reaction: \"😭\",\n  response({ args }) {\n    //args will contain the value of `e.message`\n    return `Error ocurred =\u003e ${args}`;\n  },\n});\n```\n\nTo handle an exception for a specific action, pass in an object and include the `onError` `ActionObject`:\n\n```ts\nbot.registerAction(\"hello\", {\n  response() {\n    throw new Error(\"No hellos for you today\");\n  },\n  onError: {\n    reaction: \"😭\",\n  },\n});\n```\n\n### Middleware\n\nDiscordjs-diy provides support for custom middleware.\n\n```ts\ninterface MyCustomMW{\n  myMW: {\n    currentTime: number\n  }\n}\n\nconst bot = new Bot(\"\u003ctoken\u003e\", { prefix: \"!\", embed });\nfunction myMiddleware(params: ActionParameters): ActionParameters\u003cMyCustomMW\u003e{\n  return {\n    ...params,\n    middleware: {\n      ...params.middleware,\n      myMW: {\n        currentTime: Date.now()\n      }\n    }\n  }\n}\nbot.useMiddleware\u003cMyCustomMW\u003e(myMiddleware)\nbot.registerAction(({middleware}) =\u003e //now you can use middleware.myMW in every action execution)\n```\n\n### Session Middleware\n\nDiscordjs-diy provides a solution for sessions.\n\n[Documentation is available here.](Session.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianeli1%2Fdiscordjs-diy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fianeli1%2Fdiscordjs-diy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianeli1%2Fdiscordjs-diy/lists"}