├── .changeset ├── README.md └── config.json ├── .commitlintrc.json ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── COMMIT_CONVENTION.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── LICENSE_HEADER ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build-documentation.yml │ ├── build.yml │ ├── publish-changeset.yml │ └── publish-documentation.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── biome.json ├── docs ├── .gitignore ├── .stackblitzrc ├── babel.config.js ├── config.json ├── docs │ ├── discordx │ │ ├── basics │ │ │ ├── args-of.md │ │ │ ├── client.md │ │ │ ├── debugging.md │ │ │ ├── dependency-injection.md │ │ │ ├── metadatastorage.md │ │ │ ├── rest-args-of.md │ │ │ └── sharding.md │ │ ├── decorators │ │ │ ├── command │ │ │ │ ├── _category_.json │ │ │ │ ├── simple-command-option.md │ │ │ │ ├── simple-command.md │ │ │ │ ├── slash-choice.md │ │ │ │ ├── slash-group.md │ │ │ │ ├── slash-option.md │ │ │ │ └── slash.md │ │ │ ├── general │ │ │ │ ├── _category_.json │ │ │ │ ├── bot.md │ │ │ │ ├── discord.md │ │ │ │ ├── guard.md │ │ │ │ ├── guild.md │ │ │ │ ├── on.md │ │ │ │ ├── once.md │ │ │ │ └── reaction.md │ │ │ ├── gui │ │ │ │ ├── _category_.json │ │ │ │ ├── button-component.md │ │ │ │ ├── context-menu.md │ │ │ │ ├── modal-component.md │ │ │ │ └── select-menu-component.md │ │ │ └── index.md │ │ └── getting-started.mdx │ ├── faq │ │ ├── ESM vs CJS.md │ │ ├── Errors │ │ │ ├── Common.md │ │ │ └── Pagination.md │ │ └── index.md │ └── packages.md ├── docusaurus.config.js ├── package.json ├── sandbox.config.json ├── scripts │ └── prepare-doc.mjs ├── sidebars.js ├── src │ ├── components │ │ ├── HomepageFeatures.jsx │ │ └── HomepageFeatures.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── discord.js │ │ ├── github │ │ ├── index.js │ │ ├── issues.js │ │ ├── pulls.js │ │ └── tree │ │ │ └── main.js │ │ ├── index.jsx │ │ └── index.module.css └── static │ ├── discordx-santa.svg │ ├── discordx.png │ ├── discordx.svg │ ├── favicon.ico │ └── img │ ├── authorize1.png │ ├── authorize2.png │ ├── button-example.jpg │ ├── choices.png │ ├── group1.png │ ├── group2.png │ ├── message-context.jpg │ ├── modal-example.png │ ├── options.png │ ├── permissions.png │ ├── privileged-gateway-intents.png │ ├── select-menu-example.jpg │ └── user-context.jpg ├── package.json ├── packages ├── create-discordx │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── images │ │ └── create-discordx.png │ ├── package.json │ ├── src │ │ ├── helper │ │ │ ├── dir.ts │ │ │ ├── git.ts │ │ │ ├── npm.ts │ │ │ ├── package-manager.ts │ │ │ ├── template.ts │ │ │ └── updater.ts │ │ └── index.ts │ └── tsconfig.json ├── di │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── examples │ │ └── tsyringe │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── logic │ │ │ ├── AbstractConfigurableDependencyInjector.ts │ │ │ ├── IDependencyRegistryEngine.ts │ │ │ ├── impl │ │ │ ├── DefaultDependencyRegistryEngine.ts │ │ │ ├── TsyringeDependencyRegistryEngine.ts │ │ │ ├── TypeDiDependencyRegistryEngine.ts │ │ │ └── index.ts │ │ │ └── index.ts │ └── tsconfig.json ├── discordx │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── examples │ │ ├── attachment │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── builders │ │ │ ├── commands │ │ │ │ ├── autocomplete.ts │ │ │ │ ├── choice.ts │ │ │ │ ├── hello.ts │ │ │ │ └── ping.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── button │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ └── game.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── contextmenu │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── di │ │ │ ├── tsyringe │ │ │ │ ├── commands │ │ │ │ │ ├── TokenInjection.ts │ │ │ │ │ └── common.ts │ │ │ │ ├── main.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ └── typedi │ │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ │ ├── main.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ ├── event │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ ├── priority.ts │ │ │ │ └── rest.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── guards │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ └── interaction guard.ts │ │ │ ├── guards │ │ │ │ ├── Error.ts │ │ │ │ └── NotBot.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── localization │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ ├── group.ts │ │ │ │ └── permission.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── menu │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── modal │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── multiple bots │ │ │ ├── commands │ │ │ │ ├── botA.ts │ │ │ │ ├── botB.ts │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── multiple-discord-instances │ │ │ ├── commands │ │ │ │ ├── commandA.ts │ │ │ │ └── commandB.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── permission │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ └── group.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── reaction │ │ │ ├── commands │ │ │ │ └── common.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ ├── simple-command │ │ │ ├── commands │ │ │ │ ├── common.ts │ │ │ │ ├── hello.ts │ │ │ │ └── math.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ │ └── slash │ │ │ ├── commands │ │ │ ├── choice.ts │ │ │ ├── common.ts │ │ │ ├── group.ts │ │ │ ├── group2.ts │ │ │ ├── minMax.ts │ │ │ └── transformer.ts │ │ │ ├── main.ts │ │ │ └── tsconfig.json │ ├── jest.config.mjs │ ├── package.json │ ├── src │ │ ├── Client.ts │ │ ├── classes │ │ │ ├── Mixin │ │ │ │ └── ApplicationCommandMixin.ts │ │ │ ├── SimpleCommandMessage.ts │ │ │ └── index.ts │ │ ├── decorators │ │ │ ├── classes │ │ │ │ ├── DApplicationCommand.ts │ │ │ │ ├── DApplicationCommandGroup.ts │ │ │ │ ├── DApplicationCommandOption.ts │ │ │ │ ├── DApplicationCommandOptionChoice.ts │ │ │ │ ├── DComponent.ts │ │ │ │ ├── DDiscord.ts │ │ │ │ ├── DGuard.ts │ │ │ │ ├── DOn.ts │ │ │ │ ├── DReaction.ts │ │ │ │ ├── DSimpleCommand.ts │ │ │ │ ├── DSimpleCommandOption.ts │ │ │ │ ├── Method.ts │ │ │ │ └── index.ts │ │ │ ├── decorators │ │ │ │ ├── Bot.ts │ │ │ │ ├── ButtonComponent.ts │ │ │ │ ├── ContextMenu.ts │ │ │ │ ├── Discord.ts │ │ │ │ ├── Guard.ts │ │ │ │ ├── Guild.ts │ │ │ │ ├── ModalComponent.ts │ │ │ │ ├── On.ts │ │ │ │ ├── Once.ts │ │ │ │ ├── Reaction.ts │ │ │ │ ├── SelectMenuComponent.ts │ │ │ │ ├── SimpleCommand.ts │ │ │ │ ├── SimpleCommandOption.ts │ │ │ │ ├── Slash.ts │ │ │ │ ├── SlashChoice.ts │ │ │ │ ├── SlashGroup.ts │ │ │ │ ├── SlashOption.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── logic │ │ │ ├── index.ts │ │ │ ├── managers │ │ │ │ ├── ApplicationCommandManager.ts │ │ │ │ ├── DebugManager.ts │ │ │ │ ├── EventManager.ts │ │ │ │ ├── InteractionHandler.ts │ │ │ │ ├── ReactionManager.ts │ │ │ │ ├── SimpleCommandManager.ts │ │ │ │ └── index.ts │ │ │ └── metadata │ │ │ │ └── MetadataStorage.ts │ │ ├── types │ │ │ ├── core │ │ │ │ ├── ClientOptions.ts │ │ │ │ ├── common.ts │ │ │ │ ├── index.ts │ │ │ │ └── literal.ts │ │ │ ├── index.ts │ │ │ └── public │ │ │ │ ├── common.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── index.ts │ │ │ │ ├── simple command.ts │ │ │ │ └── slash.ts │ │ └── util │ │ │ ├── common.ts │ │ │ ├── comparison.ts │ │ │ ├── index.ts │ │ │ ├── resolve-guilds.ts │ │ │ └── slash-name-validator.ts │ ├── tests │ │ ├── button.test.ts │ │ ├── events.test.ts │ │ ├── simple-command.test.ts │ │ ├── slash-choice.test.ts │ │ ├── slash-group.test.ts │ │ ├── slash.test.ts │ │ ├── tsconfig.json │ │ └── util │ │ │ └── interaction.ts │ └── tsconfig.json ├── importer │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tests │ │ ├── cjs │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── commands │ │ │ └── demo.js │ │ └── esm │ │ │ ├── index.mjs │ │ │ └── package.json │ └── tsconfig.json ├── internal │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── package.json │ ├── src │ │ ├── decorator │ │ │ ├── classes │ │ │ │ ├── Decorator.ts │ │ │ │ └── Modifier.ts │ │ │ ├── index.ts │ │ │ └── util.ts │ │ ├── index.ts │ │ └── types │ │ │ └── decorators.ts │ └── tsconfig.json ├── lava-player │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── package.json │ ├── src │ │ ├── README.md │ │ ├── base │ │ │ ├── base-cluster.ts │ │ │ └── base-node.ts │ │ ├── cluster-node.ts │ │ ├── cluster.ts │ │ ├── core │ │ │ ├── connection.ts │ │ │ ├── guild-player-store.ts │ │ │ ├── guild-player.ts │ │ │ ├── http.ts │ │ │ └── rest.ts │ │ ├── index.ts │ │ ├── node.ts │ │ └── types │ │ │ ├── index.ts │ │ │ ├── node.ts │ │ │ ├── op.ts │ │ │ ├── player.ts │ │ │ ├── rest.ts │ │ │ └── route-planner.ts │ └── tsconfig.json ├── lava-queue │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── queue-manager.ts │ │ ├── queue.ts │ │ └── util.ts │ └── tsconfig.json ├── music │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── node.ts │ │ ├── queue-manager.ts │ │ ├── queue.ts │ │ ├── types │ │ │ ├── audio-node.ts │ │ │ ├── communication-parent.ts │ │ │ ├── communication-worker.ts │ │ │ ├── index.ts │ │ │ └── queue-node-event.ts │ │ └── worker │ │ │ ├── audio-node-manager.ts │ │ │ ├── audio-node.ts │ │ │ ├── index.ts │ │ │ └── ytdl.ts │ └── tsconfig.json ├── pagination │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── examples │ │ └── pagination │ │ │ ├── .gitignore │ │ │ ├── commands │ │ │ ├── common.ts │ │ │ ├── configurations.ts │ │ │ ├── slash command info.ts │ │ │ └── slash-example.ts │ │ │ ├── main.ts │ │ │ ├── package.json │ │ │ ├── tsconfig.json │ │ │ └── util │ │ │ └── common.ts │ ├── images │ │ └── discord-embed-pagination.jpg │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── pagination │ │ │ ├── builder.ts │ │ │ ├── index.ts │ │ │ ├── pagination.ts │ │ │ ├── resolver.ts │ │ │ └── types.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ └── paginate.ts │ └── tsconfig.json ├── plugin-lava-player │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── examples │ │ ├── main.ts │ │ └── tsconfig.json │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── current.ts │ │ │ ├── gui.ts │ │ │ ├── index.ts │ │ │ ├── music.ts │ │ │ ├── pause-resume.ts │ │ │ ├── play.ts │ │ │ ├── queue.ts │ │ │ ├── seek.ts │ │ │ ├── set-volume.ts │ │ │ ├── shuffle.ts │ │ │ ├── skip.ts │ │ │ └── stop.ts │ │ ├── core │ │ │ ├── index.ts │ │ │ ├── manager.ts │ │ │ ├── node.ts │ │ │ └── queue.ts │ │ ├── events │ │ │ └── ready.ts │ │ ├── index.ts │ │ └── plugins │ │ │ └── lavalyrics │ │ │ ├── index.ts │ │ │ └── types.ts │ └── tsconfig.json ├── plugin-ytdl-player │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── examples │ │ ├── main.ts │ │ └── tsconfig.json │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── current.ts │ │ │ ├── gui.ts │ │ │ ├── index.ts │ │ │ ├── music.ts │ │ │ ├── pause-resume.ts │ │ │ ├── play.ts │ │ │ ├── playlist.ts │ │ │ ├── queue.ts │ │ │ ├── seek.ts │ │ │ ├── set-volume.ts │ │ │ ├── shuffle.ts │ │ │ ├── skip.ts │ │ │ ├── spotify.ts │ │ │ └── stop.ts │ │ ├── core │ │ │ ├── index.ts │ │ │ ├── manager.ts │ │ │ ├── queue.ts │ │ │ └── types.ts │ │ ├── events │ │ │ └── ready.ts │ │ ├── global.d.ts │ │ ├── index.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ ├── message.ts │ │ │ ├── queue.ts │ │ │ └── time.ts │ └── tsconfig.json └── utilities │ ├── CHANGELOG.md │ ├── LICENSE.txt │ ├── README.md │ ├── SECURITY.md │ ├── examples │ ├── category │ │ ├── commands │ │ │ ├── group.ts │ │ │ └── slash.ts │ │ ├── main.ts │ │ └── tsconfig.json │ └── guards │ │ ├── commands │ │ ├── IsGuildUser.ts │ │ ├── NotBot.ts │ │ ├── PermissionGuard.ts │ │ └── RateLimit.ts │ │ ├── main.ts │ │ └── tsconfig.json │ ├── package.json │ ├── src │ ├── decorators │ │ ├── category.ts │ │ ├── description.ts │ │ └── index.ts │ ├── guards │ │ ├── IsGuildUser │ │ │ └── index.ts │ │ ├── NotBot │ │ │ └── index.ts │ │ ├── PermissionGuard │ │ │ └── index.ts │ │ ├── Rate Limiter │ │ │ ├── RateLimit.ts │ │ │ ├── index.ts │ │ │ ├── logic │ │ │ │ ├── TimeOutEntry.ts │ │ │ │ ├── TimedSet.ts │ │ │ │ ├── Timer.ts │ │ │ │ └── index.ts │ │ │ └── types │ │ │ │ ├── ITimedSet.ts │ │ │ │ ├── common.ts │ │ │ │ ├── enum.ts │ │ │ │ └── index.ts │ │ └── index.ts │ ├── index.ts │ └── useful │ │ ├── enum.ts │ │ ├── index.ts │ │ └── time-format.ts │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── tsconfig.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "discordx-ts/discordx" } 6 | ], 7 | "commit": false, 8 | "fixed": [], 9 | "linked": [], 10 | "access": "restricted", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "ignore": [] 14 | } 15 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-angular"], 3 | "rules": { 4 | "scope-enum": [ 5 | 2, 6 | "always", 7 | [ 8 | "create-discordx", 9 | "di", 10 | "discordx", 11 | "docs", 12 | "importer", 13 | "internal", 14 | "lava-player", 15 | "lava-queue", 16 | "music", 17 | "pagination", 18 | "plugin-lava-player", 19 | "plugin-ytdl-player", 20 | "utilities" 21 | ] 22 | ], 23 | "type-enum": [ 24 | 2, 25 | "always", 26 | [ 27 | "build", 28 | "chore", 29 | "ci", 30 | "docs", 31 | "feat", 32 | "fix", 33 | "refactor", 34 | "revert", 35 | "test", 36 | "types", 37 | "workflow" 38 | ] 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Default owner for everything 2 | * @vijayymmeena 3 | 4 | 5 | # for anything DI related 6 | /packages/di/ @VictoriqueMoe @vijayymmeena 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [vijayymmeena] 2 | custom: ["paypal.me/vijayymmeena"] 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Discord server 4 | url: https://discordx.js.org/discord 5 | about: For questions and support requests, please visit our Discord server. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Request a new feature 3 | title: "[Feature]: " 4 | labels: [enhancement] 5 | assignees: 6 | - vijayymmeena 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thanks for taking the time to fill out this feature request! 12 | 13 | - type: textarea 14 | id: feature 15 | attributes: 16 | label: Feature? 17 | description: Please describe the feature you are requesting in detail 18 | placeholder: describe.... 19 | validations: 20 | required: true 21 | 22 | - type: dropdown 23 | id: package 24 | attributes: 25 | label: Package 26 | description: Please select the package that the requested feature pertains to. 27 | options: 28 | - "discordx" 29 | - "@discordx/changelog" 30 | - "@discordx/di" 31 | - "@discordx/importer" 32 | - "@discordx/internal" 33 | - "@discordx/koa" 34 | - "@discordx/lava-player" 35 | - "@discordx/music" 36 | - "@discordx/pagination" 37 | - "@discordx/utilities" 38 | validations: 39 | required: true 40 | -------------------------------------------------------------------------------- /.github/LICENSE_HEADER: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Please describe the changes this PR makes:** 2 | -------------------------------------------------------------------------------- /.github/workflows/build-documentation.yml: -------------------------------------------------------------------------------- 1 | name: Build - Documentation 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | paths: 6 | - "docs/**" 7 | branches: 8 | - main 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@main 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Install pnpm 19 | uses: pnpm/action-setup@master 20 | 21 | - name: Install Node 22 | uses: actions/setup-node@main 23 | with: 24 | node-version: 22 25 | cache: "pnpm" 26 | 27 | - name: Install dependencies for docs 28 | run: pnpm install 29 | working-directory: ./docs 30 | 31 | - name: Build docs 32 | run: pnpm run build 33 | working-directory: ./docs 34 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | paths-ignore: 9 | - "docs/docs/**" 10 | branches: 11 | - main 12 | 13 | jobs: 14 | build: 15 | name: Build Monorepo 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: check out code 🛎 19 | uses: actions/checkout@main 20 | 21 | - name: Install pnpm 22 | uses: pnpm/action-setup@master 23 | 24 | - name: Install Node 25 | uses: actions/setup-node@main 26 | with: 27 | node-version: 22 28 | cache: "pnpm" 29 | 30 | - name: Install dependencies 31 | run: pnpm install 32 | 33 | - name: Build 34 | run: pnpm run build 35 | 36 | - name: Run Tests 37 | run: pnpm run test 38 | 39 | - name: Run Lint 40 | run: pnpm run lint 41 | -------------------------------------------------------------------------------- /.github/workflows/publish-changeset.yml: -------------------------------------------------------------------------------- 1 | name: Publish - Changeset 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | name: Publish 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | id-token: write 15 | steps: 16 | - name: check out code 🛎 17 | uses: actions/checkout@main 18 | 19 | - name: Install pnpm 20 | uses: pnpm/action-setup@master 21 | 22 | - name: Install Node 23 | uses: actions/setup-node@main 24 | with: 25 | node-version: 22 26 | cache: "pnpm" 27 | 28 | - name: Install dependencies 29 | run: pnpm install 30 | 31 | - name: Build 32 | run: pnpm run build 33 | 34 | - name: Create Release Pull Request 35 | uses: changesets/action@v1 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | NPM_CONFIG_PROVENANCE: true 40 | with: 41 | commit: "chore: release packages" 42 | publish: pnpm publish -r 43 | title: "chore: release packages" 44 | -------------------------------------------------------------------------------- /.github/workflows/publish-documentation.yml: -------------------------------------------------------------------------------- 1 | name: Publish - Documentation 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "docs/**" 9 | 10 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 11 | permissions: 12 | contents: read 13 | pages: write 14 | id-token: write 15 | 16 | # Allow one concurrent deployment 17 | concurrency: 18 | group: "pages" 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | build: 23 | name: Build 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: check out code 🛎 27 | uses: actions/checkout@main 28 | 29 | - name: Install pnpm 30 | uses: pnpm/action-setup@master 31 | 32 | - name: Install Node 33 | uses: actions/setup-node@main 34 | with: 35 | node-version: 22 36 | cache: "pnpm" 37 | 38 | - name: Install dependencies 39 | run: pnpm install 40 | 41 | - name: Build TypeDoc 42 | run: pnpm run build:typedoc 43 | 44 | - name: Build docs 45 | run: pnpm run build 46 | working-directory: ./docs 47 | 48 | - name: Add CNAME 49 | run: echo discordx.js.org > CNAME 50 | working-directory: ./docs/build 51 | 52 | - name: Upload artifact 53 | uses: actions/upload-pages-artifact@main 54 | with: 55 | path: ./docs/build 56 | 57 | deploy: 58 | environment: 59 | name: github-pages 60 | url: ${{ steps.deployment.outputs.page_url }} 61 | runs-on: ubuntu-latest 62 | needs: build 63 | steps: 64 | - name: Deploy to GitHub Pages 65 | id: deployment 66 | uses: actions/deploy-pages@main 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * text=auto eol=crlf 2 | 3 | node_modules 4 | dist 5 | .turbo 6 | .DS_Store 7 | .docusaurus 8 | .cache-loader 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | .vscode/settings.json 15 | .idea/** 16 | 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | *.bat 21 | 22 | docs/docs/**/README.md 23 | docs/static/api 24 | docs/typedoc-sidebar.js 25 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | npx --no -- commitlint --edit $1 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm lint 2 | pnpm build 3 | pnpm test -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/2.3.0/schema.json", 3 | "vcs": { 4 | "enabled": true, 5 | "clientKind": "git", 6 | "useIgnoreFile": true 7 | }, 8 | "files": { 9 | "ignoreUnknown": false 10 | }, 11 | "formatter": { 12 | "enabled": true, 13 | "indentStyle": "space" 14 | }, 15 | "linter": { 16 | "enabled": true, 17 | "rules": { 18 | "recommended": true, 19 | "suspicious": { 20 | "noExplicitAny": "off" 21 | } 22 | } 23 | }, 24 | "javascript": { 25 | "formatter": { 26 | "quoteStyle": "double" 27 | }, 28 | "parser": { 29 | "unsafeParameterDecoratorsEnabled": true 30 | } 31 | }, 32 | "assist": { 33 | "enabled": true, 34 | "actions": { 35 | "source": { 36 | "organizeImports": "on" 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_name": "discordx", 3 | "start_urls": ["https://discordx.js.org/"], 4 | "sitemap_urls": ["https://discordx.js.org/sitemap.xml"], 5 | "sitemap_alternate_links": true, 6 | "stop_urls": ["https://discordx.js.org/docs/packages/"], 7 | "selectors": { 8 | "lvl0": { 9 | "selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]", 10 | "type": "xpath", 11 | "global": true, 12 | "default_value": "Documentation" 13 | }, 14 | "lvl1": "article h1", 15 | "lvl2": "article h2", 16 | "lvl3": "article h3", 17 | "lvl4": "article h4", 18 | "lvl5": "article h5, article td:first-child", 19 | "lvl6": "article h6", 20 | "text": "article p, article li, article td:last-child" 21 | }, 22 | "strip_chars": " .,;:#", 23 | "custom_settings": { 24 | "separatorsToIndex": "_", 25 | "attributesForFaceting": ["language", "version", "type", "docusaurus_tag"], 26 | "attributesToRetrieve": [ 27 | "hierarchy", 28 | "content", 29 | "anchor", 30 | "url", 31 | "url_without_anchor", 32 | "type" 33 | ] 34 | }, 35 | "conversation_id": ["833762294"], 36 | "nb_hits": 46250 37 | } 38 | -------------------------------------------------------------------------------- /docs/docs/discordx/basics/args-of.md: -------------------------------------------------------------------------------- 1 | # ArgsOf 2 | 3 | `ArgsOf` type your events payload as an array, just pass an event (as string) in the type parameter and it types your array with the related event's parameters 4 | 5 | You can get the list of the events and the payload type in the [**List of events**](https://discord.js.org/#/docs/discord.js/main/class/Client?scrollTo=e-applicationCommandPermissionsUpdate) from discord.js 6 | 7 | ```ts 8 | @Discord() 9 | class Example { 10 | @On({ event: Events.MessageCreate }) 11 | onMessage( 12 | // The type of message is Message 13 | [message]: ArgsOf, 14 | ) { 15 | // ... 16 | } 17 | 18 | @On({ event: Events.ChannelUpdate }) 19 | onMessage( 20 | // The type of channel1 and channel2 is TextChannel 21 | [channel1, channel2]: ArgsOf, 22 | ) { 23 | // ... 24 | } 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/docs/discordx/basics/debugging.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Debugging 3 | --- 4 | 5 | Use the VSCode debugger to debug your bot 6 | 7 | 1. Create the `.vscode/launch.json` file at your project root directory if the file do not already exists 8 | 2. Install tsx as a dev dependency 9 | 10 | ```bash npm2yarn 11 | npm install --save-dev tsx 12 | ``` 13 | 14 | 3. Copy paste this into your `launch.json` file 15 | 16 | ```json title=".vscode/launch.json" 17 | { 18 | // Use IntelliSense to learn about possible attributes. 19 | // Hover to view descriptions of existing attributes. 20 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 21 | "version": "0.2.0", 22 | "configurations": [ 23 | { 24 | "type": "node", 25 | "request": "launch", 26 | "name": "Debug bot", 27 | "protocol": "inspector", 28 | "args": ["${workspaceRoot}/PATH_TO_YOUR_MAIN.ts"], 29 | "cwd": "${workspaceRoot}", 30 | "runtimeArgs": ["--import", "tsx"], 31 | "internalConsoleOptions": "neverOpen" 32 | } 33 | ] 34 | } 35 | ``` 36 | 37 | 4. You can now put some breakpoints, go to the debug tab in VSCode and launch your bot 38 | -------------------------------------------------------------------------------- /docs/docs/discordx/basics/metadatastorage.md: -------------------------------------------------------------------------------- 1 | # MetadataStorage 2 | 3 | MetadataStorage stores all the information about your decorators. You can get the information you need by using `MetadataStorage.instance`. 4 | 5 | ```ts 6 | import { MetadataStorage } from "discordx"; 7 | 8 | MetadataStorage.instance.applicationCommandSlashes; 9 | MetadataStorage.instance.applicationCommandUsers; 10 | MetadataStorage.instance.applicationCommandMessages; 11 | MetadataStorage.instance.reactions; 12 | MetadataStorage.instance.simpleCommands; 13 | MetadataStorage.instance.events; 14 | MetadataStorage.instance.buttonComponents; 15 | MetadataStorage.instance.modalComponents; 16 | MetadataStorage.instance.selectMenuComponents; 17 | // ... 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/docs/discordx/basics/rest-args-of.md: -------------------------------------------------------------------------------- 1 | # RestArgsOf 2 | 3 | `RestArgsOf` type your rest events payload as an array, just pass an event (as string) in the type parameter and it types your array with the related event's parameters 4 | 5 | ```ts 6 | @Discord() 7 | class Example { 8 | @On.rest({ event: "rateLimited" }) 9 | onMessage([data]: RestArgsOf<"rateLimited">) { 10 | // ... 11 | } 12 | } 13 | ``` 14 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/command/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Command" 3 | } 4 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/general/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "General" 3 | } 4 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/general/discord.md: -------------------------------------------------------------------------------- 1 | # @Discord 2 | 3 | This decorator instanciates the class inside the discord.**ts** library to access the class members or to call the methods 4 | 5 | :::danger 6 | You must decorate all classes that use discordx decorators with the @Discord decorator. 7 | ::: 8 | 9 | ```typescript 10 | import { Discord, Slash } from "discordx"; 11 | 12 | @Discord() 13 | abstract class Example { 14 | // We can use member decorators 15 | // because we decorated the class with @Discord 16 | @Slash({ description: "hello" }) 17 | hello() { 18 | // ... 19 | } 20 | } 21 | ``` 22 | 23 | > `abstract` keyword is not necessary but this is more type-safe, the class shouldn't be initialized 24 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/general/once.md: -------------------------------------------------------------------------------- 1 | # @Once 2 | 3 | It's exactly the same behavior as [@On](./on) but the method is only executed once 4 | 5 | ```typescript 6 | @Discord() 7 | class Example { 8 | @Once({ event: Events.MessageDelete }) 9 | onMessageDelete() { 10 | // ... 11 | } 12 | } 13 | ``` 14 | 15 | ## Signature 16 | 17 | ```ts 18 | Once(options?: EventOptions) 19 | ``` 20 | 21 | ## Get the event payload 22 | 23 | For each event a list of arguments is injected in your decorated method, you can type this list thanks to the `ArgsOf<"YOUR_EVENT">` type provided by discord.**ts**. 24 | 25 | You also receive other useful arguments after that: 26 | 27 | 1. The event payload (`ArgsOf<"YOUR_EVENT">`) 28 | 2. The `Client` instance 29 | 3. The [guards](./guard) payload 30 | 31 | > You should use JS destructuring for `ArgsOf<"YOUR_EVENT">` like in this example 32 | 33 | ```typescript 34 | @Discord() 35 | class Example { 36 | @Once({ event: Events.MessageCreate }) 37 | onMessage( 38 | [message]: ArgsOf, // Type message automatically 39 | client: Client, // Client instance injected here, 40 | guardPayload: any, 41 | ) { 42 | // ... 43 | } 44 | } 45 | ``` 46 | 47 | ## Rest 48 | 49 | To handle rest events 50 | 51 | ```ts 52 | @Discord() 53 | class Example { 54 | @Once.rest() 55 | rateLimited([data]: RestArgsOf<"rateLimited">): void { 56 | console.log(data.limit); 57 | } 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/gui/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "GUI" 3 | } 4 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/gui/button-component.md: -------------------------------------------------------------------------------- 1 | # @ButtonComponent 2 | 3 | add button interaction handler for your bot using `@ButtonComponent` decorator 4 | 5 | Here are some example screenshots: 6 | 7 | ![](../../../../static/img/button-example.jpg) 8 | 9 | ## Signature 10 | 11 | ```ts 12 | ButtonComponent(options: ComponentOptions) 13 | ``` 14 | 15 | :::caution 16 | As per discord latest announcement, `custom_ids` being unique within a message. [read here more](https://discord.com/developers/docs/interactions/message-components#custom-id) 17 | ::: 18 | 19 | ## Example 20 | 21 | ```ts 22 | @Discord() 23 | class Example { 24 | @ButtonComponent({ id: "hello" }) 25 | handler(interaction: ButtonInteraction): void { 26 | interaction.reply(":wave:"); 27 | } 28 | 29 | @Slash({ description: "test" }) 30 | test(interaction: CommandInteraction): void { 31 | const btn = new ButtonBuilder() 32 | .setLabel("Hello") 33 | .setStyle(ButtonStyle.Primary) 34 | .setCustomId("hello"); 35 | 36 | const buttonRow = 37 | new ActionRowBuilder().addComponents( 38 | btn, 39 | ); 40 | 41 | interaction.reply({ 42 | components: [buttonRow], 43 | }); 44 | } 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/gui/context-menu.md: -------------------------------------------------------------------------------- 1 | # @ContextMenu 2 | 3 | create discord context menu options with ease! 4 | 5 | Here are some example screenshots: 6 | 7 | ![](../../../../static/img/user-context.jpg) 8 | ![](../../../../static/img/message-context.jpg) 9 | 10 | ## Signature 11 | 12 | ```ts 13 | ContextMenu( 14 | options: Omit< 15 | ApplicationCommandOptions & { 16 | type: Exclude; 17 | }, 18 | "description" | "descriptionLocalizations" 19 | > 20 | ) 21 | ``` 22 | 23 | ## Example 24 | 25 | ```ts 26 | @Discord() 27 | class Example { 28 | @ContextMenu({ 29 | name: "Hello from discordx", 30 | type: ApplicationCommandType.Message, 31 | }) 32 | messageHandler(interaction: MessageContextMenuCommandInteraction): void { 33 | console.log("I am message"); 34 | interaction.reply("message interaction works"); 35 | } 36 | 37 | @ContextMenu({ 38 | name: "Hello from discordx", 39 | type: ApplicationCommandType.User, 40 | }) 41 | userHandler(interaction: UserContextMenuCommandInteraction): void { 42 | console.log(`Selected user: ${interaction.targetId}`); 43 | interaction.reply("user interaction works"); 44 | } 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/docs/discordx/decorators/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Decorators 3 | --- 4 | 5 | it simplifies your code and improves the readability! 6 | 7 | ## Command 8 | 9 | - [@Slash](command/slash) 10 | - [@SlashChoice](command/slash-choice) 11 | - [@SlashGroup](command/slash-group) 12 | - [@SlashOption](command/slash-option) 13 | - [@SimpleCommand](command/simple-command) 14 | - [@SimpleCommandOption](command/simple-command-option) 15 | 16 | ## General 17 | 18 | - [@Bot](general/bot) 19 | - [@Discord](general/discord) 20 | - [@Guard](general/guard) 21 | - [@Guild](general/guild) 22 | - [@On](general/on) 23 | - [@Once](general/once) 24 | - [@Reaction](general/reaction) 25 | 26 | ## GUI 27 | 28 | - [@ButtonComponent](gui/button-component) 29 | - [@ContextMenu](gui/context-menu) 30 | - [@ModalComponent](gui/modal-component) 31 | - [@SelectMenuComponent](gui/select-menu-component) 32 | -------------------------------------------------------------------------------- /docs/docs/faq/Errors/Pagination.md: -------------------------------------------------------------------------------- 1 | # Pagination 2 | 3 | Errors around `@discord/pagination` package 4 | 5 | ## Missing Intent: GUILD_MESSAGES 6 | 7 | Without guild message intent, pagination does not work, Consider adding GUILD_MESSAGES as an intent. 8 | -------------------------------------------------------------------------------- /docs/docs/faq/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 0 3 | --- 4 | 5 | # F.A.Q 6 | 7 | In this section, you'll find pretty common questions, answers, and solutions 8 | 9 | ## Content 10 | 11 | - [Errors](/docs/faq/Errors/Common) 12 | - [ESM vs CJS](/docs/faq/esm-vs-cjs) 13 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docusaurus", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "prepare": "node scripts/prepare-doc.mjs", 7 | "docusaurus": "docusaurus", 8 | "start": "docusaurus start", 9 | "build": "docusaurus build", 10 | "swizzle": "docusaurus swizzle", 11 | "deploy": "docusaurus deploy", 12 | "clear": "docusaurus clear", 13 | "serve": "docusaurus serve", 14 | "write-translations": "docusaurus write-translations", 15 | "write-heading-ids": "docusaurus write-heading-ids", 16 | "dev": "docusaurus start" 17 | }, 18 | "dependencies": { 19 | "@docusaurus/core": "^3.9.2", 20 | "@docusaurus/preset-classic": "^3.9.2", 21 | "@docusaurus/remark-plugin-npm2yarn": "^3.9.2", 22 | "@docusaurus/theme-search-algolia": "^3.9.2", 23 | "@mdx-js/react": "^3.1.1", 24 | "@svgr/webpack": "^8.1.0", 25 | "@types/react": "19.2.2", 26 | "ansi-regex": "^6.2.2", 27 | "clsx": "^2.1.1", 28 | "file-loader": "^6.2.0", 29 | "nth-check": "^2.1.1", 30 | "prism-react-renderer": "^2.4.1", 31 | "react": "^19.2.0", 32 | "react-dom": "19.2.0", 33 | "typescript": "^5.9.3", 34 | "url-loader": "^4.1.1" 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.5%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | }, 48 | "description": "discordx documentation" 49 | } 50 | -------------------------------------------------------------------------------- /docs/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "infiniteLoopProtection": true, 3 | "hardReloadOnChange": true, 4 | "view": "browser", 5 | "template": "docusaurus", 6 | "node": "14", 7 | "container": { 8 | "node": "14" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/scripts/prepare-doc.mjs: -------------------------------------------------------------------------------- 1 | import fs from "node:fs"; 2 | 3 | const packages = [ 4 | "create-discordx", 5 | "di", 6 | "discordx", 7 | "importer", 8 | "internal", 9 | "lava-player", 10 | "lava-queue", 11 | "music", 12 | "pagination", 13 | "plugin-lava-player", 14 | "plugin-ytdl-player", 15 | "utilities", 16 | ]; 17 | 18 | for (const pkg in packages) { 19 | const dirPath = `docs/${packages[pkg]}`; 20 | if (!fs.existsSync(dirPath)) { 21 | fs.mkdirSync(dirPath); 22 | } 23 | 24 | const filePath = `${dirPath}/README.md`; 25 | const content = fs.readFileSync(`../packages/${packages[pkg]}/README.md`); 26 | fs.writeFileSync( 27 | filePath, 28 | `---\ntitle: Readme\nsidebar_position: 0\n---\n\n#  \n\n${content}` 29 | ); 30 | } 31 | 32 | console.log("doc prepared"); 33 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures.jsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | import styles from "./HomepageFeatures.module.css"; 4 | 5 | const FeatureList = [ 6 | { 7 | description: <>it simplifies your code and improves the readability!, 8 | title: "Decorators", 9 | }, 10 | { 11 | description: <>Implement a Discord's Slash commands system simply !, 12 | title: "Slash commands", 13 | }, 14 | { 15 | description: ( 16 | <>You can use discord.js along discordx without any problems ! 17 | ), 18 | title: "discord.js support", 19 | }, 20 | ]; 21 | 22 | function Feature({ title, description }) { 23 | return ( 24 |
25 |
26 |

