BREAKING: node migration + major improvements and style changes (#2783)

* Setup turborepo (#2610)

* chore: BREAKING move to monorepo structure

* chore: setup turborepo

* setup more eslint and tsconfig (#2612)

* fix packages setting lcoation

* add dist to ignore

* style

* fix: .vscode set prettier and remove deno configs (#2611)

* fix: rewrite to process.env

* chore: add node types

* style: run eslint --fix

* fix: tests import ext

* chore: fix formatter

* chore: add build script

* chore: remove site from turborepo

* chore: move to seperate packages

* chore: seperate util

* chore: rename to index

* fix: utils

* chore: bump typescript

* fix: in process of fixing rest

* fix: logger

* style

* chore: fix turbo script

* fix: types

* fix: types

* fix: shard

* fix: gateway

* fixing: bot

* fix: at least it can run now

* chore: fix turbo script

* chore: move plugins

* chore: add type and utils export

* chore: working bot type and cache plugin

* Add git hooks (#2618)

* CI: Setup ci (#2669)

* ci: fix test

* ci: fix typo

* fix: turbo script

* fixes: yarn and linter errors in embeds pkg

* chore: fix yarn gitignore

* Node migration - devcontainer (#2672)

*  - feat: devcontainer -> node

* 👷‍♂ - ci: devcontainer - add tabnine, prettier

* fix: ignore .env and debug.ts

* fix: couple of linter errors

* fix: linter error

* fix: gateway linter errors

* style: update style

* style: fix bot style

* fix: type

* ci: move all old workflow

* chore: close #2619

* chore: close #2671

* test: add mocha

* chore: add typescript plugin

* test: add mocha

* test: add test to utils

* test/ci: update ci and coverage

* chore: change script naming

* ci: update include test

* test: add coverage

* ci: fix cache

* ci: fix ci and codecov

* Discordeno Documentation  (#2673)

* Add git hooks

* Add documentation generatation

* Change Documentation Engine

* Add documentation

* Remove autogenerated docs

* combine lint staged action into one

* style: fix

Co-authored-by: H01001000 <heiheiho000@gmail.com>

* chore: new package client

* test: add rest test

* ci: enable codecov

* fix: type

* test: add test to all packages

* ci: add release to gh per commit

* fix: ci syntax

* fix: package version

* fix: publish script

* fix: remove private from gateway

* ci: add filter for changes

* fix: ci syntex

* ci: try fix path filter

* ci: try fix path filter

* test: add test

* ci: fix string and  boolean

* fix: package and ci

* chore: fix turbo type cache

* ci: also publish to npm

* ci: change to public

* fix: not publish to npm

* fix: dependencies

* chore: fix fmt script

* fix: better rest typecheck Closes #2621

* fix: run yarn install

* feat: add transformers to rest

* feat: add helpers to rest

* test: move bot utils test

* reverse change to release.yml

* chore: add clean build

* refactor: discordeno

* chore: add import type

* chore: remove bot

* fix: change deps from bot to dd

* chore: update yarn lock

* test: temp remove test from logger

* refactor: remove transformers in helpers/channel

* type: close #2622

* ci(fix): explicitly define coverage file

* refactor: remove transformers in helpers/emoji

* type: fix discord guild type

* feat: DiscordEditAutomoderationRule type

* fix: remove unused type

* feat: DiscordCreateGuildEmoji DiscordModifyGuildEmoji & DiscordModifyCHannel types

* feat: DiscordCreateChannel DiscordBuDeleteMessages DiscordCreateMessage DiscordEditMessage

* feat: DiscordCreateScheduledEvent EditScheduledEvent DiscordCreateInvite

* fix: types for guild stuff for rest

* feat: thread discord types for rest

* feat: channel rest types

* feat: member rest types

* feat: more discord rest types

* fix: type errors

* fix: docs bot param name should be rest

* type: fix type error

* ci(fix): codecov

* chore(client) :add export transformer

* fix: verifySignature

* test: fix types

* test: add test prevent #2683 #2678

* fix: export transformer twice

* ci: reuse cache

* test: add test:unit-noTextCoverage

* feat: add transform and constant package

* fix: half fix #2683 #2688

* fix: #2688 fix all transformer.spec.ts

* fix: transformer name

* ci: update style

* fix: dependencies

* fix: naming

* fix: yarn lock

* fix: remove validations from helpers. Closes #2700

* fix: rest routes as a constants pkg

* fix: esm import with .js

* test: add exception case

* feat: adding transformer

* chore: change script name

* chore: add path fixing to coverage file

* fix: camelize tuple bug

* fix: reverse transformers

* fix: transformers folder to camel

* fix: transformers as an object

* fix: linter error

* ci: run test with deno close #2701

* fix: test depends on build

* fix: deno import node:crypto

* fix: rest improvements

* fix: channel type

* fix: export user

* chore: move to unit dir

* test: moving bench

* fix: remove transformers from rest package

* fix: move toggle transformers to bot pkg

* fix: move out gw helpers to gw package

* test: add rest e2e test

* fix: syntex

* ci: add discord token

* fix: ci not passing secret

* test: add role test

* ci: fix secret inherit

* fix: role helpers transformer

* test: increase timeout to 10s

* fix: member helpers transformer

* test: add member test

* fix: name and type

* fix: guild ban

* test: fix test

* fix: test add await

* test: skip some test

* test: increase timeout

* chore: add transformer to import map

* fix: test

* test: add why-is-node-still-running

* test: add debug hook

* ci: add timeout incase any async running

* test: try fix

* test: turn on rest debug

* fix: if undefined

* test: reduce timeout

* fix: queue not running after some request

* fix: increase remaining after request without ratelimit header

* fix: partial webhook

* fix: fetch hooks not working if debug defined later

* fix: nickname null to undefined

* test: finish adding webhook test

* refactor(test): move rest to utils

* fix: add await

* fix: sticker

* feat: add message embed component transformer

* fix: test not done

* fix: arg type to bigString

* fix: sendMessage

* fix: add allowedMentions, interactionResponse

* test: add emoji e2e test

* test: add guild e2e test

* refactor(test): remove extra rest call

* fix: create emoji BINARY_TYPE_INVALID_DATA_URI

* fix: create guild rate limit

* fix: automode rule helpers and test

* fix: test run in only

* test: add some queue bucket test

* test: remove empty test

* refactor(test): use new guild

* test: use new guild for other test

* fix: guild not defind

* reactor(test): remove duplicated creat channel

* test: increase timeout to 30s

* test: add thread test

* fix: more transformers

* fix: gateway helpers use transformers

* fix: types belong in types pkg

* fix: helpers use transformers

* BREAKING: v19 rewrite to node + major improvements (#2703)

* fix: move all to old folder

* fix: cleanup types

* fix: more cleanup

* fix: more base cleanup

* fix: token dotenv

* fix: add base transformer

* fix: partial error handling

* fix: handle 429 rate limit

* test(rest): fix unit test

* fix(script): transform extension

* test: fix error and buffer

* feat: camelizer util

* fix: cleanup

* fix: rate limit queues and headers processing

* fix: rest exports

* fix: no more transformers

* fix: queue header null bug

* fix: add gateway package base

* fix: lint error

* fix: add prettier file

* fix: prettier is default fmtr

* fix: fmt shard file

* fix: fmt

* fix: types issue

* fix: remove unused consts

* fix: all import issues

* fix: import error

* fix: import ending with .js

* fix: remove transformers package

* Fix eslint (#2710)

* fix: typing of button component label to be optional (#2708)

* feat: add guild_connections to role tags and toggles (#2706)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* Add lint checks and autofixing workflow (#2702)

* Add lint checks and autofixing workflow

* Update lint.yml

* Fix: use yarn instead npm

* fix: add ts to eslint_extensions

* fix: update dir

* fix: lint.yml format

Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>

* fix: unused deps

* ci: fix e2e test not running

* chore: run yarn install

* test: this should run test

* feat: getCHannel

* feat: createEMji helper

* feat: collection class in util package

* fix: gateway bugs

* why on earth is this needed change

* fix: cleanup docs on collection

* Emoji rest methods (node-migration-clean) (#2713)

* feat: all emoji rest methods

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: stuff

* fix: bot types

* fix: remove logs

* fix: camelize all gateway payloads

* fix: remove todos

* fix: start deris

* fix: lint/ts errors except shard file

* thats 1 way to fix type errors

* yes (#2714)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* feat: rest channel helpers

* Update release.yml

* Update release.yml

* ci: add build filter

* ci: fail fast false

* fix: complete webhook related helpers

* fix: follow announcement helper

* add forum helper

* add stage helpers

* add thread related helpers

* alphabetize

* cleanup webhook routes

* automod helpers

* scheduled events

* integrations helpers

* invite stuff incomplete

* dm channel and avatar url

* chore: move ts-node into package

* fix: importing esm

* fix: tris message helpers

* test(rest): add simplifyUrl test

* test(rest): add checkRateLimits test

* test(rest): add processRateLimitedPaths test

* test(rest): fix missing beforeEach

* test(utils): enable old test

* interaction helpers

* perf(utils): optimize snake to camel case conversion (#2717)

* perf(utils): optimize snake to camel case conversion

* fmt

* wont change much but still faster

* actually this was a stupid idea

* shh

* Fix(client): Fix typings. (#2716)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* test: fix rest and utils test (#2723)

* test(utils): fix  cant import collection

* test(rest): await expect

* fix(utils): deno compactability

* test(utils): typing

* fix(utils): add return type

* Add rest helpers for templates (#2727)

* Add rest helpers for templates

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: remove frozenAt

* fix: cleanup templates

* ci: release to npm (#2725)

* ci: release to npm

* Update release.yml

* 🐛 - fix: types - slashcommands - add nsfw prop (#2731)

* feat(rest helpers): Add template and member helpers. (#2728)

* feat(rest helpers): Add template and member helpers.

* format code

* feat(rest): add template routes

* fix(rest): routes and runMethod

* fix(rest): try to fix most of type

Co-authored-by: H01001000 <heiheiho000@gmail.com>
Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* ci: fix release (#2732)

* fix: rest type errors

* fix: v19 begin

* fix: yarn lock

* chore: fix deps and script (#2733)

* fix: bug camelizer deleting letters

* fix: falsy token check

* fix: add frozenat check for queue

* fix: max stack trace error do to infinite loop

* fix: type error

* test(rest): fix missing import (#2734)

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* fix: file paths for imports

* fix: lastShardId should default to 0

* fix: use isomorphic ws

* test(rest): fix "TypeError: [Function] is not a thenable" (#2736)

* test(utils): add utils tests (#2737)

* test(utils): add urltobase64 test

* test(utils): add token test

* test(utils): fix missing import buffer

* test(utils): add casting test

* test(utils): add casting test

* test(utils): fix use correct function

* chore: make eslint error if missing .js extension (#2735)

* chore: eslint error if missing .js extension

* chore

* lint: fix missing .js error

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* fix: readme runtime list (#2739)

* Bot pkg (#2740)

* fix: bot pkg test

* Fix code style issues with ESLint

* Update Guild.ts

* Update Guild.ts

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>

* Update tsdoc.json (#2741)

Updates tsdoc.json to reflect the current packages.

* Interaction types - remove member,channel,role from value type (#2743)

https://discord.com/channels/785384884197392384/1067265182776176690/1068189883073572924

* Add missing types (#2742)

* Revert "fix: use isomorphic ws" (#2744)

This reverts commit ad306b0d0a.

* fix: interaction requests that sent without full url

* fix: lint issues

* fix: remote gateway test file

* fix: interaction response bug with body being invalid (#2746)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: interaction followup type (#2747)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: e2e exit bug (#2748)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: rest sending attachments files (#2749)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: guild and role methods (#2751)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* ci: add bot package (#2752)

* ci: add bot package

* ci: fix test

* e2e test stuff (#2754)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: delete guilds test (#2758)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore: fix deps (#2757)

* ci/test: fix bot pkg e2e test (#2759)

* chore: fix script and update import map (#2761)

* chore: fix version script

* chore: update import map

* chore: fix ws import map

* chore: fix deno import map

* test: fix

* fix: more rest e2e tests (#2763)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

* fix: easier to provide custom intents in bot

* fix: shutdown bot after test

* fix: add getGuild

* fix: multiple guild delete attempts

* fix: add emoji e2e tests

* fix: remaining old e2e rest tests

* Fix code style issues with ESLint

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* test: add gateway integration test (#2756)

* test: add gateway integration test

* test(gateway): fix connection test

* test(gateway): add heartbeat test

* ci: add integration test

* fix: add uWebSockets.js

* ci: add timeout

* test(utils): remove old test

* Revert "test(utils): remove old test"

This reverts commit 04fb6dd4b5.

* test(gateway): fix uws server

* test(gateway): fix type

* chore: update codecov flag

* test(gateway): remove dev code

---------

Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com>

* Update release.yml (#2768)

* fix: bot logger (#2769)

* fix: readme runtime list

* Fix code style issues with ESLint

* node 18

* fix: websocket import type

* fix: body for interaction requests

* fix: perma fix for type error in ci

* fix: followupmessage option type

* fix: e2e tests exit bug

* fix: color console logger

* fix: image file sending

* Fix code style issues with ESLint

* guild and role methods

* Fix code style issues with ESLint

* fix: dont send heartbeat if socket is not open

* fix: remove logs

* fox: remove more logs

* fix some bugs in role tests

* Switch to after hook style

* hoti's speed snaker

* auto convert objects for discord

* Fix code style issues with ESLint

* fix: remove dup imports

* fix: i hate linters

* speeder

* fix: tests delete guilds

* Fix code style issues with ESLint

* fix: easier to provide custom intents in bot

* fix: shutdown bot after test

* fix: add getGuild

* fix: multiple guild delete attempts

* fix: add emoji e2e tests

* fix: remaining old e2e rest tests

* Fix code style issues with ESLint

* fix: add bot.logger

* fix: make logger name capital

---------

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore: update readme (#2772)

* chore: add coverage per pkg

* chore: add npm version

* chore: add test status

* chore: fix ci

* chore: fix ci

* ci: fix ci needs

* chore: add only push event

* style: remove import logger

* 📚 - docs: fix README package links (#2773)

* test(all): add test importing index (#2774)

* test(all): add test importing index

* chore: remove old benchmark dir

* chore: disable coverage status fail

* test(client): add import test with try catch

* test(rest): fix narrow import scope

* test(utils): add test (#2764)

* test(utils): remove old test

* test(utils): add color test

* test(utils): fix import mocha

* test(utils): fix test type error

* test(utils): remove dev code

* fix(utils): bucket not export all function

* test(utils): add some test for bucket

* fix(utils): close #2775

* test(utils): add test for permissions.ts

* test(utils): fix missing mocha import

* fix(utils): better fix for #2775

* feat: addReaction & addReactions

* feat: connectToVoice

* fix: linters issues

* fix: remove aliases and add createGuildFromTemplate

* feat: deleteMessages

* fix: reaction related helpers

* mfa level

* voie states editing

* image urls

* fix: typos

* get message typeguards

* fix: more helpers

* fix: remaining helpers

* fix: add logs to gateway manager

* fix: rest resolve sends status and body

* fix: lots of errors

* fix: client errors

* fix: remove old pkg

* snaker

* fix: broken util import for image url

* fix: cleanup shard and circular deps

* fix: remove ThreadChannel from GuildChannel

* fix: generate interaction usage

* fix: more bugs

* fix: use node:events to import

* fix(rest): add interface RestRequestRejection (#2782)

* fix: remove invalid todo

* fix: timeout bug

---------

Co-authored-by: Skillz <skillz@discord.gg/ddeno>
Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>
Co-authored-by: deepsarda <92147339+deepsarda@users.noreply.github.com>
Co-authored-by: Awesome Stickz <awesome@stickz.dev>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Lars_und_so <46791248+Larsundso@users.noreply.github.com>
Co-authored-by: ITOH <to@itoh.at>
Co-authored-by: Yaikava <83710104+Yaikava@users.noreply.github.com>
Co-authored-by: Andreas Fink <mail@afink.dev>

---------

Co-authored-by: Jonathan Ho <48591478+H01001000@users.noreply.github.com>
Co-authored-by: H01001000 <heiheiho000@gmail.com>
Co-authored-by: deepsarda <92147339+deepsarda@users.noreply.github.com>
Co-authored-by: Yaikava <83710104+Yaikava@users.noreply.github.com>
Co-authored-by: Skillz <skillz@discord.gg/ddeno>
Co-authored-by: Awesome Stickz <awesome@stickz.dev>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Lars_und_so <46791248+Larsundso@users.noreply.github.com>
Co-authored-by: ITOH <to@itoh.at>
Co-authored-by: Andreas Fink <mail@afink.dev>
This commit is contained in:
Skillz4Killz
2023-02-20 15:00:00 -06:00
committed by GitHub
parent 1a717ddc7d
commit 2714e1e7d1
1057 changed files with 53134 additions and 55520 deletions

View File

@@ -1,4 +0,0 @@
{
"label": "Command Handler",
"position": 9
}

View File

@@ -1,92 +0,0 @@
---
sidebar_position: 2
---
# Command Manager
Currently, you probably have something like this in your code:
```js
const Discord = require("discordeno.js");
// Ideally you should move to an `.env` file
const config = require("./config.json");
const bot = Discord.createBot({
events: {
messageCreate(client, message) {
if (message.content === "!ping") {
client.helpers.sendMessage(message.channelId, { content: "pong" });
}
},
},
intents: Discord.Intents.Guilds | Discord.Intents.GuildMessages,
token: config.token,
});
const client = Discord.enableCachePlugin(bot, {});
Discord.startBot(client);
```
Of course, if you add more and more commands and as your code base grows, you can lose track very quickly.
To avoid this, it is recommended to store the commands in separate folders divided into different categories.
[Previously, we introduced you to our plugin structure, which has a lot of advantages.](../design.md)
```root
├Plugins/
├── General/
│ ├── commands/
│ │ ├── ping.js
│ │ └── ...
├── Developer/
│ ├── commands/
│ │ ├── eval.js
│ │ └── ...
└── ...
```
**Get [this file](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/CommandManager.js) from
the [nodejs template](https://github.com/discordeno/discordeno/tree/main/template)**
```js
const CommandManager = require("./template/Managers/CommandManager.js");
const manager = new CommandManager({});
manager.load({ plugin: true }); // Load the commands
client.commands = manager;
client.commands.cache.get("ping"); // Get the `ping` command
```
The Manager will automatically iterate through all files in the folder and then load them into the cache property, which
is mapped on the command name.
**Take a look at [Create Command](./create-command.md) to learn how to create a command.**
## Handle Command
The manager also contains a handler for executing the command when a message is received.
:::important
Currently checks for permissions, cooldowns, and rate limits are not covered, but these will be added soon.
:::
### Message Create Event:
```js
module.exports = async (client, message) => {
client.commands.isCommand(message);
};
```
### Interaction Create Event:
```js
module.exports = async (client, interaction) => {
client.commands.isInteraction(interaction);
};
```
You can also customize the `isCommand` function to your use case.

View File

@@ -1,61 +0,0 @@
---
sidebar_position: 3
---
# Create Command
One of the most important features we wanted in our template, was that you can use the same code for handling
`slash commands` and `message based commands`.
This can be done by saving the static class in the command cache, creating a constructor and passing the desired data.
Moreover the `BaseCommand` is extended with the `Response Command` class, so you can take advantage of functions such as
`.reply()`
**Copy the [`BaseCommand`](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures/BaseCommand.js)
&
[`CommandResponses`](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures/CommandResponses.js)
code from the template**
### Creating a Ping Command:
```js
const BaseCommand = require("../../../Structures/BaseCommand.js");
const Embed = require("../../../Structures/Embed.js");
class pingCommand extends BaseCommand {
static name = "ping";
static description = "See if the bot latency is okay";
static usage = "";
static category = "General";
static slash = { name: "ping", category: "info" };
constructor(data) {
super(data);
}
async execute() {
const msg = await this.reply({content: `Pinging...`});
// Assign properties to the response
const ping = msg.timestamp - this.message.timestamp;
const embed = new Embed()
.setTitle(`The Bots ping is ${ping} ms`)
.toJSON();
// Edit Message with the Embed
return await msg.edit({embeds: [embed] });
});
}
}
module.exports = pingCommand;
```
- The `BaseCommand` is extended with the `CommandResponses` class.
- The ping command class is extended with the `BaseCommand` class.
- Some static properties are assigned to the ping command class, in order to access it in the cache, such as `name`,
`description`, `usage`, `category` and `slash`...
- The `execute()` function will be called, when the command has been run by the user.
- The constructor allows to access data, such as `this.message`, `this.args`, `this.client`...
You can customize the `CommandManager` file, in order to pass arguments in the `execute()` function.

View File

@@ -1,22 +0,0 @@
---
sidebar_position: 1
---
# Getting Started with the Command Manager
One of the most important characteristics of bots is that they have commands that can be used to interact with the bot.
Hard coding your commands in an event function is not the best code practice and should be strictly prevented.
In the following we will show you how to create a command manager, which is compatible with Discordeno's Client.
- Load Commands
- Handle Commands
- Reload Commands
:::info template
You can also copy the
[`CommandManager` from the template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/CommandManager.js).
:::

View File

@@ -1,4 +0,0 @@
{
"label": "Event Handler",
"position": 8
}

View File

@@ -1,119 +0,0 @@
---
sidebar_position: 2
---
# Create Event Manager
In order to process certain events, you must provide the Discordeno client with functions for these events.
```js
const Discord = require("discordeno");
const config = require("./config.json");
const client = Discord.createBot({
events: {
ready(client, payload) {
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
},
async messageCreate(client, message) {
if (message.content === "!ping") {
await client.helpers.sendMessage(message.channelId, { content: "pong" });
}
console.log(`Received message: ${message.content || message.embeds}`);
},
},
intents: ["Guilds", "GuildMessages"],
token: config.token,
});
Discord.startBot(client);
```
As you listen to more and more events, the functions code grows along with them, so you can quickly lose track.
To avoid this, we recommend storing the event functions divided into files in a separate folder.
## Create Event Folder
Create a folder called `events` in your project folder.
:::info note
The event files have to be named using camelCase so that they can be understood by the client. e.g `message` ->
`messageCreate.js`. You can check the typings see how the events are called.
:::
Ready Event:
```js
module.exports = (client, payload) => {
if (payload.shardId + 1 === client.gateway.maxShards) {
// All Shards are ready
console.log(`Successfully connected to the gateway as ${payload.user.username}#${payload.user.discriminator}`);
}
};
```
## Load your Events
```js
const fs = require("fs");
const path = require("path");
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
class EventManager {
constructor(client) {
this.cache = new Map();
this._events = {};
}
load(options = {}) {
const eventsFolder = resolveFolder("../events");
fs.readdirSync(eventsFolder).map(async (file) => {
if (!file.endsWith(".js")) return;
const fileName = path.join(eventsFolder, file);
const event = require(fileName);
const eventName = file.split(".")[0];
this._events[`${eventName}`] = event;
});
return this._events;
}
}
module.exports = EventManager;
```
The code above, which can also be found in the
[template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/EventManager.js) will loop
through all the files in the `events` folder and load the functions into the `_events` object.
In order to let the client know which events should be processed, you need to pass the functions in the
`createBot<options>.events` object.
```js
const Discord = require("discordeno");
const config = require("./config.json");
const EventManager = require("./Managers/EventManager.js");
const events = new EventManager({});
const client = Discord.createBot({
events: events.load({}),
intents: ["Guilds", "GuildMessages"],
token: config.token,
});
Discord.startBot(client);
```
Moreover, you can customize the `EventManager` and add more functionality to it and make it exactly fit your needs or
even emit events, by extending it.
Of course you wonder what you can do with all of this now. We will explain this further on the next page.

View File

@@ -1,29 +0,0 @@
---
sidebar_position: 1
---
# Getting Started with the Event Handler
An event handler is essential to process the data, which Discord sends to you.
With a good implementation, you will have a nice code structure and thus have a good overview in long term.
Since the `EventEmitter` class is commonly used you probably already know it from other libraries.
Discordeno decided against it as it comes with several downsides which are mentioned below.
- It's easy to create memory leaks, when you add too many listeners or go carelessly with it.
- Many fragmented parts of event code complicate maintenance.
- ErrorHandling is difficult and debugging is harder when many listeners are open for the same events.
Performance plays a more important role than handling, however this event management system can be easily implemented
since it only needs a few changes in your code.
In the following we will show you, how to create an event manager, which is compatible with Discordeno's Client.
:::info template
You can also copy the
[`EventManager` from the template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/EventManager.js).
:::

View File

@@ -1,75 +0,0 @@
---
sidebar_position: 3
---
# Handle Events
When an event is fired, Discordeno sends two important things: the `client` instance and the `payload`.
As mentioned in the `Structure` section, the `payload` object does not contain any functions as it's a plain json
object.
In order to take use of our nice built structures, we need to transform the payload into a structure.
:::info
The Structures can be found [here](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures)
:::
Sometimes it's important to listen to events, in order to get informed of changes and updating the cache based on it.
### Message Event
This file should be called `messageCreate.js`.
```js
const Message = require("./structures/Message");
module.exports = async (client, payload) => {
const message = client.messages.forge(payload);
if (message.author.bot) return;
if (message.content === "!ping") return await message.reply("pong");
};
```
### Interaction Event
This file should be called `interactionCreate.js`.
```js
const Interaction = require("./structures/Interaction");
module.exports = async (client, payload) => {
const interaction = client.interactions.forge(payload);
if (interaction.data.name === "ping") return await interaction.reply({ content: "pong" });
};
```
### Ready Event
This file should be called `ready.js`.
:::tip
There is a small difference with the `ready` Event. The Event is fired `shard` wise, in other words it fires every time
a `shard` becomes ready.
:::
In order to fire the "real event" a small code snippet has to be added to the `ready` Event.
```js
const User = require("../Structures/User");
module.exports = async (client, payload) => {
client.user = client.users.forge(payload.user);
if (payload.shardId + 1 === client.gateway.maxShards) {
// All Shards are ready
console.log(`Successfully connected to the gateway as ${client.user.tag}`);
}
};
```

View File

@@ -1,4 +0,0 @@
{
"label": "Structures",
"position": 7
}

View File

@@ -1,55 +0,0 @@
---
sidebar_position: 5
---
# Create Collectors
Some of your commands or features are sometimes based on user interactions. E.g. if a user presses a button and you want
to know whether it was pressed. This is actually done by listening to the `interactionCreate` event.
But sometimes you need to access locale variables or don't want to "hardcode" the part.
That's why it's sometimes recommended to create collectors.
Collectors are listeners that listen to a specific event. In addition, you can provide a filter, so you only receive
certain interactions.
## Use a Collector
:::note Template The template code is used below. You must have the EventManager part to use the collector feature. :::
We have a pre-made class for collectors which you can find
[here](https://github.com/meister03/discordeno.js/blob/master/Util/Collectors.js).
```js
const Discord = require("discordeno.js");
const filter = (m) => m.data?.customId === "warn_modal" && m.user.id === interaction.user.id;
const listener = client.eventListener; // When the eventListener property is named different
const collector = new Discord.Collector("interactionCreate", {
client: client,
timeout: 60000,
filter,
max: 20,
listener,
});
collector.on("collect", (m) => {
const interaction = client.interactions.forge(m);
// Stop Collector
// collector.stop();
});
// Fires on a timeout, when the collector has reached the max amount of interactions or when it has been closed
collector.on("end", (collected) => {
// Map of Collected Interactions
console.log(collected);
});
```
As you can see, this opens up many possibilities. You can listen to any event and get the interaction you need.
### Collector Options
`filter`: Function, just fire the event if the filter returns true. `timeout`: Number, the time in milliseconds until
the collector times out. `max`: Number, the max amount of interactions the collector can collect. `listener`: Function,
the listener that will be fired when the collector collects an interaction. Just required when client property is named
differently.

View File

@@ -1,223 +0,0 @@
---
sidebar_position: 4
---
# Create Components
Since Discord has decided to make message content accessible only to privileged bots, components will play an
increasingly important role in the future. Discord has released some components already and many more will follow. Of
course, this opens up completely new possibilities. On the one hand, it improves the user experience and on the other
hand, the interactions can be easily handled by the developer.
To take advantage of this, we'll go into more detail on how to use them.
:::note Runtime Overhead
Constructor classes are nice to use and make your code look better, but they incur a slight runtime overhead compared to
just using raw data because they still execute methods, which takes more time to process.
:::
We already have a Template for `Components`, which can be found
[here](https://github.com/meister03/discordeno.js/tree/master/Structures/Component.js).
## Different Components:
There are many different components, which you can quickly read about here:
### Action Row (`type: 1`):
This is a top level component, which contains a limited amount of other components. It can be described as container.
An Action Row ...
- can not include an action row
- can maximal have 5 Buttons
- can have 1 SelectMenu
- can have 1 Text Input (only available in modal responses)
### Button (`type: 2`):
Buttons are interactive components, are bound to a message and they sent an interaction payload, when a user clicks on
it.
![Different Button Styles](https://i.imgur.com/jUE2Kp0.png)
- Needs a customId, except the Link Button
- An Action Row can have maximal 5 Buttons
There are different styles of buttons, which can be used:
- `1` - PRIMARY - blurple - customId required
- `2` - DEFAULT - grey - customId required
- `3` - SUCCESS - green - customId required
- `4` - DANGER - red - customId required
- `5` - LINK - grey - url required
### Select Menu (`type: 3`):
Select Menus are a simple drop-down with selectable options. They accept a set of allowed selects, which sends an
interaction payload, when a user selects sth. from the menu.
![Select Menu](https://i.imgur.com/42Hwiuw.png)
- You can specify a range of allowed selects (`minValue` and `maxValue`)
- Every Select Item can have an `emoji` and has a `value`, in order to identify the selected item
- A default Select Item can be set
- An Action Row can have maximal 1 Select Menu
### Text Input (`type: 4`):
Text Inputs are interactive components, which can just be sent with a modal response.
- You can specify a range of text length (`minLength` and `maxLength`)
- You can add a placeholder, a pre-filled value and specify whether the text input is required
- An Action Row can have maximal 1 Text Input
## Send Components
As mentioned above there are different types of components. This requires to define a type, so that Discord knows, which
component you want to use.
```js
class ActionRow {
constructor(options = {}) {
this.type = 1;
}
setComponents(...components) {
this.components = components;
return this;
}
}
```
```js
const button = new Button();
const button2 = new Button();
const actionRow = new ActionRow().setComponents(button, button2);
```
This code will obviously not work because it's a missing a lot required of data. The other reason is that we can't send
a class to Discord, we need sth. to transform it to a json object.
We have a pre-made class for components which you can find
[here](https://github.com/meister03/discordeno.js/tree/master/Structures/Component.js).
### Button
```js
const Discord = require("discordeno.js");
const message = client.messages.forge(rawMessage);
const button = new Discord.Component()
.setType("BUTTON")
.setStyle("LINK")
.setLabel("Click me!")
.setUrl("https://google.com")
.toJSON();
// Button with raw types
const button2 = new Discord.Component()
.setType(2)
.setStyle(4)
.setLabel("DO NOT CLICK")
.setCustomId("12345")
.toJSON();
const actionRow = new Discord.Component()
.setType("ACTION_ROW")
.setComponents(button, button2)
.toJSON();
// Message to send
const messageOptions = { content: "hello", components: [actionRow] };
// await client.helpers.sendMessage(channelId, messageOptions); // Do it the raw way
message.channel.send(messageOptions); // Do it with the structure
```
As you can see, for simplicity you can use strings instead of numbers (types), which are hard to remember.
### Select Menu
```js
const Discord = require("discordeno.js");
const message = client.messages.forge(rawMessage);
const selectMenu = new Discord.Component()
.setType("SELECT_MENU")
.setCustomId("12345")
.setOptions([
{
label: "Option 1",
value: "1",
description: `This is option 1`,
},
{
label: "Option 2",
value: "2",
description: `This is option 2`,
},
{
label: "Default Option",
value: "3",
description: `Default option...`,
default: true,
},
])
.setPlaceholder("Select an option")
.toJSON();
const actionRow = new Discord.Component()
.setType("ACTION_ROW")
.setComponents(selectMenu)
.toJSON();
const messageOptions = { content: "hello", components: [actionRow] };
// await client.helpers.sendMessage(channelId, messageOptions); // Do it the raw way
message.channel.send(messageOptions); // Do it with the structure
```
### Text Input
```js
const Discord = require("discordeno.js");
const interaction = client.messages.forge(rawInteraction);
const textInput = new Component()
.setType("TEXT_INPUT")
.setStyle("SHORT")
.setCustomId("t1")
.setLabel("User ID")
.setPlaceholder("User ID")
.setRequired(true)
.setMaxLength(20)
.setMinLength(1)
.toJSON();
const textInput2 = new Component()
.setType("TEXT_INPUT")
.setStyle("PARAGRAPH")
.setCustomId("t2")
.setLabel("Reason")
.setPlaceholder("Reason for Ban")
.setRequired(false)
.setMaxLength(300)
.toJSON();
const actionRow = new Component().setType("ACTION_ROW").setComponents(textInput).toJSON();
const actionRow2 = new Component().setType("ACTION_ROW").setComponents(textInput2).toJSON();
interaction.popupModal({
customId: "ban_modal",
title: "Ban User",
components: [actionRow, actionRow2],
});
```
### Receive Interactions
When a user clicks a button or selects an option from a Select Menu, Discord sends an `interactionCreate` event, which
contains the information necessary to process it.

View File

@@ -1,100 +0,0 @@
---
sidebar_position: 2
---
# Create Structure
Structures are often used to transform data and add methods to existing objects. To make it easier to work with them.
Imagine you have a channel object to which you want to send a message.
```js
const data = {
id: 806947972004839444n,
name: "spam-and-bots",
};
```
The recommended way would be:
```js
await client.helpers.sendMessage(data.id, { content: "hello" });
```
However, you probably want to use something shorter, such as the following:
```js
class Channel {
constructor(client, data) {
this.client = client;
this.id = data.id;
this.name = data.name;
}
async send(options) {
return await this.client.helpers.sendMessage(this.id, options);
}
}
```
Now you can use the `.send()` method on the channel object without using such a long code:
```js
const channel = new Channel(client, data);
await channel.send({ content: "hello" });
```
Moreover, you can modify the `.send()` method to better suit your use case e.g not send the message if the channel is
blacklisted.
This naturally opens a lot of opportunities and makes coding a lot easier. Because you decide what you want to do with
the data, how the methods are named and how you want to process the request.
## Using Template Structures:
When you are migrating from another library and you want to utilize the djs-like wrapper, you'll likely choose to
continue using special structures. Therefore we have ready-made structures for the wrapper `Discordeno.js`.
- [Guild](https://github.com/meister03/discordeno.js/tree/master/Structures/Guild.js)
- [Channel](https://github.com/meister03/discordeno.js/tree/master/Structures/Channel.js)
- [Role](https://github.com/meister03/discordeno.js/tree/master/Structures/Role.js)
- [Member](https://github.com/meister03/discordeno.js/tree/master/Structures/Member.js)
- [User](https://github.com/meister03/discordeno.js/tree/master/Structures/User.js)
- [Message](https://github.com/meister03/discordeno.js/tree/master/Structures/Message.js)
- [Interaction](https://github.com/meister03/discordeno.js/tree/master/Structures/Interaction.js)
- [Emoji](https://github.com/meister03/discordeno.js/tree/master/Structures/Emoji.js)
- [Webhook](https://github.com/meister03/discordeno.js/tree/master/Structures/Webhook.js)
- [Embed](https://github.com/meister03/discordeno.js/tree/master/Structures/Embed.js)
- [Component](https://github.com/meister03/discordeno.js/tree/master/Structures/Component.js)
- [Collection](https://github.com/meister03/discordeno.js/tree/master/Structures/Collection.js)
We recommend that you check the wrappers [Readme](https://github.com/meister03/discordeno.js#discordclient) in order to
construct the client for following the Guide
**Using the Structures:**
```js
const Discord = require("discordeno.js");
const client = new Discord.Client(clientOptions, cacheOptions); //See the Readme above
Discord.startBot(client);
const guild = client.guilds.forge(guildData);
const channel = guild.channels.forge(channelData);
const role = guild.roles.forge(roleData);
const member = guild.members.forge(memberData);
const user = guild.users.forge(userData);
const message = guild.messages.forge(messageData);
const interaction = guild.interactions.forge(interactionData);
const emoji = guild.emojis.forge(emojiData);
const webhook = new Discord.Webhook(client, webhookData);
const embed = new Discord.Embed(embedData); // embedData is optional
const component = new Discord.Component(componentData); // componentData is optional
const collection = new Discord.Collection();
```
Some popular methods have been added to the structures so that you can use them without having to come up with your own.
In order to use the Structures from the Wrapper, you need to invoke the `.forge` method with the raw discord data,
whereas it will construct the structure for you.
Next we're going to give a better insight into how create [`Embeds`](embeds) and [`Components`](components) with the
wrappers structures.

View File

@@ -1,106 +0,0 @@
---
sidebar_position: 3
---
# Create Embeds
Embeds are widely used by bots in order to display messages in a fancy way.
Unfortunately, the Discord API does not accept funky classes such as `new MessageEmbed().setTitle("hello")`, instead it
takes a json object, e.g. `{ title: "hello" }`. Therefore, we need to create an embed Structure that converts the
user-supplied data into the format which Discord uses.
:::note Runtime Overhead
Constructor classes are nice to use and make your code look better, but they incur a slight runtime overhead compared to
just using raw data because they still execute methods, which takes more time to process.
:::
```js
class Embed() {
constructor() {}
setTitle(title) {
this.title = title;
}
}
```
Now we have created a class which we can use to create embeds. But we can't just send this to Discord.
So we need an additional method which will convert the data from the class to the correct format.
```js
class Embed(){
constructor() {}
setTitle(title) {
this.title = title;
}
toJSON() {
return {
title: this.title
}
}
}
```
Wow, now you can create a embed and send it to Discord.
```js
const Channel = require("./structures/Channel"); // Path to structure
const channel = new Channel(client, data);
await channel.send({ embeds: [embed] });
```
You probably want more methods which you can use to create embeds.
[Here is how the Embed Structure looks like](https://github.com/meister03/discordeno.js/blob/master/Structures/Embed.js)
### Using the Embed Structure:
```js
const Discord = require("discordeno.js");
const channel = client.channels.forge(channelData);
const showCaseEmbed = new Discord.Embed()
.setColor(0x00AE86)
.setTitle("A Random Title")
.setURL("https://github.com/discordeno")
.setAuthor({
name: "Author name",
iconUrl: "https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png",
url: "https://github.com/discordeno",
})
.setDescription("A Random Description")
.setThumbnail("https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png")
.addFields(
{ name: "Field 1 Name", value: "Normal Field Value" },
{ name: "\u200B", value: "\u200B" },
{ name: "Field 2 Name", value: "Inline Field Value", inline: true },
{ name: "Field 3 Name", value: "Inline Field Value", inline: true },
)
.addField({ name: "Field 4", value: "Field Value" })
.setImage("https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png")
.setTimestamp()
.setFooter({
text: "A Footer Text",
iconUrl: "https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png",
})
.toJSON();
await channel.send({ embeds: [showCaseEmbed] });
```
### Embed Limits:
- Title: 256 characters
- Description: 4096 characters
- Field Name: 256 characters
- Field Value: 1024 characters
- Footer Text: 2048 characters
- Author Name: 256 characters
- 10 Embeds per message
- In total over all 10 Embeds not more than 6000 characters

View File

@@ -1,30 +0,0 @@
---
sidebar_position: 1
---
# Getting Started with Structures
As previously mentioned, Discordeno was built with as few classes as possible, this is in favor of performance.
For example, you cannot execute functions on objects.
```diff
- message.channel.send({content: "hello"})
+ client.helpers.sendMessage(message.channel.id, {content: "hello"})
```
This seems to be more complicated at first, but has many advantages:
- You get full control over the actions
- Errors are easier to debug
- A validation by classes does not have to take place
One of the disadvantages is that you have to change a lot in your code.
Of course, we recommend that you try out the upper way, but we will introduce structures in this guide because they are
used by many users who eventually want to migrate.
For example, if you want to get correctly formatted objects, structures are obviously beneficial, because they support
the readability of the code by their ease of use
In the following, we will introduce how to create your own structures and how to use the ones available in the template.

View File

@@ -1,4 +0,0 @@
{
"label": "Nodejs",
"position": 3
}

View File

@@ -1,29 +0,0 @@
---
sidebar_position: 3
---
# Create Application
1. Go to the [Developer Portal](https://discord.com/developers/applications) and create a new application.
2. Navigate to the Section `Bot` and confirm with "Yes, do it!"
3. Now copy your token and save it under a safe environment.
:::caution Token Security
Keep your token safe, because it is like a password that grants access to your bot, which then can be used for mass
DMing, mass banning or any other kind of malicious activity.
:::
## Add your Bot to your Server
In order to use your Bot, it should be in a server where you can interact with it.
1. Go to the [Developer Portal](https://discord.com/developers/applications) and click on your previously created bot.
2. Click on `OAuth2` and there go to the `URL Generator`.
3. Select the `bot` and the `applications.commands` scope.
4. Scroll down and select the `Administrator` permission.
5. Copy the generated URL and open it in your browser.
6. Select your Server and click the invite button.
The bot should now have been added to your server and show as an offline user.

View File

@@ -1,203 +0,0 @@
---
sidebar_position: 6
---
# Design
In order to ensure long-term scalability and maintainability, the code structure is of enormous importance. In the
following, we show how such a code structure could look like.
The essential parts are a `CommandHandler/CommandManager`, `EventHandler/EventManager`, lots of `Structures` in order to
code faster and `Plugins`, where your different features will be, such as `Commands`, `DB Stuff`...
## Code Structure
We recommend following structure for your code:
```root
├index.js
├─Structures/
├─Managers/
├─events/
├─Plugins/
├── General/
│ ├── commands/
│ │ ├── ping.js
│ │ └── ...
├── Developer/
│ ├── commands/
│ │ ├── eval.js
│ │ └── ...
├─Util/
└── ...
```
The following explains why this structure is suitable. If you want to follow this guide further, you should create these
folders.
In the `Managers` folder the Managers will be added e.g. `CommandManager.js`, `EventManager.js`. Generally codes, which
manage the system.
While in the `Structures` folder mainly classes are added like `BaseCommand.js`, `CommandResponse.js`, `Embed.js`,
`Components.js`, which make it easier to add methods to objects.
The `events` folder will contain the event handlers such as `messageCreate.js`, `debug.js`
Your many useful features and categories end up in the `Plugins` folder, where they should be categorically divided into
many folders.
The `Util` folder contains functions or classes that help you convert certain things, such as timestamps, into a
human-readable format.
## CommandHandler & BaseCommand
The `CommandHandler` is the main class of the bot, which will handle all the commands and the events received from
Discord.
The `BaseCommand` is the base class of all commands, which will be extended with the`CommandResponse` class.
### Steps showed in the following Guide
- Loading commands from different plugins
- Deploying slash commands
- Handling `messageCreate` & `interactionCreate` events
- Command rate limit handling
- Handle `Interaction` & `Message` commands with the same code
- Validating user provided arguments
- Correct permission and error handling
- Hot reloading commands
- Creating message and interaction collectors
## EventHandler
You probably realized that Discordeno does not use an `EventEmitter` to fire the events, but your own event function is
fired.
There are ways to adapt to an `EventEmitter`, but we decided against it for the following reasons:
- It's easy to create memory leaks, when you add too many listeners or go carelessly with it.
- Many fragmented parts of event code complicate maintenance.
- ErrorHandling is difficult and debugging is harder when many listeners are open for the same events.
## Structures
Structures are essential to abstract larger parts of code in smaller ready-made methods and to modify them if necessary.
Example:
```js
class Command {
static name = "ping";
static aliases = ["pong"];
static botPermission = ["SEND_EMBED_LINKS"];
run(message, args) {
// do something
}
}
```
It would be annoying adding everytime the `botPermission` property to the class Command, when the Permission is used
from every Command, then it is unnecessary to add it, when you can extend the class.
It would be annoying to add the `botPermission` property to the command class every time the same permissions are used
by each command. Extending the class makes this extra step obsolete.
```js
class BaseCommand {
constructor(client) {
this.client = client;
this.basePermission = ["SEND_EMBED_LINKS"];
}
}
class Command extends BaseCommand {
static name = "ping";
static aliases = ["pong"];
constructor(data) {
super(data);
}
run(message, args) {
// do something
}
}
```
## Plugins
The plugins folder helps you categorize your code into many parts to give some structure.
Of course, this has many advantages, you have a much clearer code, you can debug problems much easier.
This also opens possibilities for open source contributions, since not all parts of the code have to be published in
order to add new plugins, since they are "independent".
There will be the main `Plugins` folder, which by default contains a `General` folder for all your base commands. The
`Plugins` folder will also contain all your other plugins.
## Error Handling
One of the most important things is how to handle errors. This is done to provide a user-friendly experience and to find
errors faster.
You should catch errors and log them in your logger so you can fix them later. There are several open source `Sentry`'s
that give you a good overview of the latest errors through a website.
Sometimes errors have a positive effect on maintainability and scalability.
In addition, handling errors caused by users is very important to increase transparency. If they don't know why the
error happened, then they'll be very surprised with what they did wrong and might even remove your bot from their
server.
## Caching
Normally libraries cache all the info they get, which can of course be helpful at the beginning to discover all
functionalities but later it turns out to be a resource-consuming method. Therefore, this way should be avoided.
Discordeno allows `Custom Caching` and even `Custom Property Caching` which gives you fine-grained control over the
caching of data. Normally you only need 20% of the data received by Discord, which makes caching unnecessary in most
cases.
There are also some `Filter` and `Sweeper` methods which help you to empty unused cache values.
## Cross Communication & Scaling
If you are running many different processes, such as a Welcomer API, communication is of central importance in order to
send or receive data, with which you can then perform certain actions.
Cross communication can be easily done with sockets or a TCP client.
This brings up this Structure:
```js
Bridge (Heart)
- Machine 1
- Cluster [0-9]
- Machine 2
- Cluster [10-18]
- Machine 3 -> Welcomer Api
- Machine 4 -> Dashboard
```
It's important to use something fast to have a proper "real time" communication.
Discordeno already offers many internal options for scaling bots, no matter what size.
As you scale, you will likely separate many parts of your bot and put them in separate processes, such as a
`RestManager`, a `Gateway Manager` etc.
This of course opens up a lot of possibilities:
- Zero downtime updates
- Global cache
- Synced rate limits
[Check the Github Readme for more information](https://github.com/discordeno/discordeno#features)
:::tip congratulations
You just learned how to design a scalable bot, let's get into implementing it with the next pages.
:::

View File

@@ -1,48 +0,0 @@
---
sidebar_position: 1
---
# Getting Started
If you are reading this, you probably want to create a Discord bot with Discordeno or migrate from popular libraries like Discord.js.
If this is going to be your first time making a bot, you should use Deno instead of Node.js. Although in some cases, Deno might not be suitable for you because of missing packages or a code base that is too large to migrate to a slightly different language.
This guide will help you make your first Discord bot using Node.js or even migrate your bot from another library.
Moreover this guide will utilize two different options. One option to use the Discordeno package without any frameworks
and one, which uses the wrapper called `Discordeno.js`, which aims to achieve a djs-like interface.
:::important Disclaimer
Some features are not documented yet. If you want to know more about them, kindly ask for help in the
[Discord Server](https://discord.gg/ddeno).
:::
## Why should I switch?
Discordeno was built with the purpose of being scalable, flexible and easy to use.
Libraries like `Discord.js` and `Eris` often have excessive caching behavior that can only be changed slightly without
breaking the entire library. There is a lack of customization and many nested classes, which makes it almost impossible
to edit the code without having unwanted side effects. Moreover scalability is only possible on a limited extend.
Discordeno has been kept plain and simple, which opens up a lot of opportunities for customization such as
`custom-caching (custom-property-caching)`, [`Standalone Rest`](../big-bot-guide/rest.md),
[`Gateway`](../big-bot-guide/gateway.md), [`Cache`](../big-bot-guide/cache.md) and more. Check the detailed advantages
[here](https://github.com/discordeno/discordeno#features).
This guide will also help you making your code more scalable and easier to maintain with bringing you closer to the
Discord API.
# Before you start
Before you start digging in this guide, you should have a solid understanding of `javascript`. If you are not familiar
with it, then you should take a look at some popular resources.
- [W3Schools Course](https://www.w3schools.com/js/DEFAULT.asp)
- [Mozilla Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- [JavaScript.Info](https://javascript.info)
A basic understanding is of great importance in order to solve problems skillfully.

View File

@@ -1,46 +0,0 @@
---
sidebar_position: 4
---
# Initial Setup
## Config File
Ideally, you should save your configs in an `.env` file. Out of simplicity for this guide, we are saving it in a
`config.json` file.
Create a file named `config.json` in your project folder and insert the following content:
```json
{
"token": "YOUR_TOKEN_HERE",
"prefix": "!"
}
```
## Edit the main file
Open the `index.js` file which you have created earlier and then insert the following content:
```js
const Discord = require("discordeno");
const config = require("./config.json");
const client = Discord.createBot({
events: {
ready(client, payload) {
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
},
},
intents: ["Guilds", "GuildMessages"],
token: config.token,
});
Discord.startBot(client);
```
Now you can start your bot by running the following command in your terminal:
```cli
$ node index.js
```

View File

@@ -1,30 +0,0 @@
---
sidebar_position: 2
---
# Installing Node.js and Discordeno
To use the Discordeno library you first need to install Node.js and then Discordeno from NPM.
Go to [nodejs.org](https://nodejs.org/en/) and download the latest version of Node.js. Open the downloaded file and
follow the instructions of the installer to install Node.js.
## Create a Folder
Open your file manager and create a new folder (e.g.: `discordbot`) in your desired directory. Then open the code editor
of your choice and create a new file (e.g.: `index.js`) in the folder you just have created.
### Initalize NPM & Install Discordeno
In order to keep track of the dependencies, you need to initialize NPM, which generates a `package.json` file.
```cli
$ npm init --yes
```
Then you need to install Discordeno. When you want to go along with the wrapper named `Discordeno.js`, then install it
too. Go to your terminal and run the following command:
```cli
$ npm install discordeno
```

View File

@@ -1,64 +0,0 @@
---
sidebar_position: 5
---
# Slash Commands
Since Discord has decided to make message content accessible only to privileged bots, message commands will play a
subordinate role in the future. Discord users will be more used to slash commands. That's why it's essential that every
bot offers them.
In the following we will show you how to create slash commands:
## Deploying Slash Commands
There is a difference between global and guild commands. Global commands take a while to appear in all guilds. Guild
commands show up directly.
For this reason, we will now show how to create guild commands, in order to test them immediately.
```js
const guildId = BigInt("YOUR_GUILD_ID");
const command = {
name: "ping",
description: "Retrieves the Bot latency",
options: [],
};
client.helpers.createApplicationCommand(command, guildId);
```
This is just very simple example, you can also add sub commands, select options and much more.
## Handling Slash Commands
Discord sends a WebSocket Event when a user runs a slash command. You can listen to this event by adding the
`interactionCreate` function in the client.
```js
const Discord = require("discordeno");
const config = require("./config.json");
const client = Discord.createBot({
events: {
ready(client, payload) {
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
},
async interactionCreate(client, interaction) {
if (interaction.data?.name === "ping") {
return await client.helpers.sendInteractionResponse(interaction.id, interaction.token, {
type: Discord.InteractionResponseTypes.ChannelMessageWithSource,
data: { content: "🏓 Pong!" },
});
}
},
},
intents: Discord.Intents.Guilds | Discord.Intents.GuildMessages,
token: config.token,
});
Discord.startBot(client);
```
The handling may see complicated in the beginning, but as mentioned before, we will introduce structures to make it
easier.