mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-01 16:30:08 +00:00
Site: update site structure and add architecture page (#2675)
* remove blog * fix: license * chore: bump docusaurus * separate benchmark page * move to sub folder * fix blog path * Chore: update site * fix: only deploy on push and dispatch * fix: on: * ci: merge workflow * ci: fix if * refactor: dump preset
This commit is contained in:
4
site/tutorial/nodejs/Structures/_category_.json
Normal file
4
site/tutorial/nodejs/Structures/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Structures",
|
||||
"position": 7
|
||||
}
|
||||
55
site/tutorial/nodejs/Structures/collectors.md
Normal file
55
site/tutorial/nodejs/Structures/collectors.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
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.
|
||||
223
site/tutorial/nodejs/Structures/components.md
Normal file
223
site/tutorial/nodejs/Structures/components.md
Normal file
@@ -0,0 +1,223 @@
|
||||
---
|
||||
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.
|
||||
|
||||

|
||||
|
||||
- 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.
|
||||
|
||||

|
||||
|
||||
- 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.
|
||||
100
site/tutorial/nodejs/Structures/create-structure.md
Normal file
100
site/tutorial/nodejs/Structures/create-structure.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
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.
|
||||
106
site/tutorial/nodejs/Structures/embeds.md
Normal file
106
site/tutorial/nodejs/Structures/embeds.md
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
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
|
||||
30
site/tutorial/nodejs/Structures/getting-started.md
Normal file
30
site/tutorial/nodejs/Structures/getting-started.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user