{title}

27 |

{description}

28 |
29 |
30 | ); 31 | } 32 | 33 | export default function HomepageFeatures() { 34 | return ( 35 |
36 |
37 |
38 | {FeatureList.map((props) => ( 39 | 40 | ))} 41 |
42 |
43 |
44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | .features { 4 | display: flex; 5 | align-items: center; 6 | padding: 2rem 0; 7 | width: 100%; 8 | } 9 | 10 | .featureSvg { 11 | height: 200px; 12 | width: 200px; 13 | } 14 | -------------------------------------------------------------------------------- /docs/src/pages/discord.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function Discord() { 4 | React.useEffect(() => { 5 | window.location.href = "https://discord.gg/yHQY9fexH9"; 6 | }, []); 7 | return null; 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/pages/github/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function Discord() { 4 | React.useEffect(() => { 5 | window.location.href = "https://github.com/discordx-ts/discordx"; 6 | }, []); 7 | return null; 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/pages/github/issues.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function Discord() { 4 | React.useEffect(() => { 5 | window.location.href = "https://github.com/discordx-ts/discordx/issues"; 6 | }, []); 7 | return null; 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/pages/github/pulls.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function Discord() { 4 | React.useEffect(() => { 5 | window.location.href = "https://github.com/discordx-ts/discordx/pulls"; 6 | }, []); 7 | return null; 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/pages/github/tree/main.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function Redirect() { 4 | React.useEffect(() => { 5 | window.location.href = "https://github.com/discordx-ts/discordx/tree/main"; 6 | }, []); 7 | return null; 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/pages/index.jsx: -------------------------------------------------------------------------------- 1 | import Link from "@docusaurus/Link"; 2 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 3 | import Layout from "@theme/Layout"; 4 | import clsx from "clsx"; 5 | 6 | import HomepageFeatures from "../components/HomepageFeatures"; 7 | import styles from "./index.module.css"; 8 | 9 | function HomepageHeader() { 10 | const { siteConfig } = useDocusaurusContext(); 11 | return ( 12 |
13 |
14 | logo 15 |

Documentation

16 |

{siteConfig.tagline}

17 |
18 | 22 | Quick Start → 23 | 24 |
25 |
26 |
27 | ); 28 | } 29 | 30 | export default function Home() { 31 | return ( 32 | 33 |
34 | 35 | 36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | } 14 | 15 | .heroImg { 16 | max-width: 564px; 17 | width: 100%; 18 | padding: 2rem 0; 19 | } 20 | 21 | @media screen and (max-width: 966px) { 22 | .heroBanner { 23 | padding: 2rem; 24 | } 25 | } 26 | 27 | .buttons { 28 | display: flex; 29 | align-items: center; 30 | justify-content: center; 31 | } 32 | -------------------------------------------------------------------------------- /docs/static/discordx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/discordx.png -------------------------------------------------------------------------------- /docs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/authorize1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/authorize1.png -------------------------------------------------------------------------------- /docs/static/img/authorize2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/authorize2.png -------------------------------------------------------------------------------- /docs/static/img/button-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/button-example.jpg -------------------------------------------------------------------------------- /docs/static/img/choices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/choices.png -------------------------------------------------------------------------------- /docs/static/img/group1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/group1.png -------------------------------------------------------------------------------- /docs/static/img/group2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/group2.png -------------------------------------------------------------------------------- /docs/static/img/message-context.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/message-context.jpg -------------------------------------------------------------------------------- /docs/static/img/modal-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/modal-example.png -------------------------------------------------------------------------------- /docs/static/img/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/options.png -------------------------------------------------------------------------------- /docs/static/img/permissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/permissions.png -------------------------------------------------------------------------------- /docs/static/img/privileged-gateway-intents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/privileged-gateway-intents.png -------------------------------------------------------------------------------- /docs/static/img/select-menu-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/select-menu-example.jpg -------------------------------------------------------------------------------- /docs/static/img/user-context.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/docs/static/img/user-context.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Create a discord bot with TypeScript and Decorators!", 6 | "keywords": [ 7 | "api", 8 | "bot", 9 | "client", 10 | "decorators", 11 | "discord", 12 | "framework", 13 | "library", 14 | "tool", 15 | "typescript" 16 | ], 17 | "homepage": "https://discordx.js.org", 18 | "bugs": { 19 | "url": "https://github.com/discordx-ts/discordx/issues", 20 | "email": "vijayymmeena@gmail.com" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/discordx-ts/discordx" 25 | }, 26 | "license": "Apache-2.0", 27 | "contributors": [ 28 | "Vijay Meena (https://github.com/vijayymmeena)" 29 | ], 30 | "scripts": { 31 | "build": "turbo run build", 32 | "build:typedoc": "turbo run build:typedoc", 33 | "format": "biome format --write", 34 | "lint": "biome lint", 35 | "prepare": "husky", 36 | "prettier": "prettier --check .", 37 | "test": "turbo run test" 38 | }, 39 | "devDependencies": { 40 | "@biomejs/biome": "2.3.0", 41 | "@changesets/changelog-github": "^0.5.1", 42 | "@changesets/cli": "^2.29.7", 43 | "@commitlint/cli": "^20.1.0", 44 | "@commitlint/config-angular": "^20.0.0", 45 | "husky": "^9.1.7", 46 | "tsup": "^8.5.0", 47 | "tsx": "^4.20.6", 48 | "turbo": "^2.5.8", 49 | "typedoc": "^0.28.14", 50 | "typescript": "^5.9.3" 51 | }, 52 | "packageManager": "pnpm@10.19.0", 53 | "publishConfig": { 54 | "access": "restricted" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/create-discordx/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # create-discordx 2 | 3 | ## 1.3.2 4 | 5 | ### Patch Changes 6 | 7 | - Dep update 8 | 9 | ## 1.3.1 10 | 11 | ### Patch Changes 12 | 13 | - dep update and eslint 14 | 15 | ## 1.3.0 16 | 17 | ### Minor Changes 18 | 19 | - added bun as a package manager 20 | 21 | ## 1.2.4 22 | 23 | ### Patch Changes 24 | 25 | - build config 26 | 27 | ## 1.2.3 28 | 29 | ### Patch Changes 30 | 31 | - fixed tar import 32 | 33 | ## 1.2.2 34 | 35 | ### Patch Changes 36 | 37 | - lint 38 | 39 | ## 1.2.1 40 | 41 | ### Patch Changes 42 | 43 | - c697f01b: fix: rimraf export (#962) 44 | 45 | ## 1.2.0 46 | 47 | ### Minor Changes 48 | 49 | - fix: monorepo 50 | -------------------------------------------------------------------------------- /packages/create-discordx/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/create-discordx/images/create-discordx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/packages/create-discordx/images/create-discordx.png -------------------------------------------------------------------------------- /packages/create-discordx/src/helper/npm.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import validateProjectName from "validate-npm-package-name"; 8 | 9 | /** 10 | * Validate project name 11 | * 12 | * @param name project name 13 | * @returns 14 | */ 15 | export function ValidateNpmName(name: string): { 16 | problems?: string[]; 17 | valid: boolean; 18 | } { 19 | const nameValidation = validateProjectName(name); 20 | if (nameValidation.validForNewPackages) { 21 | return { valid: true }; 22 | } 23 | 24 | return { 25 | problems: [ 26 | ...(nameValidation.errors ?? []), 27 | ...(nameValidation.warnings ?? []), 28 | ], 29 | valid: false, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /packages/create-discordx/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "src", 4 | "outDir": "dist", 5 | "module": "ESNext", 6 | "target": "ESNext", 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "noUncheckedIndexedAccess": true, 11 | "resolveJsonModule": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "moduleResolution": "Bundler", 14 | "esModuleInterop": true, 15 | "skipLibCheck": true 16 | }, 17 | "exclude": ["examples", "dist"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/di/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/di 2 | 3 | ## 3.3.4 4 | 5 | ### Patch Changes 6 | 7 | - fix default di add service instance 8 | 9 | ## 3.3.3 10 | 11 | ### Patch Changes 12 | 13 | - dep update and eslint 14 | 15 | ## 3.3.2 16 | 17 | ### Patch Changes 18 | 19 | - build config 20 | 21 | ## 3.3.1 22 | 23 | ### Patch Changes 24 | 25 | - lint 26 | 27 | ## 3.3.0 28 | 29 | ### Minor Changes 30 | 31 | - refactor: added clearAllServices method for engine and updated DIService to act as bridge for engine only 32 | 33 | ## 3.2.0 34 | 35 | ### Minor Changes 36 | 37 | - fix: monorepo 38 | -------------------------------------------------------------------------------- /packages/di/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/di/examples/tsyringe/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import "reflect-metadata"; 8 | 9 | import { DIService, tsyringeDependencyRegistryEngine } from "@discordx/di"; 10 | import { container, injectable, singleton } from "tsyringe"; 11 | 12 | @singleton() 13 | class Database { 14 | database: string; 15 | 16 | constructor() { 17 | console.log("I am database"); 18 | this.database = new Date().toString(); 19 | } 20 | 21 | query() { 22 | return this.database; 23 | } 24 | } 25 | 26 | @injectable() 27 | export class Example { 28 | constructor(database: Database) { 29 | console.log(database.query()); 30 | } 31 | } 32 | 33 | DIService.engine = tsyringeDependencyRegistryEngine.setInjector(container); 34 | DIService.engine.addService(Example); 35 | DIService.engine.getService(Example); 36 | -------------------------------------------------------------------------------- /packages/di/examples/tsyringe/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "outDir": "dist", 8 | "emitDecoratorMetadata": false, 9 | "experimentalDecorators": true, 10 | "strictNullChecks": true, 11 | "noUncheckedIndexedAccess": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "moduleResolution": "Bundler", 14 | "esModuleInterop": true 15 | }, 16 | "exclude": ["node_modules", "tests", "examples"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/di/src/logic/AbstractConfigurableDependencyInjector.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { InstanceOf } from "../index.js"; 8 | import type { IDependencyRegistryEngine } from "./IDependencyRegistryEngine.js"; 9 | 10 | export abstract class AbstractConfigurableDependencyInjector 11 | implements IDependencyRegistryEngine 12 | { 13 | protected injector: I | undefined; 14 | 15 | protected useToken = false; 16 | 17 | protected _serviceSet = new Set(); 18 | 19 | public setInjector(injector: I): this { 20 | this.injector = injector; 21 | return this; 22 | } 23 | 24 | public setUseTokenization(useToken: boolean): this { 25 | this.useToken = useToken; 26 | return this; 27 | } 28 | 29 | public abstract addService(serviceConstructor: any): void; 30 | 31 | public abstract clearAllServices(): void; 32 | 33 | public abstract getAllServices(): Set; 34 | 35 | public abstract getService(serviceConstructor: T): InstanceOf | null; 36 | } 37 | -------------------------------------------------------------------------------- /packages/di/src/logic/IDependencyRegistryEngine.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { InstanceOf } from "../index.js"; 8 | 9 | /** 10 | * Interface to facilitate the ability to add custom IOC containers by conforming to the proxy of adding and retrieval of services 11 | */ 12 | export interface IDependencyRegistryEngine { 13 | /** 14 | * Add a service from the IOC container. 15 | * @param serviceConstructor - The type of service to add 16 | */ 17 | addService(serviceConstructor: any): void; 18 | 19 | /** 20 | * Clear all Discord service classes 21 | */ 22 | clearAllServices(): void; 23 | 24 | /** 25 | * Get all Discord service classes 26 | * @returns {Set} 27 | */ 28 | getAllServices(): Set; 29 | 30 | /** 31 | * Get a service from the IOC container 32 | * @param {T} classType - the Class of the service to retrieve 33 | * @returns {InstanceOf | null} the instance of this service or null if there is no instance 34 | */ 35 | getService(classType: T): InstanceOf | null; 36 | } 37 | -------------------------------------------------------------------------------- /packages/di/src/logic/impl/DefaultDependencyRegistryEngine.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { InstanceOf } from "../../index.js"; 8 | import type { IDependencyRegistryEngine } from "../IDependencyRegistryEngine.js"; 9 | 10 | export class DefaultDependencyRegistryEngine 11 | implements IDependencyRegistryEngine 12 | { 13 | private static _instance: DefaultDependencyRegistryEngine | undefined; 14 | private _services = new Map(); 15 | 16 | public static get instance(): DefaultDependencyRegistryEngine { 17 | DefaultDependencyRegistryEngine._instance ??= 18 | new DefaultDependencyRegistryEngine(); 19 | return DefaultDependencyRegistryEngine._instance; 20 | } 21 | 22 | public addService(serviceConstructor: any): void { 23 | const service = new serviceConstructor(); 24 | this._services.set(serviceConstructor, service); 25 | } 26 | 27 | public clearAllServices(): void { 28 | this._services.clear(); 29 | } 30 | 31 | public getAllServices(): Set { 32 | return new Set(this._services.values()); 33 | } 34 | 35 | public getService(classType: T): InstanceOf { 36 | return this._services.get(classType) as InstanceOf; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/di/src/logic/impl/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./DefaultDependencyRegistryEngine.js"; 8 | export * from "./TsyringeDependencyRegistryEngine.js"; 9 | export * from "./TypeDiDependencyRegistryEngine.js"; 10 | -------------------------------------------------------------------------------- /packages/di/src/logic/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./AbstractConfigurableDependencyInjector.js"; 8 | export type * from "./IDependencyRegistryEngine.js"; 9 | export * from "./impl/index.js"; 10 | -------------------------------------------------------------------------------- /packages/di/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/discordx/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/discordx/examples/attachment/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ApplicationCommandOptionType, 9 | type Attachment, 10 | type CommandInteraction, 11 | } from "discord.js"; 12 | import { Discord, Slash, SlashOption } from "discordx"; 13 | 14 | @Discord() 15 | export class Example { 16 | @Slash({ description: "attachment" }) 17 | async attachment( 18 | @SlashOption({ 19 | description: "image", 20 | name: "image", 21 | required: true, 22 | type: ApplicationCommandOptionType.Attachment, 23 | }) 24 | attachment: Attachment, 25 | interaction: CommandInteraction, 26 | ): Promise { 27 | await interaction.reply(attachment.url); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/discordx/examples/attachment/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/builders/commands/autocomplete.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | SlashCommandBuilder, 9 | SlashCommandStringOption, 10 | type AutocompleteInteraction, 11 | type CommandInteraction, 12 | } from "discord.js"; 13 | import { Discord, Slash, SlashOption } from "discordx"; 14 | 15 | const cmd = new SlashCommandBuilder() 16 | .setName("planet-auto") 17 | .setDescription("Select a planet"); 18 | 19 | const planet_option = new SlashCommandStringOption() 20 | .setName("planet") 21 | .setDescription("Choose a planet") 22 | .setRequired(true) 23 | .setAutocomplete(true); 24 | 25 | @Discord() 26 | export class Example { 27 | @Slash(cmd) 28 | async hello( 29 | @SlashOption(planet_option) planet: string, 30 | interaction: CommandInteraction | AutocompleteInteraction, 31 | ): Promise { 32 | if (interaction.isAutocomplete()) { 33 | await interaction.respond([ 34 | { name: "Earth", value: "Earth" }, 35 | { name: "Mars", value: "Mars" }, 36 | ]); 37 | } else { 38 | await interaction.reply(`:rocket: going to ${planet}`); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/discordx/examples/builders/commands/choice.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | SlashCommandBuilder, 9 | SlashCommandStringOption, 10 | type CommandInteraction, 11 | } from "discord.js"; 12 | import { Discord, Slash, SlashOption } from "discordx"; 13 | 14 | const cmd = new SlashCommandBuilder() 15 | .setName("planet") 16 | .setDescription("Select a planet"); 17 | 18 | const planet_option = new SlashCommandStringOption() 19 | .setName("planet") 20 | .setDescription("Choose a planet") 21 | .setRequired(true) 22 | .addChoices([ 23 | { name: "Earth", value: "Earth" }, 24 | { name: "Mars", value: "Mars" }, 25 | ]); 26 | 27 | @Discord() 28 | export class Example { 29 | @Slash(cmd) 30 | async hello( 31 | @SlashOption(planet_option) planet: string, 32 | interaction: CommandInteraction, 33 | ): Promise { 34 | await interaction.reply(`:rocket: going to ${planet}`); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/discordx/examples/builders/commands/hello.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | SlashCommandBuilder, 9 | SlashCommandMentionableOption, 10 | type CommandInteraction, 11 | type User, 12 | } from "discord.js"; 13 | import { Discord, Slash, SlashOption } from "discordx"; 14 | 15 | const cmd = new SlashCommandBuilder() 16 | .setName("hello") 17 | .setDescription("Say hello!"); 18 | 19 | const user_option = new SlashCommandMentionableOption() 20 | .setName("user") 21 | .setDescription("Mention user to say hello to.") 22 | .setRequired(true); 23 | 24 | @Discord() 25 | export class Example { 26 | @Slash(cmd) 27 | async hello( 28 | @SlashOption(user_option) user: User, 29 | interaction: CommandInteraction, 30 | ): Promise { 31 | await interaction.reply(`:wave: ${user.toString()}`); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/discordx/examples/builders/commands/ping.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { SlashCommandBuilder, type CommandInteraction } from "discord.js"; 8 | import { Discord, Slash } from "discordx"; 9 | 10 | const cmd = new SlashCommandBuilder() 11 | .setName("ping") 12 | .setDescription("Reply with pong!"); 13 | 14 | @Discord() 15 | export class Example { 16 | @Slash(cmd) 17 | async ping(interaction: CommandInteraction): Promise { 18 | await interaction.reply("Pong"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/discordx/examples/builders/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/button/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ActionRowBuilder, 9 | ButtonBuilder, 10 | ButtonStyle, 11 | type ButtonInteraction, 12 | type CommandInteraction, 13 | type MessageActionRowComponentBuilder, 14 | } from "discord.js"; 15 | import { ButtonComponent, Discord, Slash } from "discordx"; 16 | 17 | @Discord() 18 | export class Example { 19 | @ButtonComponent({ id: "hello" }) 20 | async handler(interaction: ButtonInteraction): Promise { 21 | await interaction.reply(":wave:"); 22 | } 23 | 24 | @ButtonComponent({ id: "hello" }) 25 | handler2(interaction: ButtonInteraction): void { 26 | console.log(`${interaction.user.toString()} says hello`); 27 | } 28 | 29 | @Slash({ description: "test" }) 30 | async test(interaction: CommandInteraction): Promise { 31 | const btn = new ButtonBuilder() 32 | .setLabel("Hello") 33 | .setStyle(ButtonStyle.Primary) 34 | .setCustomId("hello"); 35 | 36 | const buttonRow = 37 | new ActionRowBuilder().addComponents( 38 | btn, 39 | ); 40 | 41 | await interaction.reply({ 42 | components: [buttonRow], 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/discordx/examples/button/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { dirname, importx } from "@discordx/importer"; 8 | import { Events, IntentsBitField } from "discord.js"; 9 | import { Client } from "discordx"; 10 | 11 | // biome-ignore lint/complexity/noStaticOnlyClass: ignore 12 | export class Main { 13 | private static client: Client; 14 | 15 | static async start(): Promise { 16 | Main.client = new Client({ 17 | // botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)], 18 | intents: [ 19 | IntentsBitField.Flags.Guilds, 20 | IntentsBitField.Flags.GuildMessages, 21 | ], 22 | silent: false, 23 | }); 24 | 25 | Main.client.once(Events.ClientReady, () => { 26 | void Main.client.initApplicationCommands(); 27 | 28 | console.log("Bot started"); 29 | }); 30 | 31 | Main.client.on(Events.InteractionCreate, (interaction) => { 32 | Main.client.executeInteraction(interaction); 33 | }); 34 | 35 | await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`); 36 | 37 | // let's start the bot 38 | if (!process.env.BOT_TOKEN) { 39 | throw Error("Could not find BOT_TOKEN in your environment"); 40 | } 41 | await Main.client.login(process.env.BOT_TOKEN); 42 | } 43 | } 44 | 45 | void Main.start(); 46 | -------------------------------------------------------------------------------- /packages/discordx/examples/button/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/contextmenu/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ApplicationCommandType, 9 | type MessageContextMenuCommandInteraction, 10 | type UserContextMenuCommandInteraction, 11 | } from "discord.js"; 12 | import { ContextMenu, Discord } from "discordx"; 13 | 14 | @Discord() 15 | export class Example { 16 | @ContextMenu({ 17 | name: "Hello from discordx", 18 | type: ApplicationCommandType.Message, 19 | }) 20 | async messageHandler( 21 | interaction: MessageContextMenuCommandInteraction, 22 | ): Promise { 23 | console.log("I am message"); 24 | await interaction.reply("message interaction works"); 25 | } 26 | 27 | @ContextMenu({ 28 | name: "Hello from discordx", 29 | type: ApplicationCommandType.User, 30 | }) 31 | async userHandler( 32 | interaction: UserContextMenuCommandInteraction, 33 | ): Promise { 34 | console.log(`Selected user: ${interaction.targetId}`); 35 | await interaction.reply("user interaction works"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/discordx/examples/contextmenu/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/di/tsyringe/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "discordx": "workspace:^", 4 | "tsyringe": "^4.10.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/discordx/examples/di/tsyringe/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/di/typedi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "discordx": "workspace:^", 4 | "typedi": "^0.10.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/discordx/examples/di/typedi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/event/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { Events } from "discord.js"; 8 | import { Discord, On, type ArgsOf } from "discordx"; 9 | 10 | @Discord() 11 | export class Example { 12 | @On() 13 | messageCreate([message]: ArgsOf): void { 14 | console.log(message.content); 15 | } 16 | 17 | @On() 18 | messageReactionAdd([ 19 | reaction, 20 | user, 21 | ]: ArgsOf): void { 22 | const member = reaction.message.guild?.members.resolve(user.id); 23 | if (member) { 24 | console.log(member.roles.cache.map((r) => r.name)); 25 | // member.roles.add("role-id"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/discordx/examples/event/commands/priority.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Events } from "discord.js"; 8 | import { Discord, On } from "discordx"; 9 | 10 | enum PriorityLevel { 11 | High, 12 | Moderate, 13 | Low, 14 | } 15 | 16 | @Discord() 17 | export class Example { 18 | @On({ event: Events.ClientReady, priority: PriorityLevel.Low }) 19 | onReady(): void { 20 | console.log(PriorityLevel[PriorityLevel.Low]); 21 | } 22 | 23 | @On({ event: Events.ClientReady, priority: PriorityLevel.High }) 24 | onReady3(): void { 25 | console.log(PriorityLevel[PriorityLevel.High]); 26 | } 27 | 28 | @On({ event: Events.ClientReady, priority: PriorityLevel.Moderate }) 29 | onReady2(): void { 30 | console.log(PriorityLevel[PriorityLevel.Moderate]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/discordx/examples/event/commands/rest.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Discord, On, type RestArgsOf } from "discordx"; 8 | 9 | @Discord() 10 | export class Example { 11 | @On.rest() 12 | rateLimited([data]: RestArgsOf<"rateLimited">): void { 13 | console.log(data.limit); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/discordx/examples/event/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { dirname, importx } from "@discordx/importer"; 8 | import { Events, IntentsBitField } from "discord.js"; 9 | import { Client } from "discordx"; 10 | 11 | // biome-ignore lint/complexity/noStaticOnlyClass: ignore 12 | export class Main { 13 | private static client: Client; 14 | 15 | static async start(): Promise { 16 | Main.client = new Client({ 17 | // botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)], 18 | intents: [ 19 | IntentsBitField.Flags.Guilds, 20 | IntentsBitField.Flags.GuildMessages, 21 | IntentsBitField.Flags.GuildMembers, 22 | IntentsBitField.Flags.GuildMessageReactions, 23 | IntentsBitField.Flags.MessageContent, 24 | ], 25 | silent: false, 26 | }); 27 | 28 | Main.Client.on(Events.ClientReady, () => { 29 | console.log("Bot started..."); 30 | }); 31 | 32 | await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`); 33 | 34 | // let's start the bot 35 | if (!process.env.BOT_TOKEN) { 36 | throw Error("Could not find BOT_TOKEN in your environment"); 37 | } 38 | await Main.client.login(process.env.BOT_TOKEN); 39 | } 40 | } 41 | 42 | void Main.start(); 43 | -------------------------------------------------------------------------------- /packages/discordx/examples/event/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/guards/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Discord, Guard, On, Slash, type ArgsOf } from "discordx"; 9 | 10 | import { ErrorHandler } from "../guards/Error.js"; 11 | import { NotBot } from "../guards/NotBot.js"; 12 | 13 | @Discord() 14 | export class Example { 15 | @On() 16 | @Guard(NotBot) 17 | messageCreate([message]: ArgsOf): void { 18 | console.log(message.content); 19 | } 20 | 21 | @Slash({ description: "hello" }) 22 | @Guard(NotBot) 23 | hello(interaction: CommandInteraction): void { 24 | console.log(interaction); 25 | } 26 | 27 | @Slash({ description: "errorGuard", name: "error-guard" }) 28 | @Guard(ErrorHandler, NotBot) 29 | errorGuard(): void { 30 | throw Error("My custom error"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/discordx/examples/guards/commands/interaction guard.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ApplicationCommandType, 9 | type ContextMenuCommandInteraction, 10 | } from "discord.js"; 11 | import { ContextMenu, Discord, Guard, type GuardFunction } from "discordx"; 12 | 13 | export const InteractionGuard: GuardFunction< 14 | ContextMenuCommandInteraction 15 | > = async (_interaction, _client, next) => { 16 | await next(); 17 | }; 18 | 19 | @Discord() 20 | export class Example { 21 | @ContextMenu({ name: "Check details", type: ApplicationCommandType.User }) 22 | @Guard(InteractionGuard) 23 | userHandler(interaction: ContextMenuCommandInteraction): void { 24 | console.log(`Selected user: ${interaction.targetId}`); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/discordx/examples/guards/guards/Error.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import type { GuardFunction } from "discordx"; 9 | 10 | export const ErrorHandler: GuardFunction = async ( 11 | interaction, 12 | _client, 13 | next, 14 | ) => { 15 | try { 16 | await next(); 17 | } catch (err) { 18 | if (err instanceof Error) { 19 | await interaction.reply(err.message); 20 | } else { 21 | await interaction.reply("unknown error"); 22 | } 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /packages/discordx/examples/guards/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { dirname, importx } from "@discordx/importer"; 8 | import { Events, IntentsBitField } from "discord.js"; 9 | import { Client } from "discordx"; 10 | 11 | // biome-ignore lint/complexity/noStaticOnlyClass: ignore 12 | export class Main { 13 | private static client: Client; 14 | 15 | static async start(): Promise { 16 | Main.client = new Client({ 17 | // botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)], 18 | intents: [ 19 | IntentsBitField.Flags.Guilds, 20 | IntentsBitField.Flags.GuildMessages, 21 | IntentsBitField.Flags.MessageContent, 22 | ], 23 | silent: false, 24 | }); 25 | 26 | Main.client.once(Events.ClientReady, () => { 27 | void Main.client.initApplicationCommands(); 28 | }); 29 | 30 | Main.client.on(Events.InteractionCreate, (interaction) => { 31 | Main.client.executeInteraction(interaction); 32 | }); 33 | 34 | await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`); 35 | 36 | // let's start the bot 37 | if (!process.env.BOT_TOKEN) { 38 | throw Error("Could not find BOT_TOKEN in your environment"); 39 | } 40 | await Main.client.login(process.env.BOT_TOKEN); 41 | } 42 | } 43 | 44 | void Main.start(); 45 | -------------------------------------------------------------------------------- /packages/discordx/examples/guards/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/localization/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ApplicationCommandOptionType, 9 | type CommandInteraction, 10 | } from "discord.js"; 11 | import { Discord, Slash, SlashOption } from "discordx"; 12 | 13 | @Discord() 14 | export class Example { 15 | @Slash({ 16 | description: "say hello", 17 | nameLocalizations: { 18 | "en-GB": "hello-x", 19 | }, 20 | }) 21 | async hello( 22 | @SlashOption({ 23 | description: "message", 24 | name: "message", 25 | required: true, 26 | type: ApplicationCommandOptionType.String, 27 | }) 28 | message: string, 29 | interaction: CommandInteraction, 30 | ): Promise { 31 | await interaction.reply(message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/discordx/examples/localization/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/menu/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { dirname, importx } from "@discordx/importer"; 8 | import { Events, IntentsBitField } from "discord.js"; 9 | import { Client } from "discordx"; 10 | 11 | // biome-ignore lint/complexity/noStaticOnlyClass: ignore 12 | export class Main { 13 | private static client: Client; 14 | 15 | static async start(): Promise { 16 | Main.client = new Client({ 17 | // botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)], 18 | intents: [ 19 | IntentsBitField.Flags.Guilds, 20 | IntentsBitField.Flags.GuildMessages, 21 | ], 22 | silent: false, 23 | }); 24 | 25 | Main.client.once(Events.ClientReady, () => { 26 | void Main.client.initApplicationCommands(); 27 | 28 | console.log("Bot started"); 29 | }); 30 | 31 | Main.client.on(Events.InteractionCreate, (interaction) => { 32 | Main.client.executeInteraction(interaction); 33 | }); 34 | 35 | await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`); 36 | 37 | // let's start the bot 38 | if (!process.env.BOT_TOKEN) { 39 | throw Error("Could not find BOT_TOKEN in your environment"); 40 | } 41 | await Main.client.login(process.env.BOT_TOKEN); 42 | } 43 | } 44 | 45 | void Main.start(); 46 | -------------------------------------------------------------------------------- /packages/discordx/examples/menu/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/modal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple bots/commands/botA.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Bot, Discord, Slash } from "discordx"; 9 | 10 | @Discord() 11 | @Bot("botA") // A bot id is crucial 12 | export class Example { 13 | @Slash({ description: "hello" }) 14 | async hello(interaction: CommandInteraction): Promise { 15 | await interaction.reply("I am bot A."); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple bots/commands/botB.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Bot, Discord, Slash } from "discordx"; 9 | 10 | @Discord() 11 | @Bot("botB") // A bot id is crucial 12 | export class Example { 13 | @Slash({ description: "hello" }) 14 | async hello(interaction: CommandInteraction): Promise { 15 | await interaction.reply("I am bot B."); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple bots/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Bot, Discord, Slash } from "discordx"; 9 | 10 | @Discord() 11 | @Bot("botA", "botB") // A bot id is crucial 12 | export class Example { 13 | @Slash({ description: "shared" }) 14 | async shared(interaction: CommandInteraction): Promise { 15 | await interaction.reply( 16 | "This is a shared command and can be used by both bots", 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple bots/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple-discord-instances/commands/commandA.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Discord, Slash } from "discordx"; 9 | 10 | @Discord() 11 | export class CommandA { 12 | @Slash({ description: "hello" }) 13 | async hello(interaction: CommandInteraction): Promise { 14 | await interaction.reply(":wave:"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple-discord-instances/commands/commandB.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import { Discord, Slash } from "discordx"; 9 | 10 | @Discord() 11 | export class CommandB { 12 | @Slash({ description: "hi" }) 13 | async hi(interaction: CommandInteraction): Promise { 14 | await interaction.reply(":wave:"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple-discord-instances/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { dirname, importx } from "@discordx/importer"; 8 | import { Events, IntentsBitField } from "discord.js"; 9 | import { Client } from "discordx"; 10 | 11 | // biome-ignore lint/complexity/noStaticOnlyClass: ignore 12 | export class Main { 13 | private static client: Client; 14 | 15 | static async start(): Promise { 16 | Main.client = new Client({ 17 | // botGuilds: [(client) => client.guilds.cache.map((guild) => guild.id)], 18 | intents: [ 19 | IntentsBitField.Flags.Guilds, 20 | IntentsBitField.Flags.GuildMessages, 21 | ], 22 | silent: false, 23 | }); 24 | 25 | Main.client.once(Events.ClientReady, () => { 26 | void Main.client.initApplicationCommands(); 27 | }); 28 | 29 | Main.client.on(Events.InteractionCreate, (interaction) => { 30 | Main.client.executeInteraction(interaction); 31 | }); 32 | 33 | await importx(`${dirname(import.meta.url)}/commands/**/*.{js,ts}`); 34 | 35 | // let's start the bot 36 | if (!process.env.BOT_TOKEN) { 37 | throw Error("Could not find BOT_TOKEN in your environment"); 38 | } 39 | await Main.client.login(process.env.BOT_TOKEN); 40 | } 41 | } 42 | 43 | void Main.start(); 44 | -------------------------------------------------------------------------------- /packages/discordx/examples/multiple-discord-instances/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/permission/commands/group.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { ChatInputCommandInteraction } from "discord.js"; 8 | import { Discord, Slash, SlashGroup } from "discordx"; 9 | 10 | @Discord() 11 | @SlashGroup({ 12 | defaultMemberPermissions: 0n, 13 | description: "vital", 14 | dmPermission: false, 15 | name: "vital", 16 | }) 17 | @SlashGroup("vital") 18 | export class Example { 19 | @Slash({ description: "perm1" }) 20 | async perm1(interaction: ChatInputCommandInteraction): Promise { 21 | await interaction.reply(":wave:"); 22 | } 23 | 24 | @Slash({ description: "perm2" }) 25 | async perm2(interaction: ChatInputCommandInteraction): Promise { 26 | await interaction.reply(":wave:"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/discordx/examples/permission/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/reaction/commands/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { MessageReaction, User } from "discord.js"; 8 | import { Discord, Reaction } from "discordx"; 9 | 10 | @Discord() 11 | export class Example { 12 | @Reaction({ emoji: "⭐", remove: true }) 13 | async starReaction(reaction: MessageReaction, user: User): Promise { 14 | await reaction.message.reply( 15 | `Received a ${reaction.emoji.toString()} from ${user.toString()}`, 16 | ); 17 | } 18 | 19 | @Reaction({ aliases: ["📍", "custom_emoji"], emoji: "📌" }) 20 | async pin(reaction: MessageReaction): Promise { 21 | await reaction.message.pin(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/discordx/examples/reaction/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/simple-command/commands/hello.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Discord, SimpleCommand, type SimpleCommandMessage } from "discordx"; 8 | 9 | @Discord() 10 | export class Example { 11 | @SimpleCommand({ aliases: ["hey", "hi"], name: "hello" }) 12 | async hello(command: SimpleCommandMessage): Promise { 13 | await command.message.reply( 14 | "This command should work both with `!` and `$` as a prefix.", 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/simple-command/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/examples/slash/commands/choice.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | ApplicationCommandOptionType, 9 | type CommandInteraction, 10 | } from "discord.js"; 11 | import { Discord, Slash, SlashChoice, SlashOption } from "discordx"; 12 | 13 | @Discord() 14 | export class Example { 15 | @Slash({ description: "choice-test", name: "choice-test" }) 16 | async min( 17 | @SlashChoice({ name: "alex", value: "alex" }) 18 | @SlashChoice({ name: "mike", value: "mike" }) 19 | @SlashOption({ 20 | description: "input", 21 | name: "input", 22 | required: true, 23 | type: ApplicationCommandOptionType.String, 24 | }) 25 | input: string, 26 | interaction: CommandInteraction, 27 | ): Promise { 28 | await interaction.reply(input); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/discordx/examples/slash/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": false, 4 | "esModuleInterop": true, 5 | "experimentalDecorators": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "noEmit": true, 10 | "noImplicitAny": true, 11 | "noUncheckedIndexedAccess": true, 12 | "rootDir": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "target": "ESNext" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/discordx/jest.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | preset: "ts-jest/presets/default-esm", 3 | resolver: "ts-jest-resolver", 4 | roots: ["/tests"], 5 | testEnvironment: "node", 6 | testRegex: "/*.test.ts", 7 | }; 8 | -------------------------------------------------------------------------------- /packages/discordx/src/classes/Mixin/ApplicationCommandMixin.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { ApplicationCommand } from "discord.js"; 8 | 9 | import type { DApplicationCommand } from "../../index.js"; 10 | 11 | export class ApplicationCommandMixin { 12 | constructor( 13 | public command: ApplicationCommand, 14 | public instance: DApplicationCommand, 15 | ) { 16 | // empty constructor 17 | } 18 | 19 | get name(): string { 20 | return this.command.name; 21 | } 22 | 23 | get description(): string { 24 | return this.command.description; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/discordx/src/classes/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./Mixin/ApplicationCommandMixin.js"; 8 | export * from "./SimpleCommandMessage.js"; 9 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/classes/DApplicationCommandGroup.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Decorator } from "@discordx/internal"; 8 | 9 | import type { 10 | DApplicationCommand, 11 | DApplicationCommandOption, 12 | } from "../index.js"; 13 | 14 | interface CreateStructure { 15 | name: string; 16 | payload: Partial; 17 | root?: string; 18 | } 19 | 20 | /** 21 | * @category Decorator 22 | */ 23 | export class DApplicationCommandGroup< 24 | InfoType = DApplicationCommand | DApplicationCommandOption, 25 | > extends Decorator { 26 | name: string; 27 | root?: string; 28 | payload: Partial; 29 | 30 | constructor(options: CreateStructure) { 31 | super(); 32 | this.name = options.name; 33 | this.root = options.root; 34 | this.payload = options.payload; 35 | } 36 | 37 | static create( 38 | options: CreateStructure, 39 | ): DApplicationCommandGroup { 40 | return new DApplicationCommandGroup(options); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/classes/DGuard.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Decorator } from "@discordx/internal"; 8 | 9 | import type { GuardFunction } from "../../index.js"; 10 | 11 | /** 12 | * @category Decorator 13 | */ 14 | export class DGuard extends Decorator { 15 | protected _fn: GuardFunction; 16 | 17 | get fn(): GuardFunction { 18 | return this._fn; 19 | } 20 | 21 | constructor(fn: GuardFunction) { 22 | super(); 23 | this._fn = fn; 24 | } 25 | 26 | static create(fn: GuardFunction): DGuard { 27 | return new DGuard(fn); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/classes/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./DApplicationCommand.js"; 8 | export * from "./DApplicationCommandGroup.js"; 9 | export * from "./DApplicationCommandOption.js"; 10 | export * from "./DApplicationCommandOptionChoice.js"; 11 | export * from "./DComponent.js"; 12 | export * from "./DDiscord.js"; 13 | export * from "./DGuard.js"; 14 | export * from "./DOn.js"; 15 | export * from "./DReaction.js"; 16 | export * from "./DSimpleCommand.js"; 17 | export * from "./DSimpleCommandOption.js"; 18 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/decorators/Discord.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { ClassDecoratorEx } from "@discordx/internal"; 8 | 9 | import { DDiscord, MetadataStorage } from "../../index.js"; 10 | 11 | /** 12 | * Create a metadata instance for the class 13 | * ___ 14 | * 15 | * [View Documentation](https://discordx.js.org/docs/discordx/decorators/general/discord) 16 | * 17 | * @category Decorator 18 | */ 19 | export function Discord(): ClassDecoratorEx { 20 | return (target) => { 21 | const clazz = target as unknown as new () => unknown; 22 | const instance = DDiscord.create(clazz.name).decorate(clazz, clazz.name); 23 | MetadataStorage.instance.addDiscord(instance); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/decorators/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./Bot.js"; 8 | export * from "./ButtonComponent.js"; 9 | export * from "./ContextMenu.js"; 10 | export * from "./Discord.js"; 11 | export * from "./Guard.js"; 12 | export * from "./Guild.js"; 13 | export * from "./ModalComponent.js"; 14 | export * from "./On.js"; 15 | export * from "./Once.js"; 16 | export * from "./Reaction.js"; 17 | export * from "./SelectMenuComponent.js"; 18 | export * from "./SimpleCommand.js"; 19 | export * from "./SimpleCommandOption.js"; 20 | export * from "./Slash.js"; 21 | export * from "./SlashChoice.js"; 22 | export * from "./SlashGroup.js"; 23 | export * from "./SlashOption.js"; 24 | -------------------------------------------------------------------------------- /packages/discordx/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./classes/index.js"; 8 | export * from "./decorators/index.js"; 9 | -------------------------------------------------------------------------------- /packages/discordx/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./classes/index.js"; 8 | export * from "./Client.js"; 9 | export * from "./decorators/index.js"; 10 | export * from "./logic/index.js"; 11 | export * from "./types/index.js"; 12 | export * from "./util/index.js"; 13 | export * from "@discordx/di"; 14 | export * from "@discordx/internal"; 15 | -------------------------------------------------------------------------------- /packages/discordx/src/logic/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./managers/index.js"; 8 | export * from "./metadata/MetadataStorage.js"; 9 | -------------------------------------------------------------------------------- /packages/discordx/src/logic/managers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ApplicationCommandManager.js"; 2 | export * from "./DebugManager.js"; 3 | export * from "./EventManager.js"; 4 | export * from "./InteractionHandler.js"; 5 | export * from "./ReactionManager.js"; 6 | export * from "./SimpleCommandManager.js"; 7 | -------------------------------------------------------------------------------- /packages/discordx/src/types/core/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { 8 | ChatInputCommandInteraction, 9 | Message, 10 | Snowflake, 11 | } from "discord.js"; 12 | 13 | import type { 14 | Client, 15 | DApplicationCommand, 16 | DComponent, 17 | DReaction, 18 | DSimpleCommand, 19 | SimpleCommandMessage, 20 | } from "../../index.js"; 21 | 22 | export type Awaitable = Promise | T; 23 | 24 | export type TransformerFunction = ( 25 | value: any, 26 | interaction: ChatInputCommandInteraction, 27 | ) => Awaitable; 28 | 29 | export type Next = (...paramsToNext: unknown[]) => Promise; 30 | 31 | export type IPrefix = string | string[]; 32 | export type IPrefixResolver = 33 | | string 34 | | string[] 35 | | ((message: Message) => Awaitable); 36 | 37 | export type IGuild = 38 | | Snowflake 39 | | Snowflake[] 40 | | (( 41 | client: Client, 42 | command: 43 | | DApplicationCommand 44 | | DComponent 45 | | DReaction 46 | | SimpleCommandMessage 47 | | undefined, 48 | ) => Snowflake | Snowflake[] | Promise | Promise); 49 | 50 | export interface ISimpleCommandByName { 51 | command: DSimpleCommand; 52 | name: string; 53 | } 54 | -------------------------------------------------------------------------------- /packages/discordx/src/types/core/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export type * from "./ClientOptions.js"; 8 | export type * from "./common.js"; 9 | export * from "./literal.js"; 10 | -------------------------------------------------------------------------------- /packages/discordx/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./core/index.js"; 8 | export * from "./public/index.js"; 9 | -------------------------------------------------------------------------------- /packages/discordx/src/types/public/enum.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | /** 8 | * Component type enum 9 | */ 10 | export enum ComponentType { 11 | Button, 12 | SelectMenu, 13 | Modal, 14 | } 15 | 16 | /** 17 | * Component type enum 18 | */ 19 | export enum SimpleCommandParseType { 20 | notCommand, 21 | notFound, 22 | } 23 | -------------------------------------------------------------------------------- /packages/discordx/src/types/public/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export type * from "./common.js"; 8 | export * from "./enum.js"; 9 | export * from "./simple command.js"; 10 | export type * from "./slash.js"; 11 | -------------------------------------------------------------------------------- /packages/discordx/src/types/public/simple command.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { 8 | GuildChannel, 9 | GuildMember, 10 | Role, 11 | ThreadChannel, 12 | User, 13 | } from "discord.js"; 14 | 15 | import type { SimpleCommandMessage } from "../../index.js"; 16 | import type { IGuild, IPrefix, NotEmpty } from "../index.js"; 17 | 18 | export type ArgSplitter = 19 | | string 20 | | RegExp 21 | | ((command: SimpleCommandMessage) => string[]); 22 | 23 | export interface SimpleCommandOptions { 24 | aliases?: string[]; 25 | argSplitter?: ArgSplitter; 26 | botIds?: string[]; 27 | description?: string; 28 | directMessage?: boolean; 29 | guilds?: IGuild[]; 30 | name?: NotEmpty; 31 | prefix?: IPrefix; 32 | } 33 | 34 | export interface SimpleCommandOptionOptions { 35 | description?: string; 36 | name: NotEmpty; 37 | type: SimpleCommandOptionType; 38 | } 39 | 40 | export type SimpleOptionType = 41 | | string 42 | | number 43 | | boolean 44 | | ThreadChannel 45 | | GuildChannel 46 | | User 47 | | GuildMember 48 | | Role 49 | | null; 50 | 51 | export enum SimpleCommandOptionType { 52 | String, 53 | Number, 54 | Boolean, 55 | User, 56 | Channel, 57 | Role, 58 | Mentionable, 59 | } 60 | -------------------------------------------------------------------------------- /packages/discordx/src/util/common.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts the provided arguments into a single flat array of strings. 3 | * Accepts multiple arguments, each of which can be a string or an array of strings. 4 | * If an argument is a string, it is wrapped in an array. If it is an array, it is flattened. 5 | * 6 | * @param {...(string | string[])[]} input - One or more strings or arrays of strings. 7 | * @returns {string[]} A flat array of strings. 8 | */ 9 | export function toStringArray(...input: (string | string[])[]): string[] { 10 | return input.flatMap((item) => (Array.isArray(item) ? item : [item])); 11 | } 12 | -------------------------------------------------------------------------------- /packages/discordx/src/util/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./common.js"; 8 | export * from "./comparison.js"; 9 | export * from "./resolve-guilds.js"; 10 | export * from "./slash-name-validator.js"; 11 | -------------------------------------------------------------------------------- /packages/discordx/src/util/resolve-guilds.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import isEqual from "lodash/isEqual.js"; 8 | import uniqWith from "lodash/uniqWith.js"; 9 | 10 | import type { 11 | Client, 12 | DApplicationCommand, 13 | DComponent, 14 | DReaction, 15 | IGuild, 16 | SimpleCommandMessage, 17 | } from "../index.js"; 18 | 19 | /** 20 | * Resolve IGuilds 21 | * @param client 22 | * @param command 23 | * @param guilds 24 | * @returns 25 | */ 26 | export const resolveIGuilds = async ( 27 | client: Client, 28 | command: 29 | | DApplicationCommand 30 | | DComponent 31 | | DReaction 32 | | SimpleCommandMessage 33 | | undefined, 34 | guilds: IGuild[], 35 | ): Promise => { 36 | const guildX = await Promise.all( 37 | guilds.map(async (guild) => 38 | typeof guild === "function" ? guild(client, command) : guild, 39 | ), 40 | ); 41 | 42 | return uniqWith(guildX.flat(1), isEqual); 43 | }; 44 | -------------------------------------------------------------------------------- /packages/discordx/src/util/slash-name-validator.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { SpecialCharactersList } from "../types/index.js"; 8 | 9 | /** 10 | * Slash name validator 11 | * @param name - name 12 | * @returns 13 | */ 14 | export function SlashNameValidator(name: string): true { 15 | const isNotValid = 16 | name.length === 0 || 17 | name.length > 32 || 18 | name.toLowerCase() !== name || 19 | SpecialCharactersList.some((c) => name.includes(c)); 20 | 21 | if (isNotValid) { 22 | throw Error( 23 | `Invalid slash name: ${name}\nName must only be lowercase with no space as per Discord guidelines (https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-naming)\n`, 24 | ); 25 | } 26 | 27 | return true; 28 | } 29 | -------------------------------------------------------------------------------- /packages/discordx/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./", 4 | "module": "ESNext", 5 | "target": "ESNext", 6 | "strict": true, 7 | "strictNullChecks": true, 8 | "noUncheckedIndexedAccess": true, 9 | "noImplicitAny": true, 10 | "sourceMap": true, 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": false, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/discordx/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": [ 21 | "node_modules", 22 | "dist", 23 | "tests", 24 | "examples", 25 | "docs", 26 | "packages", 27 | "scripts" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/importer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/importer 2 | 3 | ## 1.3.3 4 | 5 | ### Patch Changes 6 | 7 | - Dep update 8 | 9 | ## 1.3.2 10 | 11 | ### Patch Changes 12 | 13 | - dep update and eslint 14 | 15 | ## 1.3.1 16 | 17 | ### Patch Changes 18 | 19 | - build config 20 | 21 | ## 1.3.0 22 | 23 | ### Minor Changes 24 | 25 | - fix: monorepo 26 | -------------------------------------------------------------------------------- /packages/importer/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/importer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@discordx/importer", 3 | "version": "1.3.3", 4 | "private": false, 5 | "description": "A solution to import files on the module and commonjs at the same time", 6 | "keywords": [ 7 | "cjs", 8 | "esm", 9 | "importer", 10 | "javascript", 11 | "mjs", 12 | "typescript" 13 | ], 14 | "homepage": "https://discordx.js.org", 15 | "bugs": { 16 | "url": "https://github.com/discordx-ts/discordx/issues", 17 | "email": "vijayymmeena@gmail.com" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/discordx-ts/discordx.git" 22 | }, 23 | "license": "Apache-2.0", 24 | "contributors": [ 25 | "Vijay Meena (https://github.com/vijayymmeena)" 26 | ], 27 | "exports": { 28 | ".": { 29 | "import": "./dist/index.mjs", 30 | "require": "./dist/index.js" 31 | } 32 | }, 33 | "types": "./dist/index.d.ts", 34 | "files": [ 35 | "dist", 36 | "index.d.ts", 37 | "CHANGELOG.md", 38 | "LICENSE.txt", 39 | "README.md", 40 | "SECURITY.md", 41 | "package.json" 42 | ], 43 | "scripts": { 44 | "build": "tsup src/index.ts --format cjs,esm --dts" 45 | }, 46 | "dependencies": { 47 | "glob": "^11.0.3" 48 | }, 49 | "devDependencies": { 50 | "typescript": "5.9.3" 51 | }, 52 | "publishConfig": { 53 | "access": "public" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/importer/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import path from "node:path"; 8 | import { fileURLToPath } from "node:url"; 9 | import { glob } from "glob"; 10 | 11 | export function isESM(): boolean { 12 | return !!import.meta.url; 13 | } 14 | 15 | export function dirname(url: string): string { 16 | return path.dirname(fileURLToPath(url)); 17 | } 18 | 19 | export async function resolve(...paths: string[]): Promise { 20 | const imports: string[] = []; 21 | 22 | await Promise.all( 23 | paths.map(async (ps) => { 24 | const files = await glob(ps.split(path.sep).join("/")); 25 | 26 | files.forEach((file) => { 27 | if (!imports.includes(file)) { 28 | imports.push(`file://${file}`); 29 | } 30 | }); 31 | }), 32 | ); 33 | 34 | return imports; 35 | } 36 | 37 | export async function importx(...paths: string[]): Promise { 38 | const files = await resolve(...paths); 39 | await Promise.all(files.map((file) => import(file))); 40 | } 41 | -------------------------------------------------------------------------------- /packages/importer/tests/cjs/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-require-imports */ 2 | const path = require("node:path"); 3 | const importer = require("@discordx/importer"); 4 | 5 | const { importx, isESM, resolve } = importer; 6 | 7 | async function main() { 8 | console.log(`isESM: ${isESM()}`); 9 | 10 | await resolve(path.join(__dirname, "../commands/**.js")).then(console.log); 11 | 12 | importx(path.join(__dirname, "../commands/**.js")); 13 | } 14 | 15 | main(); 16 | -------------------------------------------------------------------------------- /packages/importer/tests/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /packages/importer/tests/commands/demo.js: -------------------------------------------------------------------------------- 1 | console.log("I think, I am imported"); 2 | -------------------------------------------------------------------------------- /packages/importer/tests/esm/index.mjs: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import { dirname, importx, isESM, resolve } from "@discordx/importer"; 3 | 4 | const __dirname = dirname(import.meta.url); 5 | 6 | async function main() { 7 | console.log(`isESM: ${isESM()}`); 8 | 9 | await resolve(path.join(__dirname, "../commands/**.js")).then(console.log); 10 | 11 | importx(path.join(__dirname, "../commands/**.js")); 12 | } 13 | 14 | main(); 15 | -------------------------------------------------------------------------------- /packages/importer/tests/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /packages/importer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["node_modules", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/internal/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/internal 2 | 3 | ## 1.2.0 4 | 5 | ### Minor Changes 6 | 7 | - refactor: various internal code improvement 8 | 9 | ## 1.1.5 10 | 11 | ### Patch Changes 12 | 13 | - dep update and eslint 14 | 15 | ## 1.1.4 16 | 17 | ### Patch Changes 18 | 19 | - build config 20 | 21 | ## 1.1.3 22 | 23 | ### Patch Changes 24 | 25 | - description change and minor improvements 26 | 27 | ## 1.1.2 28 | 29 | ### Patch Changes 30 | 31 | - lint 32 | 33 | ## 1.1.1 34 | 35 | ### Patch Changes 36 | 37 | - internal code improvement 38 | 39 | ## 1.1.0 40 | 41 | ### Minor Changes 42 | 43 | - fix: monorepo 44 | -------------------------------------------------------------------------------- /packages/internal/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/internal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@discordx/internal", 3 | "version": "1.2.0", 4 | "private": false, 5 | "description": "Internal methods for discordx", 6 | "keywords": [ 7 | "bot", 8 | "decorators", 9 | "dependency injection", 10 | "discord", 11 | "discordx", 12 | "framework", 13 | "javascript", 14 | "tsyringe", 15 | "typescript" 16 | ], 17 | "homepage": "https://discordx.js.org", 18 | "bugs": { 19 | "url": "https://github.com/discordx-ts/discordx/issues", 20 | "email": "vijayymmeena@gmail.com" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/discordx-ts/discordx.git" 25 | }, 26 | "license": "Apache-2.0", 27 | "contributors": [ 28 | "Owen Calvin (https://github.com/OwenCalvin)", 29 | "Vijay Meena (https://github.com/vijayymmeena)" 30 | ], 31 | "exports": { 32 | ".": { 33 | "import": "./dist/index.mjs", 34 | "require": "./dist/index.js" 35 | } 36 | }, 37 | "types": "./dist/index.d.ts", 38 | "files": [ 39 | "dist", 40 | "CHANGELOG.md", 41 | "LICENSE.txt", 42 | "README.md", 43 | "SECURITY.md", 44 | "package.json" 45 | ], 46 | "scripts": { 47 | "build": "tsup src/index.ts --format cjs,esm --dts", 48 | "build:typedoc": "npx typedoc src/index.ts --out ../../docs/static/api/internal" 49 | }, 50 | "devDependencies": { 51 | "typescript": "5.9.3" 52 | }, 53 | "engines": { 54 | "node": ">=16.0.0", 55 | "npm": ">=7.0.0" 56 | }, 57 | "publishConfig": { 58 | "access": "public" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/internal/src/decorator/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./classes/Decorator.js"; 8 | export * from "./classes/Modifier.js"; 9 | export * from "./util.js"; 10 | -------------------------------------------------------------------------------- /packages/internal/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./decorator/index.js"; 8 | export type * from "./types/decorators.js"; 9 | -------------------------------------------------------------------------------- /packages/internal/src/types/decorators.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export type ClassDecoratorEx = ( 8 | target: Record, 9 | propertyKey?: undefined, 10 | descriptor?: undefined, 11 | ) => void; 12 | 13 | export type PropertyDecorator = ( 14 | target: Record, 15 | propertyKey: string, 16 | descriptor?: undefined, 17 | ) => void; 18 | 19 | export type MethodDecoratorEx = ( 20 | target: Record, 21 | propertyKey: string, 22 | descriptor: TypedPropertyDescriptor, 23 | ) => void; 24 | 25 | export type ParameterDecoratorEx = ( 26 | target: Record, 27 | propertyKey: string, 28 | parameterIndex: number, 29 | ) => void; 30 | 31 | export type ClassMethodDecorator = ( 32 | target: Record, 33 | propertyKey?: string, 34 | descriptor?: TypedPropertyDescriptor, 35 | ) => void; 36 | -------------------------------------------------------------------------------- /packages/internal/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/lava-player/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/lava-player 2 | 3 | ## 2.1.5 4 | 5 | ### Patch Changes 6 | 7 | - Dep update 8 | 9 | ## 2.1.4 10 | 11 | ### Patch Changes 12 | 13 | - dep update and eslint 14 | 15 | ## 2.1.3 16 | 17 | ### Patch Changes 18 | 19 | - dep updates and improvements 20 | 21 | ## 2.1.2 22 | 23 | ### Patch Changes 24 | 25 | - build config 26 | 27 | ## 2.1.1 28 | 29 | ### Patch Changes 30 | 31 | - export http client 32 | 33 | ## 2.1.0 34 | 35 | ### Minor Changes 36 | 37 | - improved method and class names 38 | 39 | ## 2.0.6 40 | 41 | ### Patch Changes 42 | 43 | - use null for empty rest response 44 | 45 | ## 2.0.5 46 | 47 | ### Patch Changes 48 | 49 | - improvements 50 | 51 | ## 2.0.4 52 | 53 | ### Patch Changes 54 | 55 | - description change and minor improvements 56 | 57 | ## 2.0.3 58 | 59 | ### Patch Changes 60 | 61 | - lint 62 | 63 | ## 2.0.2 64 | 65 | ### Patch Changes 66 | 67 | - allow replace track 68 | 69 | ## 2.0.1 70 | 71 | ### Patch Changes 72 | 73 | - set default self mute to false 74 | 75 | ## 2.0.0 76 | 77 | ### Major Changes 78 | 79 | - lavalink v4 support 80 | 81 | ## 1.1.1 82 | 83 | ### Patch Changes 84 | 85 | - fix: missing ws package 86 | 87 | ## 1.1.0 88 | 89 | ### Minor Changes 90 | 91 | - fix: monorepo 92 | -------------------------------------------------------------------------------- /packages/lava-player/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/lava-player/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@discordx/lava-player", 3 | "version": "2.1.5", 4 | "private": false, 5 | "description": "Powerful Lavalink player library written in TypeScript for Node.js", 6 | "keywords": [ 7 | "bot", 8 | "discord", 9 | "discordx", 10 | "javascript", 11 | "lava-player", 12 | "lavalink", 13 | "music", 14 | "typescript", 15 | "youtube" 16 | ], 17 | "homepage": "https://discordx.js.org", 18 | "bugs": { 19 | "url": "https://github.com/discordx-ts/discordx/issues", 20 | "email": "vijayymmeena@gmail.com" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/discordx-ts/discordx.git" 25 | }, 26 | "license": "Apache-2.0", 27 | "contributors": [ 28 | "Vijay Meena (https://github.com/vijayymmeena)" 29 | ], 30 | "exports": { 31 | ".": { 32 | "import": "./dist/index.mjs", 33 | "require": "./dist/index.js" 34 | } 35 | }, 36 | "types": "./dist/index.d.ts", 37 | "files": [ 38 | "dist", 39 | "CHANGELOG.md", 40 | "LICENSE.txt", 41 | "README.md", 42 | "SECURITY.md", 43 | "package.json" 44 | ], 45 | "scripts": { 46 | "build": "tsup src/index.ts --format cjs,esm --dts", 47 | "build:typedoc": "npx typedoc src/index.ts --out ../../docs/static/api/lava-player" 48 | }, 49 | "dependencies": { 50 | "@types/backoff": "^2.5.5", 51 | "backoff": "^2.5.0", 52 | "ws": "^8.18.3" 53 | }, 54 | "devDependencies": { 55 | "@types/ws": "^8.18.1", 56 | "typescript": "5.9.3" 57 | }, 58 | "engines": { 59 | "node": ">=16.0.0", 60 | "npm": ">=7.0.0" 61 | }, 62 | "publishConfig": { 63 | "access": "public" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/lava-player/src/README.md: -------------------------------------------------------------------------------- 1 | # @discordx/lava-player 2 | 3 | A powerful lava link player library written in [TypeScript](https://www.typescriptlang.org) for [Node.js](https://nodejs.org). Support youtube songs and playlist. 4 | 5 | # About 6 | 7 | - Wrapper for the [Lavalink](https://github.com/lavalink-devs/Lavalink) audio client for Discord in TypeScript. 8 | -------------------------------------------------------------------------------- /packages/lava-player/src/cluster.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { BaseCluster } from "./base/base-cluster.js"; 8 | import type ClusterNode from "./cluster-node.js"; 9 | import type { ClusterNodeOptions } from "./cluster-node.js"; 10 | 11 | export interface ClusterOptions { 12 | filter?: (node: ClusterNode, guildId: string) => boolean; 13 | nodes?: ClusterNodeOptions[]; 14 | send: (guildId: string, packet: any) => any; 15 | } 16 | 17 | export class Cluster extends BaseCluster { 18 | public filter: (node: ClusterNode, guildId: string) => boolean; 19 | public send: (guildId: string, packet: any) => any; 20 | 21 | constructor(options: ClusterOptions) { 22 | super(options.nodes); 23 | this.filter = options.filter ?? (() => true); 24 | this.send = options.send; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/lava-player/src/core/guild-player-store.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { BaseNode } from "../base/base-node.js"; 8 | import { GuildPlayer } from "./guild-player.js"; 9 | 10 | export default class GuildPlayerStore< 11 | T extends BaseNode = BaseNode, 12 | > extends Map> { 13 | public readonly node: T; 14 | 15 | constructor(node: T) { 16 | super(); 17 | this.node = node; 18 | } 19 | 20 | public get(key: string): GuildPlayer { 21 | let player = super.get(key); 22 | if (!player) { 23 | player = new GuildPlayer(this.node, key); 24 | this.set(key, player); 25 | } 26 | 27 | return player; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/lava-player/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./base/base-cluster.js"; 8 | export * from "./base/base-node.js"; 9 | export * from "./cluster.js"; 10 | export * from "./cluster-node.js"; 11 | export * from "./core/connection.js"; 12 | export * from "./core/guild-player.js"; 13 | export * from "./core/http.js"; 14 | export * from "./core/rest.js"; 15 | export * from "./node.js"; 16 | export * from "./types/index.js"; 17 | -------------------------------------------------------------------------------- /packages/lava-player/src/node.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { BaseNode } from "./base/base-node.js"; 8 | import type { BaseNodeOptions } from "./types/index.js"; 9 | 10 | export interface NodeOptions extends BaseNodeOptions { 11 | send: (guildId: string, packet: any) => any; 12 | } 13 | 14 | export class Node extends BaseNode { 15 | public send: (guildId: string, packet: any) => any; 16 | 17 | constructor(options: NodeOptions) { 18 | super(options); 19 | this.send = options.send; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/lava-player/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export type * from "./node.js"; 8 | export * from "./op.js"; 9 | export * from "./player.js"; 10 | export * from "./rest.js"; 11 | export * from "./route-planner.js"; 12 | -------------------------------------------------------------------------------- /packages/lava-player/src/types/node.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { ConnectionOptions } from "../index.js"; 8 | 9 | export interface VoiceStateUpdate { 10 | channel_id?: string; 11 | deaf?: boolean; 12 | guild_id: string; 13 | mute?: boolean; 14 | self_deaf?: boolean; 15 | self_mute?: boolean; 16 | session_id: string; 17 | suppress?: boolean; 18 | user_id: string; 19 | } 20 | 21 | export interface VoiceServerUpdate { 22 | endpoint: string; 23 | guild_id: string; 24 | token: string; 25 | } 26 | 27 | export interface RestOptions { 28 | address: string; 29 | port: number; 30 | secure?: boolean; 31 | } 32 | 33 | export interface HostOptions { 34 | address: string; 35 | connectionOptions?: ConnectionOptions; 36 | port: number; 37 | rest?: RestOptions; 38 | secure?: boolean; 39 | } 40 | 41 | export interface BaseNodeOptions { 42 | host?: HostOptions; 43 | password: string; 44 | userId: string; 45 | } 46 | -------------------------------------------------------------------------------- /packages/lava-player/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "esModuleInterop": true, 7 | "sourceMap": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "noUncheckedIndexedAccess": true, 11 | "rootDir": "src", 12 | "outDir": "dist", 13 | "emitDecoratorMetadata": false, 14 | "experimentalDecorators": true, 15 | "declaration": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "moduleResolution": "Bundler", 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/lava-queue/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/lava-queue/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./queue.js"; 8 | export * from "./queue-manager.js"; 9 | export * from "./util.js"; 10 | -------------------------------------------------------------------------------- /packages/lava-queue/src/util.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | export enum RepeatMode { 9 | OFF = "OFF", 10 | REPEAT_ALL = "REPEAT_ALL", 11 | REPEAT_ONE = "REPEAT_ONE", 12 | } 13 | 14 | export function fromMS(duration: number): string { 15 | const seconds = Math.floor((duration / 1e3) % 60).toString(); 16 | const minutes = Math.floor((duration / 6e4) % 60).toString(); 17 | const hours = Math.floor(duration / 36e5).toString(); 18 | const secondsPad = seconds.padStart(2, "0"); 19 | const minutesPad = minutes.padStart(2, "0"); 20 | const hoursPad = hours.padStart(2, "0"); 21 | return `${hours ? `${hoursPad}:` : ""}${minutesPad}:${secondsPad}`; 22 | } 23 | 24 | export function toMS(duration: string): number { 25 | const parts = duration.split(":").map(parseFloat); 26 | if (parts.some(Number.isNaN)) { 27 | throw new Error(`Invalid duration format: "${duration}"`); 28 | } 29 | 30 | // Calculate total seconds (supports hh:mm:ss, mm:ss, or ss) 31 | const seconds = parts.reduce((total, value) => total * 60 + value, 0); 32 | 33 | return Math.round(seconds * 1000); 34 | } 35 | -------------------------------------------------------------------------------- /packages/lava-queue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "esModuleInterop": true, 7 | "sourceMap": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "noUncheckedIndexedAccess": true, 11 | "rootDir": "src", 12 | "outDir": "dist", 13 | "emitDecoratorMetadata": false, 14 | "experimentalDecorators": true, 15 | "declaration": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "moduleResolution": "Bundler", 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/music/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/music 2 | 3 | ## 6.3.3 4 | 5 | ### Patch Changes 6 | 7 | - Dep update 8 | 9 | - Updated dependencies []: 10 | - @discordx/importer@1.3.3 11 | 12 | ## 6.3.2 13 | 14 | ### Patch Changes 15 | 16 | - dep update and eslint 17 | 18 | - Updated dependencies []: 19 | - @discordx/importer@1.3.2 20 | 21 | ## 6.3.1 22 | 23 | ### Patch Changes 24 | 25 | - fix: track repeat mode 26 | 27 | ## 6.3.0 28 | 29 | ### Minor Changes 30 | 31 | - replace ytdl core 32 | 33 | ## 6.2.1 34 | 35 | ### Patch Changes 36 | 37 | - dep updates and improvements 38 | 39 | ## 6.2.0 40 | 41 | ### Minor Changes 42 | 43 | - improved player 44 | 45 | ## 6.1.3 46 | 47 | ### Patch Changes 48 | 49 | - build config 50 | 51 | - Updated dependencies []: 52 | - @discordx/importer@1.3.1 53 | 54 | ## 6.1.2 55 | 56 | ### Patch Changes 57 | 58 | - description change and minor improvements 59 | 60 | ## 6.1.1 61 | 62 | ### Patch Changes 63 | 64 | - lint 65 | 66 | ## 6.1.0 67 | 68 | ### Minor Changes 69 | 70 | - fix: monorepo 71 | -------------------------------------------------------------------------------- /packages/music/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/music/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./node.js"; 8 | export * from "./queue.js"; 9 | export * from "./queue-manager.js"; 10 | export * from "./types/index.js"; 11 | -------------------------------------------------------------------------------- /packages/music/src/types/audio-node.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { AudioPlayerStatus } from "@discordjs/voice"; 8 | 9 | export enum AudioNodeEvent { 10 | Debug = "DEBUG", 11 | Error = "ERROR", 12 | PlaybackInfo = "PLAYBACK_INFO", 13 | StateChange = "STATE_CHANGE", 14 | Subscription = "SUBSCRIPTION", 15 | UnSubscription = "UN_SUBSCRIPTION", 16 | } 17 | 18 | export interface PlaybackInfoAudioNodePayload { 19 | ended: boolean; 20 | playbackDuration: number; 21 | playerStatus: AudioPlayerStatus; 22 | type: AudioNodeEvent.PlaybackInfo; 23 | } 24 | 25 | export interface DebugAudioNodePayload { 26 | message: string; 27 | type: AudioNodeEvent.Debug; 28 | } 29 | 30 | export interface StateChangeAudioNodePayload { 31 | newState: AudioPlayerStatus; 32 | oldState: AudioPlayerStatus; 33 | type: AudioNodeEvent.StateChange; 34 | } 35 | 36 | export type AudioNodeEventPayload = 37 | | PlaybackInfoAudioNodePayload 38 | | DebugAudioNodePayload 39 | | StateChangeAudioNodePayload; 40 | -------------------------------------------------------------------------------- /packages/music/src/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./audio-node.js"; 8 | export * from "./communication-parent.js"; 9 | export * from "./communication-worker.js"; 10 | export * from "./queue-node-event.js"; 11 | -------------------------------------------------------------------------------- /packages/music/src/types/queue-node-event.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { ParentProcessDataPayload } from "./communication-parent.js"; 8 | 9 | export enum QueueEvent { 10 | ParentProcessEvent = "PARENT_PROCESS_EVENT", 11 | } 12 | 13 | export interface QueueEventPayloads { 14 | [QueueEvent.ParentProcessEvent]: ParentProcessDataPayload; 15 | } 16 | -------------------------------------------------------------------------------- /packages/music/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "esModuleInterop": true, 7 | "sourceMap": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "noUncheckedIndexedAccess": true, 11 | "rootDir": "src", 12 | "outDir": "dist", 13 | "emitDecoratorMetadata": false, 14 | "experimentalDecorators": true, 15 | "declaration": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "moduleResolution": "Bundler", 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/pagination/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @discordx/pagination 2 | 3 | ## 4.4.0 4 | 5 | ### Minor Changes 6 | 7 | - refactor(pagination): adapt to builder methods and getter 8 | 9 | ## 4.3.0 10 | 11 | ### Minor Changes 12 | 13 | - pagination button label optional 14 | 15 | ## 4.2.0 16 | 17 | ### Minor Changes 18 | 19 | - allow pagination button to be removed 20 | 21 | ## 4.1.0 22 | 23 | ### Minor Changes 24 | 25 | - page generation improvements 26 | 27 | ## 4.0.1 28 | 29 | ### Patch Changes 30 | 31 | - fixes pagination exit on same page selection 32 | 33 | ## 4.0.0 34 | 35 | ### Major Changes 36 | 37 | - pagination upgrade 38 | 39 | ## 3.6.0 40 | 41 | ### Minor Changes 42 | 43 | - code refactoring 44 | 45 | ## 3.5.8 46 | 47 | ### Patch Changes 48 | 49 | - Dep update 50 | 51 | ## 3.5.7 52 | 53 | ### Patch Changes 54 | 55 | - dep update and eslint 56 | 57 | ## 3.5.6 58 | 59 | ### Patch Changes 60 | 61 | - refactor(pagination): emoji support for button 62 | 63 | ## 3.5.5 64 | 65 | ### Patch Changes 66 | 67 | - dep updates and improvements 68 | 69 | ## 3.5.4 70 | 71 | ### Patch Changes 72 | 73 | - build config 74 | 75 | ## 3.5.3 76 | 77 | ### Patch Changes 78 | 79 | - description change and minor improvements 80 | 81 | ## 3.5.2 82 | 83 | ### Patch Changes 84 | 85 | - lint 86 | 87 | ## 3.5.1 88 | 89 | ### Patch Changes 90 | 91 | - fix: payload construction with djs 14.15.1 92 | 93 | ## 3.5.0 94 | 95 | ### Minor Changes 96 | 97 | - fix: monorepo 98 | -------------------------------------------------------------------------------- /packages/pagination/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/.gitignore: -------------------------------------------------------------------------------- 1 | tmp -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/commands/configurations.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Pagination } from "@discordx/pagination"; 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash } from "discordx"; 10 | 11 | import { GeneratePages } from "../util/common.js"; 12 | 13 | @Discord() 14 | export class Example { 15 | // example: simple slash with menu pagination 16 | @Slash({ 17 | description: "Custom page name for select menu", 18 | name: "config-example", 19 | }) 20 | async configExample(interaction: CommandInteraction): Promise { 21 | const pagination = new Pagination(interaction, GeneratePages(), { 22 | selectMenu: { 23 | pageText: "My custom page: {page}, Index: {page}", 24 | }, 25 | }); 26 | 27 | await pagination.send(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/commands/slash-example.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import fs from "node:fs/promises"; 8 | import { Pagination, type PaginationItem } from "@discordx/pagination"; 9 | import type { CommandInteraction } from "discord.js"; 10 | import { Discord, Slash } from "discordx"; 11 | 12 | @Discord() 13 | export class SlashExample { 14 | // example: pagination for all slash command 15 | @Slash({ 16 | description: "pagination attachment", 17 | name: "pagination-attachment", 18 | }) 19 | async cmd(interaction: CommandInteraction): Promise { 20 | const filename = "tmp/hello.txt"; 21 | await fs.mkdir("tmp").catch(() => null); 22 | await fs.writeFile(filename, "test string"); 23 | const pages: PaginationItem[] = [ 24 | { 25 | content: "Page 1", 26 | files: [filename], 27 | }, 28 | { 29 | content: "Page 2", 30 | }, 31 | { 32 | content: "Page 3", 33 | files: [filename], 34 | }, 35 | ]; 36 | 37 | const pagination = new Pagination(interaction, pages, { time: 10000 }); 38 | await pagination.send(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@discordx/importer": "workspace:^", 4 | "@discordx/pagination": "workspace:^", 5 | "discordx": "workspace:^" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "noUncheckedIndexedAccess": true, 8 | "outDir": "dist", 9 | "emitDecoratorMetadata": false, 10 | "experimentalDecorators": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "moduleResolution": "Bundler", 13 | "esModuleInterop": true 14 | }, 15 | "exclude": ["node_modules", "tests", "examples"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/pagination/examples/pagination/util/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { PaginationItem } from "@discordx/pagination"; 8 | import { EmbedBuilder } from "discord.js"; 9 | 10 | export function GeneratePages(limit?: number): PaginationItem[] { 11 | const pages = Array.from(Array(limit ?? 20).keys()).map((i) => { 12 | return { content: `I am ${String(i + 1)}`, embed: `Demo ${String(i + 1)}` }; 13 | }); 14 | 15 | return pages.map((page) => { 16 | return { 17 | content: page.content, 18 | embeds: [new EmbedBuilder().setTitle(page.embed)], 19 | }; 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /packages/pagination/images/discord-embed-pagination.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordx-ts/discordx/c3beb732777e61bf452ca4efff4d60904e7bd643/packages/pagination/images/discord-embed-pagination.jpg -------------------------------------------------------------------------------- /packages/pagination/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./pagination/index.js"; 8 | export * from "./utils/index.js"; 9 | -------------------------------------------------------------------------------- /packages/pagination/src/pagination/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./builder.js"; 8 | export * from "./pagination.js"; 9 | export * from "./resolver.js"; 10 | export * from "./types.js"; 11 | -------------------------------------------------------------------------------- /packages/pagination/src/pagination/resolver.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { Pagination, PaginationItem } from "./index.js"; 8 | 9 | export type Resolver = ( 10 | page: number, 11 | pagination: Pagination, 12 | ) => PaginationItem | Promise; 13 | 14 | export class PaginationResolver { 15 | constructor( 16 | public resolver: T, 17 | public maxLength: number, 18 | ) {} 19 | } 20 | -------------------------------------------------------------------------------- /packages/pagination/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./paginate.js"; 8 | -------------------------------------------------------------------------------- /packages/pagination/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "outDir": "build", 8 | "emitDecoratorMetadata": false, 9 | "experimentalDecorators": true, 10 | "strictNullChecks": true, 11 | "noUncheckedIndexedAccess": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "rootDir": "./", 14 | "moduleResolution": "Bundler", 15 | "esModuleInterop": true 16 | }, 17 | "exclude": ["node_modules", "tests", "examples"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "./current.js"; 9 | import "./gui.js"; 10 | import "./music.js"; 11 | import "./pause-resume.js"; 12 | import "./play.js"; 13 | import "./queue.js"; 14 | import "./seek.js"; 15 | import "./set-volume.js"; 16 | import "./shuffle.js"; 17 | import "./skip.js"; 18 | import "./stop.js"; 19 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/music.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Discord, SlashGroup } from "discordx"; 9 | 10 | @Discord() 11 | @SlashGroup({ description: "music", name: "music" }) 12 | export class Command { 13 | // 14 | } 15 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/queue.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { lavaPlayerManager } from "../core/manager.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "View queue", name: "queue" }) 17 | async queue(interaction: CommandInteraction): Promise { 18 | const cmd = await lavaPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | clearTimeout(cmd.autoDeleteTimer); 24 | const { queue } = cmd; 25 | await queue.view(interaction); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/set-volume.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { 9 | ApplicationCommandOptionType, 10 | type CommandInteraction, 11 | } from "discord.js"; 12 | import { Discord, Slash, SlashGroup, SlashOption } from "discordx"; 13 | 14 | import { lavaPlayerManager } from "../core/manager.js"; 15 | 16 | @Discord() 17 | @SlashGroup("music") 18 | export class Command { 19 | @Slash({ 20 | description: 21 | "The player volume, in percentage, from 0 to 1000 (default 100)", 22 | name: "set-volume", 23 | }) 24 | async setVolume( 25 | @SlashOption({ 26 | description: "Set volume", 27 | maxValue: 1000, 28 | minValue: 0, 29 | name: "volume", 30 | required: true, 31 | type: ApplicationCommandOptionType.Integer, 32 | }) 33 | volume: number, 34 | interaction: CommandInteraction, 35 | ): Promise { 36 | const cmd = await lavaPlayerManager.parseCommand(interaction); 37 | if (!cmd) { 38 | return; 39 | } 40 | 41 | const { queue } = cmd; 42 | await queue.setVolume(volume); 43 | await interaction.followUp({ 44 | content: `> volume set to ${String(volume)}`, 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/shuffle.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { lavaPlayerManager } from "../core/manager.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Shuffle queue", name: "shuffle" }) 17 | async shuffle(interaction: CommandInteraction): Promise { 18 | const cmd = await lavaPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | queue.shuffleTracks(); 25 | await interaction.followUp({ content: "> playlist shuffled!" }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/skip.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { lavaPlayerManager } from "../core/manager.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Skip current track", name: "skip" }) 17 | async skip(interaction: CommandInteraction): Promise { 18 | const cmd = await lavaPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | const currentTrack = queue.currentPlaybackTrack; 25 | if (!currentTrack) { 26 | await interaction.followUp({ 27 | content: "> There doesn't seem to be anything to skip at the moment.", 28 | }); 29 | return; 30 | } 31 | 32 | const next = await queue.playNext(); 33 | if (!next) { 34 | await queue.exit(); 35 | await interaction.followUp({ 36 | content: "> all queued up, amigo!", 37 | }); 38 | return; 39 | } 40 | 41 | await interaction.followUp({ 42 | content: `> Playing ${next.info.title}`, 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/commands/stop.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { lavaPlayerManager } from "../core/manager.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Stop music player", name: "stop" }) 17 | async stop(interaction: CommandInteraction): Promise { 18 | const cmd = await lavaPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | await queue.exit(); 25 | await interaction.followUp({ 26 | content: "> adios amigo, see you later!", 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/core/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | export * from "./manager.js"; 9 | export * from "./node.js"; 10 | export * from "./queue.js"; 11 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/events/ready.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { setTimeout as wait } from "node:timers/promises"; 9 | import { QueueManager } from "@discordx/lava-queue"; 10 | import type { Events } from "discord.js"; 11 | import { Discord, Once, type ArgsOf, type Client } from "discordx"; 12 | 13 | import { lavaPlayerManager } from "../core/manager.js"; 14 | import { getNode } from "../core/node.js"; 15 | 16 | @Discord() 17 | export class Command { 18 | @Once() 19 | async clientReady( 20 | _: ArgsOf, 21 | client: Client, 22 | ): Promise { 23 | await wait(5e3); 24 | lavaPlayerManager.instance = new QueueManager(getNode(client)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "./events/ready.js"; 9 | import "./commands/index.js"; 10 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/src/plugins/lavalyrics/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | export interface LyricsLine { 9 | /** 10 | * The duration of the line in milliseconds 11 | */ 12 | duration: number | null; 13 | /** 14 | * The lyrics line 15 | */ 16 | line: string; 17 | /** 18 | * Additional plugin specific data 19 | */ 20 | plugin: any; 21 | /** 22 | * The timestamp of the line in milliseconds 23 | */ 24 | timestamp: number; 25 | } 26 | 27 | export interface Lyrics { 28 | /** 29 | * The lyrics lines 30 | */ 31 | lines: LyricsLine[]; 32 | /** 33 | * Additional plugin specific data 34 | */ 35 | plugin: any; 36 | /** 37 | * The name of the provider the lyrics was fetched from on the source 38 | */ 39 | provider: string; 40 | /** 41 | * The name of the source where the lyrics were fetched from 42 | */ 43 | sourceName: string; 44 | /** 45 | * The lyrics text 46 | */ 47 | text: string | null; 48 | } 49 | -------------------------------------------------------------------------------- /packages/plugin-lava-player/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "outDir": "build", 8 | "emitDecoratorMetadata": false, 9 | "experimentalDecorators": true, 10 | "strictNullChecks": true, 11 | "noUncheckedIndexedAccess": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "moduleResolution": "Bundler", 14 | "esModuleInterop": true 15 | }, 16 | "exclude": ["node_modules", "tests", "examples"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "./current.js"; 9 | import "./gui.js"; 10 | import "./music.js"; 11 | import "./pause-resume.js"; 12 | import "./play.js"; 13 | import "./playlist.js"; 14 | import "./queue.js"; 15 | import "./seek.js"; 16 | import "./set-volume.js"; 17 | import "./shuffle.js"; 18 | import "./skip.js"; 19 | import "./spotify.js"; 20 | import "./stop.js"; 21 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/music.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Discord, SlashGroup } from "discordx"; 9 | 10 | @Discord() 11 | @SlashGroup({ description: "music", name: "music" }) 12 | export class Command { 13 | // 14 | } 15 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/queue.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { musicPlayerManager } from "../core/index.js"; 12 | import { showQueue } from "../utils/index.js"; 13 | 14 | @Discord() 15 | @SlashGroup("music") 16 | export class Command { 17 | @Slash({ description: "View queue", name: "queue" }) 18 | async queue(interaction: CommandInteraction): Promise { 19 | const cmd = await musicPlayerManager.parseCommand(interaction); 20 | if (!cmd) { 21 | return; 22 | } 23 | 24 | clearTimeout(cmd.autoDeleteTimer); 25 | const { queue } = cmd; 26 | await showQueue(queue, interaction); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/set-volume.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { 9 | ApplicationCommandOptionType, 10 | type CommandInteraction, 11 | } from "discord.js"; 12 | import { Discord, Slash, SlashGroup, SlashOption } from "discordx"; 13 | 14 | import { musicPlayerManager } from "../core/index.js"; 15 | 16 | @Discord() 17 | @SlashGroup("music") 18 | export class Command { 19 | @Slash({ 20 | description: 21 | "The player volume, in percentage, from 0 to 1000 (default 100)", 22 | name: "set-volume", 23 | }) 24 | async setVolume( 25 | @SlashOption({ 26 | description: "Set volume", 27 | maxValue: 1000, 28 | minValue: 0, 29 | name: "volume", 30 | required: true, 31 | type: ApplicationCommandOptionType.Integer, 32 | }) 33 | volume: number, 34 | interaction: CommandInteraction, 35 | ): Promise { 36 | const cmd = await musicPlayerManager.parseCommand(interaction); 37 | if (!cmd) { 38 | return; 39 | } 40 | 41 | const { queue } = cmd; 42 | queue.setVolume(volume); 43 | await interaction.followUp({ 44 | content: `> volume set to ${String(volume)}`, 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/shuffle.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { musicPlayerManager } from "../core/index.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Shuffle queue", name: "shuffle" }) 17 | async shuffle(interaction: CommandInteraction): Promise { 18 | const cmd = await musicPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | queue.shuffleTracks(); 25 | await interaction.followUp({ content: "> playlist shuffled!" }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/skip.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { musicPlayerManager } from "../core/index.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Skip current track", name: "skip" }) 17 | async skip(interaction: CommandInteraction): Promise { 18 | const cmd = await musicPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | const currentTrack = queue.currentPlaybackTrack; 25 | if (!currentTrack) { 26 | await interaction.followUp({ 27 | content: "> There doesn't seem to be anything to skip at the moment.", 28 | }); 29 | return; 30 | } 31 | 32 | const next = queue.playNext(); 33 | if (!next) { 34 | queue.exit(); 35 | await interaction.followUp({ 36 | content: "> all queued up, amigo!", 37 | }); 38 | return; 39 | } 40 | 41 | await interaction.followUp({ 42 | content: `> Playing ${next.title}`, 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/commands/stop.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import type { CommandInteraction } from "discord.js"; 9 | import { Discord, Slash, SlashGroup } from "discordx"; 10 | 11 | import { musicPlayerManager } from "../core/index.js"; 12 | 13 | @Discord() 14 | @SlashGroup("music") 15 | export class Command { 16 | @Slash({ description: "Stop music player", name: "stop" }) 17 | async stop(interaction: CommandInteraction): Promise { 18 | const cmd = await musicPlayerManager.parseCommand(interaction); 19 | if (!cmd) { 20 | return; 21 | } 22 | 23 | const { queue } = cmd; 24 | queue.exit(); 25 | await interaction.followUp({ 26 | content: "> adios amigo, see you later!", 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/core/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | export * from "./manager.js"; 9 | export * from "./queue.js"; 10 | export type * from "./types.js"; 11 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/core/types.ts: -------------------------------------------------------------------------------- 1 | import type { Track } from "@discordx/music"; 2 | import type { PartialGroupDMChannel, TextBasedChannel, User } from "discord.js"; 3 | 4 | export interface MyTrack extends Track { 5 | duration: number; 6 | thumbnail?: string; 7 | title: string; 8 | user: User; 9 | } 10 | 11 | export type TrackChannel = Exclude; 12 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/events/ready.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Node, QueueManager } from "@discordx/music"; 9 | import type { Events } from "discord.js"; 10 | import { Discord, Once, type ArgsOf, type Client } from "discordx"; 11 | 12 | import { musicPlayerManager } from "../core/manager.js"; 13 | 14 | @Discord() 15 | export class Command { 16 | @Once() 17 | clientReady(_: ArgsOf, client: Client): void { 18 | const node = new Node(client); 19 | musicPlayerManager.instance = new QueueManager(node); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/global.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | interface SpotifyTrack { 9 | artist: string; 10 | duration: number; 11 | name: string; 12 | previewUrl: string; 13 | uri: string; 14 | } 15 | 16 | interface Spotify { 17 | getTracks: (url: string) => Promise; 18 | } 19 | 20 | declare module "spotify-url-info" { 21 | function spotify(fetch: any): Spotify; 22 | export = spotify; 23 | } 24 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "./events/ready.js"; 9 | import "./commands/index.js"; 10 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./message.js"; 2 | export * from "./queue.js"; 3 | export * from "./time.js"; 4 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/utils/message.ts: -------------------------------------------------------------------------------- 1 | import type { Message } from "discord.js"; 2 | 3 | export async function deleteMessage(message: Message): Promise { 4 | if (!message.deletable) { 5 | return null; 6 | } 7 | 8 | return await message.delete().catch(() => null); 9 | } 10 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/src/utils/time.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | export function fromMS(duration: number): string { 9 | const seconds = Math.floor((duration / 1e3) % 60); 10 | const minutes = Math.floor((duration / 6e4) % 60); 11 | const hours = Math.floor(duration / 36e5); 12 | const secondsPad = seconds.toString().padStart(2, "0"); 13 | const minutesPad = minutes.toString().padStart(2, "0"); 14 | const hoursPad = hours.toString().padStart(2, "0"); 15 | return `${hours ? `${hoursPad}:` : ""}${minutesPad}:${secondsPad}`; 16 | } 17 | 18 | export function toMS(duration: string): number { 19 | const parts = duration.split(":").map(parseFloat); 20 | if (parts.some(Number.isNaN)) { 21 | throw new Error(`Invalid duration format: "${duration}"`); 22 | } 23 | 24 | // Calculate total seconds (supports hh:mm:ss, mm:ss, or ss) 25 | const seconds = parts.reduce((total, value) => total * 60 + value, 0); 26 | 27 | return Math.round(seconds * 1000); 28 | } 29 | -------------------------------------------------------------------------------- /packages/plugin-ytdl-player/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/utilities/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Please report vulnerabilities via github issues, with the prefix starting with `SECURITY:`. If possible, please submit a PR for the fix. 14 | -------------------------------------------------------------------------------- /packages/utilities/examples/category/commands/group.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { Category, type ICategory } from "@discordx/utilities"; 8 | import type { CommandInteraction } from "discord.js"; 9 | import { 10 | Discord, 11 | MetadataStorage, 12 | Slash, 13 | SlashGroup, 14 | type DApplicationCommand, 15 | } from "discordx"; 16 | 17 | @Discord() 18 | @Category("Admin Commands") 19 | @SlashGroup({ description: "my-group", name: "my-group" }) 20 | @SlashGroup("my-group") 21 | export class SlashExample { 22 | @Slash({ description: "subgroup" }) 23 | async subgroup(interaction: CommandInteraction): Promise { 24 | await interaction.deferReply(); 25 | 26 | MetadataStorage.instance.applicationCommandSlashesFlat.forEach( 27 | (cmd: DApplicationCommand & ICategory) => { 28 | void interaction.followUp( 29 | `Name: \`${cmd.name}\`, Category: \`${cmd.category ?? "unknown"}\``, 30 | ); 31 | }, 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/utilities/examples/category/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "noUncheckedIndexedAccess": true, 8 | "outDir": "dist", 9 | "emitDecoratorMetadata": false, 10 | "experimentalDecorators": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "moduleResolution": "Bundler", 13 | "esModuleInterop": true 14 | }, 15 | "exclude": ["node_modules", "tests", "examples"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/utilities/examples/guards/commands/IsGuildUser.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { type IsGuardUserCallback, IsGuildUser } from "@discordx/utilities"; 8 | import { Events } from "discord.js"; 9 | import { 10 | type ArgsOf, 11 | Discord, 12 | Guard, 13 | On, 14 | SimpleCommand, 15 | type SimpleCommandMessage, 16 | } from "discordx"; 17 | 18 | const OwnerOnly: IsGuardUserCallback = ({ client, user }) => { 19 | if (!user) { 20 | return false; 21 | } 22 | 23 | return client.application?.owner?.id === user.id; 24 | }; 25 | 26 | @Discord() 27 | @Guard(IsGuildUser(OwnerOnly)) 28 | export class Example { 29 | @On({ event: Events.MessageCreate }) 30 | message([_message]: ArgsOf) { 31 | //... 32 | } 33 | 34 | @SimpleCommand({ name: "wave" }) 35 | wave(_command: SimpleCommandMessage) { 36 | //... 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/utilities/examples/guards/commands/NotBot.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { NotBot } from "@discordx/utilities"; 8 | import { Events } from "discord.js"; 9 | import { 10 | type ArgsOf, 11 | Discord, 12 | Guard, 13 | On, 14 | SimpleCommand, 15 | type SimpleCommandMessage, 16 | } from "discordx"; 17 | 18 | @Discord() 19 | @Guard(NotBot) 20 | export class Example { 21 | @On({ event: Events.MessageCreate }) 22 | message([_message]: ArgsOf) { 23 | //... 24 | } 25 | 26 | @SimpleCommand({ name: "hello" }) 27 | hello(_command: SimpleCommandMessage) { 28 | //... 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/utilities/examples/guards/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "noUncheckedIndexedAccess": true, 8 | "outDir": "dist", 9 | "emitDecoratorMetadata": false, 10 | "experimentalDecorators": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "moduleResolution": "Bundler", 13 | "esModuleInterop": true 14 | }, 15 | "exclude": ["node_modules", "tests", "examples"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/utilities/src/decorators/description.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { 8 | DApplicationCommand, 9 | DSimpleCommand, 10 | MetadataStorage, 11 | type MethodDecoratorEx, 12 | Modifier, 13 | } from "discordx"; 14 | 15 | export function Description(description: string): MethodDecoratorEx { 16 | return (target, key, descriptor?: PropertyDescriptor) => { 17 | MetadataStorage.instance.addModifier( 18 | Modifier.create( 19 | (original: DApplicationCommand | DSimpleCommand) => { 20 | original.description = description; 21 | }, 22 | DApplicationCommand, 23 | DSimpleCommand, 24 | ).attachToTarget(target, key, descriptor), 25 | ); 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /packages/utilities/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./category.js"; 8 | export * from "./description.js"; 9 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/NotBot/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import { IsGuildUser } from "../IsGuildUser/index.js"; 8 | 9 | /** 10 | * Guard to prevent bot from executing discordx methods 11 | */ 12 | export const NotBot = IsGuildUser(({ user }) => !user?.bot); 13 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export { TimedSet } from "./logic/index.js"; 8 | export * from "./RateLimit.js"; 9 | export * from "./types/index.js"; 10 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/logic/TimeOutEntry.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export class TimeOutEntry { 8 | private _currentCallAmount = 0; 9 | 10 | public constructor( 11 | public userId: string, 12 | public guildId: string, 13 | private _rateValue = 1, 14 | ) { 15 | this._currentCallAmount++; 16 | } 17 | 18 | public hasLimitReached(): boolean { 19 | return !(this._currentCallAmount <= this._rateValue); 20 | } 21 | 22 | public incrementCallCount(): void { 23 | this._currentCallAmount++; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/logic/Timer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export class Timer { 8 | public id: NodeJS.Timeout; 9 | private _whenWillExecute: number; 10 | 11 | public constructor(callback: (...args: unknown[]) => void, delay: number) { 12 | this._whenWillExecute = Date.now() + delay; 13 | this.id = setTimeout(callback, delay); 14 | } 15 | 16 | public get timeLeft(): number { 17 | return this._whenWillExecute - Date.now(); 18 | } 19 | 20 | public clearTimer(): void { 21 | clearTimeout(this.id); 22 | this._whenWillExecute = -1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/logic/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./TimedSet.js"; 8 | export * from "./TimeOutEntry.js"; 9 | export * from "./Timer.js"; 10 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/types/ITimedSet.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | /** 8 | * A set like object that evicts entries from the set after they have been in there for the set time 9 | */ 10 | export interface ITimedSet { 11 | /** 12 | * Get the time left until this item is removed from the set 13 | */ 14 | getTimeRemaining(key: T): number; 15 | 16 | /** 17 | * checks if this set is empty 18 | */ 19 | isEmpty(): boolean; 20 | 21 | /** 22 | * Refresh the timeout for this element (resets the timer for the items eviction) 23 | * 24 | * @param key - Key 25 | */ 26 | refresh(key: T): boolean; 27 | } 28 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/types/common.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { CommandInteraction } from "discord.js"; 8 | import type { Awaitable, SimpleCommandMessage } from "discordx"; 9 | 10 | export interface RateLimitOption< 11 | T extends CommandInteraction | SimpleCommandMessage, 12 | > { 13 | /** 14 | * for interaction only 15 | */ 16 | ephemeral?: boolean; 17 | /** 18 | * the message to post when a command is called when the 19 | * user is in rate limit, defaults = "message being rate limited!, please try again at {time}". 20 | * use the placeholder {time} in your string to get the time you can next call it `` 21 | * If a function is supplied, it will pass both the interaction and how many milliseconds are left until the rate limit is over 22 | */ 23 | message?: ((interaction: T, timeLeft: number) => Awaitable) | string; 24 | /** 25 | * the value to specify how many messages can be called before it is rate limited, defaults to 1 26 | */ 27 | rateValue?: number; 28 | } 29 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/types/enum.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export enum TIME_UNIT { 8 | days, 9 | hours, 10 | minutes, 11 | seconds, 12 | } 13 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/Rate Limiter/types/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export type * from "./common.js"; 8 | export * from "./enum.js"; 9 | export type * from "./ITimedSet.js"; 10 | -------------------------------------------------------------------------------- /packages/utilities/src/guards/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./IsGuildUser/index.js"; 8 | export * from "./NotBot/index.js"; 9 | export * from "./PermissionGuard/index.js"; 10 | export * from "./Rate Limiter/index.js"; 11 | -------------------------------------------------------------------------------- /packages/utilities/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | // guards 8 | export * from "./guards/index.js"; 9 | 10 | // decorators 11 | export * from "./decorators/index.js"; 12 | 13 | // useful 14 | export * from "./useful/index.js"; 15 | -------------------------------------------------------------------------------- /packages/utilities/src/useful/enum.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | import type { SlashChoiceType } from "discordx"; 8 | 9 | export function EnumChoice( 10 | choices: Record, 11 | ): SlashChoiceType[] { 12 | return Object.keys(choices).map((key) => ({ 13 | name: key, 14 | value: choices[key], 15 | })); 16 | } 17 | -------------------------------------------------------------------------------- /packages/utilities/src/useful/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Copyright (c) Vijay Meena (https://github.com/vijayymmeena). All rights reserved. 4 | * Licensed under the Apache License. See License.txt in the project root for license information. 5 | * ------------------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "./enum.js"; 8 | export * from "./time-format.js"; 9 | -------------------------------------------------------------------------------- /packages/utilities/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "rootDir": "src", 11 | "outDir": "dist", 12 | "emitDecoratorMetadata": false, 13 | "experimentalDecorators": true, 14 | "declaration": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Bundler", 17 | "esModuleInterop": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["examples", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - packages/*/examples/** 4 | - docs 5 | 6 | onlyBuiltDependencies: 7 | - core-js 8 | - core-js-pure 9 | - esbuild 10 | - ffmpeg-static 11 | - unrs-resolver 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "noImplicitAny": true, 6 | "sourceMap": true, 7 | "strict": true, 8 | "strictNullChecks": true, 9 | "noUncheckedIndexedAccess": true, 10 | "emitDecoratorMetadata": false, 11 | "experimentalDecorators": true, 12 | "declaration": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "moduleResolution": "Node", 15 | "esModuleInterop": true 16 | }, 17 | "exclude": [] 18 | } 19 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "tasks": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**"] 7 | }, 8 | "build:typedoc": { 9 | "dependsOn": ["^build"], 10 | "cache": false 11 | }, 12 | "test": { 13 | "dependsOn": ["^build"], 14 | "cache": false 15 | } 16 | } 17 | } 18 | --------------------------------------------------------------------------------