問題描述
我已經開始使用 Discord.js 庫在 Node.js 中創建 Discord 機器人.但是,所有代碼都包含在一個索引文件中.
I've started creating a Discord bot in Node.js using the Discord.js library. However, all the code is contained within a single index file.
如何將命令和事件分別組織到單獨的文件中,并在需要時運行它們?
How do I organize the commands and events each into separate files, and run them when needed?
推薦答案
為您的機器人組織代碼的一種出色、簡潔的方法是使用事件和命令處理程序.
An excellent, clean way to organize the code for your bot is to employ event and command handlers.
您從一個小的索引文件開始初始化客戶端和其余代碼.事件處理程序保存每個事件的文件,并在事件發出時調用它們.然后,在客戶端的 message
事件中,您可以通過運行來自預期命令文件的代碼.
You start out with a small index file to initialize the client and the rest of the code. An event handler keeps the files for each event, and calls on them when the event is emitted. Then, in your client's message
event, you can avoid long if
chains and switch
/case
altogether by running the code from the intended command's file.
您需要了解的基本 Node.js 結構是 module代碼>.
The basic Node.js structure you'll need to understand is a module
.
[A module is a] 您希望在應用程序中包含的一組函數.
[A module is a] set of functions you want to include in your application.
引自 w3schools.com.
因此,可以將模塊視為一個包含代碼片段的整齊粘貼的盒子.你可以把包裹帶到某個地方,打開它,然后拆開包裝.在 JavaScript 術語中,您可以在程序中的其他地方要求該模塊,并利用其中包含的代碼.模塊可以包含您需要在代碼的不同位置使用的變量、類、函數等.
So, think of a module as a neatly taped up box containing pieces of code. You can take the package somewhere, open it up, and unpack the pieces. In JavaScript terms, you can require the module somewhere else in your program, and utilize the code contained within it. Modules can contain variables, classes, functions, etc. that you need to use throughout different locations across your code.
既然您知道什么是模塊,那么您必須了解如何使用它們.
Now that you know what a module is, you have to understand how to work with them.
出于處理程序的目的,您將只使用 module
對象的 exports
屬性.通過對模塊使用 require()
,module.exports
返回.請考慮以下設置.
For the purpose of the handlers, you're only going to be using the exports
property of the module
object. By using require()
for a module, module.exports
is returned. Consider the following setups.
Question.js
class Question {
constructor(author, details) {
this.author = author;
this.details = details;
this.answers = [];
}
}
module.exports = Question;
newQuestion.js
const Question = require('./Question.js');
const myQuestion = new Question('me', 'How to code event/command handlers?');
在 Question.js
中,創建了一個新類 Question,并將其分配給 module.exports
.然后,當 newQuestion.js
中需要 Question.js
時,Question
被聲明為導出的類.它可以像往常一樣使用.
In Question.js
, a new class, Question, is created and assigned to module.exports
. Then, when Question.js
is required in newQuestion.js
, Question
is declared as the exported class. It can be used just as usual.
現在,例如,如果您需要導出多個類...
Now, for example, if you needed to export multiple classes...
Posts.js
class Question {...}
class Answer {...}
module.exports = { Question, Answer };
// Alternatively...
// module.exports.Question = Question;
// module.exports.Answer = Answer;
newQuestion.js
const { Question } = require('./Posts.js');
const myQuestion = new Question(...);
這樣,module.exports
被定義為一個對象,包含所創建的類.這意味著 require()
將返回一個對象,因此您可以 從對象中解構所需的類.
In this way, module.exports
is defined as an object, containing the created classes. This means that require()
will return an object instead, so you can destructure the needed class from the object.
您應該首先為您的活動創建一個文件夾,然后為每個活動創建一個文件.根據事件的名稱命名文件.例如,對于您客戶的 message
event,該文件應命名為 message.js
.
You should start by creating a folder for your events, and create a file for each one. Name the files according to the name of the event. For example, for your client's message
event, the file should be named message.js
.
實現您現在對模塊的了解,您可以編寫事件文件.比如……
Implementing what you now know about modules, you can code the event files. For example...
message.js
module.exports = (client, message) => {
// This code will be executed when
// the 'message' event is emitted.
};
設置處理程序.
要制作實際的處理程序,您可以將以下代碼放在函數中以加載事件...
Setting up the handler.
To make the actual handler, you can place the following code in a function to load events...
const requireAll = require('require-all'); // Don't forget to install!
const files = requireAll({ // Require all the files within your
dirname: `${__dirname}/events`, // event directory which have a name
filter: /^(?!-)(.+).js$/ // ending in '.js' NOT starting
}); // with '-' (a way to disable files).
client.removeAllListeners(); // Prevent duplicate listeners on reload.
// CAUTION: THIS REMOVES LISTENERS
// ATTACHED BY DISCORD.JS!
for (const name in files) { // Iterate through the files object
const event = files[name]; // and attach listeners to each
// event, passing 'client' as the
client.on(name, event.bind(null, client)); // first parameter, and the rest
// of the expected parameters
console.log(`Event loaded: ${name}`); // afterwards. Then, log the
} // successful load to the console.
現在,當您的客戶端發出您有文件的事件之一時,其中的代碼就會運行.
Now, when your client emits one of the events you have a file for, the code inside of it is run.
就像事件處理程序一樣,您應該首先為您的命令創建一個單獨的文件夾,然后為每個單獨的命令創建文件.
Just like for the event handler, you should start by creating a separate folder for your commands, and create files for each individual command.
您可以導出一個運行"函數和一個配置對象,而不是只導出一個函數.
Instead of exporting just one function, you can export a "run" function and a configuration object.
help.js
module.exports.run = async (client, message, args) => {
// This code will be executed to
// run the 'help' command.
};
module.exports.config = {
name: 'help',
aliases: ['h'] // Even if you don't want an alias, leave this as an array.
};
設置處理程序.
就像事件處理程序一樣,將此代碼放在一個函數中以加載命令...
Setting up the handler.
Just like the event handler, place this code in a function to load commands...
const requireAll = require('require-all'); // Using the same npm module...
const files = requireAll({ // Require all the files within your
dirname: `${__dirname}/commands`, // command directory which have a name
filter: /^(?!-)(.+).js$/ // ending in '.js' NOT starting
}); // with '-' (a way to disable files).
client.commands = new Map(); // Create new Maps for the corresponding
client.aliases = new Map(); // command names/commands, and aliases.
for (const name in files) { // Iterate through the files object
const cmd = files[name]; // and set up the 'commands' and
// 'aliases' Maps. Then, log the
client.commands.set(cmd.config.name, cmd); // successful load to the console.
for (const a of cmd.config.aliases) client.aliases.set(a, cmd.config.name);
console.log(`Command loaded: ${cmd.config.name}`);
}
在您客戶端的 message
事件中,您可以使用以下代碼運行命令...
In your client's message
event, you can use the following code to run the commands...
const prefix = '!'; // Example
const [cmd, ...args] = message.content.trim().slice(prefix.length).split(/s+/g);
const command = client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd));
if (command) {
command.run(client, message, args);
console.log(`Executing ${command.config.name} command for ${message.author.tag}.`);
}
<小時>
常見問題.
如果我需要傳遞事件/命令的數據庫相關變量或其他變量怎么辦?
對于事件,您可以在 event.on(...)
中傳遞您的變量,在 client
之后.然后在您的實際事件中,您的函數必須在 client
之后包含該參數.
For events, you can pass your variable in event.on(...)
, following client
. Then in your actual events, your function must include that parameter after client
.
對于命令,您可以在 message
事件中調用時將變量傳遞給 run 函數.同樣,在您的函數中,您需要包含正確放置的參數.
For commands, you can pass your variable into the run function when calling it in the message
event. Again, in your function, you need to include the properly placed parameter.
如果我想在子文件夾中包含命令/事件怎么辦?
查看此答案以進行遞歸搜索.
Check out this answer to search recursively.
如何將這些處理程序用于重新加載命令?
如果您將它們的代碼放在函數中,您可以設置一個重新加載"命令來調用這些函數,再次加載事件和命令.
If you placed the code for them inside of functions, you can set up a "reload" command that calls those functions, loading the events and commands again.
- Node.js 文檔
- MDN 文檔
- W3Schools 教程
require-all
包- Discord.js 文檔
client.removeAllListeners()
將刪除附加到客戶端的所有 監聽器,包括那些源自客戶端實例化的監聽器.這可能會導致與語音連接相關的錯誤,特別是語音連接未在 15 秒內建立
被拋出.為防止出現此問題,請跟蹤每個偵聽器函數并使用client.removeListener(listener)
單獨刪除每個函數.
client.removeAllListeners()
will remove all listeners attached to the client, including those originating from client instantiation. This can cause voice connection related errors, specificallyVoice connection not established within 15 seconds
being thrown. To prevent this issue, keep track of every listener function and remove each individually usingclient.removeListener(listener)
.
這篇關于如何為我的 Discord.js 機器人編寫事件/命令處理程序?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!