이번에는 지난 포스팅에 이어 본격적으로 디스코드 봇에 여러 기능을 추가하는 방법에 대해 알아보자.
지난 포스팅 보러가기(봇 생성 및 discord.js 라이브러리 설치)
Discord.js로 메이플스토리 디스코드 봇 만들기 (0)
한참 이런저런 일로 이슈가 되었던 메이플스토리를 시작하고 난 후, 모르는 것이 많아 수시로 검색을 하곤 했는데, 몇번 찾아봤던 내용도 자세하게 기억나지 않아 여러 번 같은 검색어를 검색하
huzan2.tistory.com
messageCreate
기존 discord.js v13까지의 버전에서는 messageCreate를 이용해서 명령어를 구현했다. 현재 구동되고 있는 봇들 중에서도 각 봇마다 다른 접두사(prefix)를 이용해서 명령어를 입력하는 봇들이 많은데, 전부 messageCreate 이벤트를 감지해서 작동하는 것이다.
지난 시간에 생성한 index.js 파일에 다음과 같은 코드를 추가해 보자.
client.on("messageCreate", (message) => {
if (message.content === "핑") {
message.channel.send("퐁~!");
}
});
봇을 구동시킨 다음, 디스코드 채팅 채널에 "핑"이라는 채팅을 전송하면, 다음과 같이 응답하는 모습을 볼 수 있다.
필자가 사용하고 있는 Visual Studio Code(VSC) 기준으로, client.on()을 입력하면 다음과 같이 client를 통해 입력받을 수 있는 수많은 이벤트의 목록이 뜬다.
즉 위의 코드는 채팅(메시지)가 생성되었을 때 발생하는 messageCreate 이벤트를 받아 옆에 매개변수로 전달된 함수를 실행하도록 한 코드이다.
또한 자바스크립트를 이용하여 메시지의 내용 전부가 일치하는 경우가 아니라 일부 키워드가 포함되어 있는 경우에도 함수를 실행하도록 할 수 있다.
if (message.content.includes("안녕")) {
message.reply("안녕하세요 반갑습니다~!");
}
reply() 함수를 이용해 "안녕"이라는 키워드가 포함된 메시지가 생성되면 답장하도록 코드를 짠 후 봇을 실행했다. 그런데...
해당 키워드가 답장 내용에 포함되니 봇이 본인 채팅에 답장을 하는 현상이 발생했다. 이러한 현상을 방지하기 위해 우리는 유저가 생성한 채팅에만 봇이 반응하도록 코드를 짤 필요가 있다. 즉 message의 작성자가 봇일 경우 반응하지 않도록 하는 것이다.
client.on("messageCreate", (message) => {
if (message.author.bot) {
return;
}
if (message.content === "핑") {
message.channel.send("퐁~!");
}
if (message.content.includes("안녕")) {
message.reply("안녕하세요 반갑습니다~!");
}
});
message의 auther가 bot일 경우 아래 조건문을 실행하지 않고 바로 return하도록 코드를 짜 주었다.
SlashCommand
다음으로 SlashCommand라는 것을 이용해 명령어를 생성해 볼 것인데, 그 전에 한 가지 해 줘야 할 작업이 있다.
src라는 폴더 안에 있던 index.js를 메인 폴더로 꺼내 주는 것이다.
즉 다음과 같은 폴더트리가 구성되면 된다.
package.json의 "main"도 src/index.js가 아닌 index.js로 변경해주도록 하자.
원래는 Event Handler와 Command Handler 등을 전부 구현하는 방식을 이용하려고 했지만, 이를 자동으로 설정해주는 멋진 라이브러리가 있다는 것을 알게 되어 이를 이용한 방법을 소개하려고 한다.
원래 구현하려던 내용은 추후 포스팅으로 작성하여 링크를 첨부하도록 하겠다.
SlashCommand는 별도의 접두사를 설정하여 채팅으로 명령어를 입력하던 기존 방식과 달리 discord에서 공식적으로 명령어를 사용하는 방식이다. Slash("/")를 이용해서 명령어를 입력하는 방식이고, messageCreate를 이용하는 것보다 편리한 점이 많다.
DJS-Commander
Command Handling과 Event Handling을 알아서 해 주는 라이브러리이다. 공식 문서 페이지는 여기로 가면 된다.
DJS-Commander Documentation - DJS-Commander
GitHub - notunderctrl/djs-commander: Easy-to-use JavaScript library that simplifies the process of handling commands, events, and validations in your Discord.js projects.
djs-commander.underctrl.io
먼저 라이브러리를 설치해 보자. 터미널을 열고 다음 명령어로 라이브러리를 설치해 준다.
npm i djs-commander
다음으로, 각각의 명령어를 별개의 파일에서 구현할 예정이니 이 파일들을 모아둘 commands 폴더를 하나 생성한다.
이제 index.js 파일에서 CommandHandler 클래스를 불러온 후, CommandHandler를 생성해 줄 것이다.
먼저 index.js 상단에 CommandHandler 클래스를 불러오도록 하자.
const { CommandHandler } = require("djs-commander");
우리의 CommandHandler에게 commands 폴더를 전달하기 위해 path도 불러와준다.
const path = require("path");
이제 드디어 CommandHandler를 생성해준다.
new CommandHandler({
client,
commandsPath: path.join(__dirname, "commands"),
});
이렇게만 해주면 기존에 직접 구현하려던 방식보다 압도적으로 간단하게 기본적인 명령어 핸들러가 생성되었다!
ping.js
이제 명령어를 하나 만들어보자. 코딩의 처음에 Hello World가 있다면, 디스코드 봇 개발의 처음에는 ping이 있다. (일종의 국룰)
ping이라는 명령어에 pong이라고 응답하는 것이다.
먼저 commands 폴더 안에 ping.js라는 파일을 생성해보자.
공식 문서에 따르면 명령어 파일에서는 명령어 Object를 export 해야 한다고 한다. 해당 문서를 참고하여 다음과 같은 코드를 작성해 준다.
const { SlashCommandBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("ping")
.setDescription("pong이라고 응답합니다."),
run: ({ interaction }) => {
interaction.reply("Pong!");
},
};
SlashCommandBuilder는 discord.js에서 SlashCommand를 생성하는 함수이다.
setName() 함수 안에는 입력할 명령어의 이름을 문자열로 넣어주고, setDescription()함수 안에는 명령어의 설명을 적어준다. 이러한 정보들은 data 필드 안에 들어가 명령어의 정보를 구성할 것이다.
run 필드에는 해당 명령어가 호출되었을 때 실행할 함수를 넣으면 된다. 위 코드에서는 Pong!이라고 응답하도록 작성했다.
이제 파일을 저장하고 봇을 구동하면 다음과 같이 콘솔에 명령어가 생성되었다는 로그가 뜨고, 명령어도 정상적으로 작동한다.
Event Handling
위에서 command 뿐만 아니라 Event도 핸들링이 가능하다고 했는데, 이 기능을 이용하기 위해 먼저 event 폴더를 생성하고, 그 안에 ready 폴더, 그 안에 console-log.js라는 파일을 생성해 주었다. ready 이벤트를 받아 console.log를 실행해 주는 코드를 작성할 것이다.
이제 위에서 생성한 핸들러에 events 폴더의 path도 전달해준다.
new CommandHandler({
client,
commandsPath: path.join(__dirname, "commands"),
eventsPath: path.join(__dirname, "events"),
});
공식 문서의 설명을 읽어보고, 다음과 같이 코드를 작성해 준다.
module.exports = (client) => {
console.log(`${client.user.tag} is online`);
};
index.js에도 해당 기능을 하는 코드가 있기 때문에 ready 이벤트를 받는 부분을 지워주고 실행하면 다음과 같이 콘솔에 정상적으로 online 문구가 출력되는 것을 볼 수 있다.
이 ready 이벤트를 받아서 봇의 상태도 직접 변경할 수 있는데, ready 폴더 안에 setState.js라는 파일을 생성한 후 다음과 같은 코드를 입력해 준다.
const { ActivityType } = require("discord.js");
module.exports = (client) => {
client.user.setActivity({
name: "discord 봇 개발",
type: ActivityType.Playing,
});
};
discord.js에서 ActivityType을 불러온 후 "discord 봇 개발 하는 중"이라는 상태를 띄우기 위해 Playing 타입을 넣어 줬다.
이제 봇을 다시 실행해주면 아래 사진과 같이 봇의 상태가 변경된다.
SlashCommand에 Option 추가하기
이제 명령어에 option을 추가해 볼 것이다. option은 함수로 치면 매개변수 같은 것인데, 명령어를 입력할 때 봇에게 직접 전달할 수 있는 정보가 바로 option이다.
먼저 두 수를 더한 결과를 출력해주는 간단한 명령어를 만들며 이를 익혀보자. commands 폴더에 add.js라는 파일을 생성해 준 후, 다음과 같은 코드를 입력해 준다.
const { SlashCommandBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("add")
.setDescription("두 수를 더한 결과를 출력합니다.")
.addIntegerOption((option) => //option의 type이 integer(정수)
option
.setName("target-number-1") //option의 이름
.setDescription("첫 번째 숫자") //option의 설명
.setRequired(true) //필수로 입력되어야 하는지 여부
)
.addIntegerOption((option) =>
option
.setName("target-number-2")
.setDescription("두 번째 숫자")
.setRequired(true)
),
run: ({ interaction }) => {
const num1 = interaction.options.get("target-number-1").value; //각각의 option의 값(value)를 불러온다
const num2 = interaction.options.get("target-number-2").value;
interaction.reply(`${num1 + num2}`);
},
};
먼저 명령어의 정보를 구성하는 data 필드에 option을 받도록 정보를 입력해 주어야 한다.
우리는 정수를 받은 후 두 정수를 더할 것이므로 addIntegerOption()을 이용했지만, 다음 사진과 같이 여러 type의 option을 추가할 수 있다. 심지어 user이나 channel 정보도 option으로 받을 수 있다!
setName()과 setDescription()은 명령어를 구성하는 것과 동일한 방식으로 작동한다. 다음 사진을 보면 이해가 쉬울 것이다.
interaction.options.get("옵션의 Name").value로 각 옵션의 값을 가져올 수 있고, 이를 이용하여 num1 + num2를 reply하도록 했다.
이번 시간에는 디스코드 봇의 명령어를 생성하는 방법에 대해 알아봤다. 이제까지는 기본적인 discord.js 및 djs-commander 라이브러리 사용법이었고, 다음 포스팅부터 본격적으로 메이플스토리 디스코드 봇을 만들어보도록 하겠다.
마지막으로 현재 index.js의 전체 코드를 첨부하고 마무리하도록 하겠다.
require("dotenv").config();
const { Client, IntentsBitField } = require("discord.js");
const { CommandHandler } = require("djs-commander");
const path = require("path");
const client = new Client({
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMembers,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.MessageContent,
],
});
new CommandHandler({
client,
commandsPath: path.join(__dirname, "commands"),
eventsPath: path.join(__dirname, "events"),
});
client.on("messageCreate", (message) => {
if (message.author.bot) {
return;
}
if (message.content === "핑") {
message.channel.send("퐁~!");
}
if (message.content.includes("안녕")) {
message.reply("안녕하세요 반갑습니다~!");
}
});
client.login(process.env.TOKEN);
'Node.js > Discord.js' 카테고리의 다른 글
Discord.js로 메이플스토리 디스코드 봇 만들기 (5) (0) | 2023.08.27 |
---|---|
Discord.js로 메이플스토리 디스코드 봇 만들기 (4) (0) | 2023.08.26 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (3) (0) | 2023.08.25 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (2) (2) | 2023.08.24 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (0) (0) | 2023.08.18 |