디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

좋은 기회로 디스코드 챗봇을 만드는 온라인 특강을 듣게되었다.
정말 재미있었다!

순서

vs code에 npm 설치하기

  1. npm install: npm을 설치한다.
  2. npm run dev: 설치한 npm을 실행한다.

디스코드 디벨로퍼에서 챗봇등록하기

  1. new appication 클릭
  2. add bot 클릭 후 yes do it 후 토큰을 복사

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

토큰을 통해서 채팅을 CR할 수 있기때문에 실제 서버에 배포한다면 토큰은 절대 공개되서는 안된다.

  1. vs code의 터미널에서 config.json에 복사한 토큰을 붙여넣는다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

  1. 디스코드 디벨로퍼 포털에서 생성한 채널을 클릭한 뒤 General Information에서 CLIENT ID 토큰 복사

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

  1. 디스코드 permissions calculator에서 권한주기

    • add 클릭 → 승인
      디스코드 봇 만들기 js - diseukodeu bos mandeulgi js
  2. 디스코드에서 채널이 생성된 것을 확인하기

vs code에서 코딩하기

!투표를 이용해서 제목과 투표지를 띄어쓰기로 입력하면 해당 입력값으로 투표하기를 생성해주는 챗봇을 만들어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export default async function vote(message, args) {
const voteEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"];

const question = args.shift();

if (args.length < 1 || args.length > 5) {
message.reply("One to five options are required. 선택 항목은 1-5개만 지원합니다.");
}

const embed = new MessageEmbed();

let description = "";
args.forEach((arg, i) => {
description += `${voteEmojis[i]}: ${arg}\n`;
});

embed.setTitle("🗳 " + question);
embed.setDescription(description);

const vote = await message.reply("Vote", { embed: embed });
args.forEach(async (arg, i) => {
await vote.react(voteEmojis[i]);
});
}

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

  • 전체 소스코드

웹소캣 vs HTTP

HTTP의 경우 클라이언트의 요청이 없으면 서버는 먼저 말을 걸 수 없다.
웹소켓은 서버가 클라이언트에게 먼저 말(메세지)을 걸수있다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

서버 확인하는 사이트

서버가 정상적인지 확인하는 사이트 : https://isitup.org/

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

1. Discord Bot 설정

우선 Discord 계정이 있어야 하고, 본인이 관리자 권한을 가진 서버를 생성해야 합니다.

아래 디스코드 개발자 포털로 접속합니다.

https://discord.com/developers/applications

먼저 디스코드 개발자 UI를 사용해서 디스코드 봇을 설정하고 봇의 토큰을 확인하겠습니다.

디스코드 개발자 포털에서 로그인 한 후, New Application 버튼을 클릭해서 새로운 어플리케이션을 생성합니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js
어플리케이션의 이름은 봇의 이름과 상관 없습니다. 봇의 이름과 어플리케이션 이름이 달라도 됩니다.
디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

어플리케이션을 생성하면 어플리케이션 대시보드로 이동하는데, 좌측에 Bot 탭으로 이동합니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

Add Bot 버튼을 클릭해서 봇을 추가합니다. 팝업 창이 뜨면 Yes, do it! 을 클릭해주세요.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

봇이 생성된 화면입니다. 봇의 이름과 아이콘을 선택할 수 있는 대시보드입니다. Click to Reveal Token 을 클릭하면 인증 토큰을 확인할 수 있습니다. 이 토큰을 복사해 놓습니다. 이 토큰은 봇에 로그인을 할 수 있는 인증토큰이기때문에 유출되지 않도록 조심해야 합니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

다음은 봇을 서버로 초대할 수 있도록 초대 링크를 만들어야 합니다.

OAuth2 탭으로 이동해서 SCOPES에서 bot을 선택하고, 하단에 Bot Permissions 에서 Administrator을 선택하여 관리자 권한을 줍니다.

Scopes에 하단에 보면 URL이 생성되어 있는 걸 확인할 수 있습니다. 생성된 URL을 복사해서 이동합니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

URL로 이동하면 위와 같은 화면을 볼 수 있습니다. 봇을 추가할 서버를 선택하고 계속하기 버튼을 클릭합니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

승인을 누르면 아래와 같이 봇이 오프라인 상태로 초대 된 것을 확인할 수 있습니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js
디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

디스코드 봇을 생성했고, 서버에 초대도 했으니 이제 봇에 로그인하는 프로그램을 작성해봅시다.

2. 프로젝트 생성

프로젝트 디렉토리를 생성하고 해당 디렉토리 내에 config.json 파일을 생성합니다.

아래와 같이 파일 내에 인증 토큰을 입력해주겠습니다.

config.json

{ 
	"BOT_TOKEN": "<YOUR TOKEN>" 
}

NPM 명령어를 이용해 package.json 생성합니다.

$ npm init

디스코드 API와 상호작용할 수 있는 discord.js 패키지를 설치해줍니다.

$ npm install discord.js

index.js 파일을 생성하고, 아래와 같이 디스코드 클라이언트를 생성하고, 인증 토큰을 이용하여 로그인 하는 코드를 입력합니다.

index.js

const Discord = require("discord.js");
const config = require("./config.json");

const client = new Discord.Client();
client.login(config.BOT_TOKEN);

아래 명령어를 통해 어플리케이션을 실행합니다.

$ node index.js

실행하면 디스코드 상에서 봇의 상태가 온라인으로 바뀌는 것을 확인할 수 있습니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

3. 사용자 명령 처리

이제 어플리케이션에서 사용자의 명령을 처리하는 로직을 구현해보도록 합시다.

봇이 식별하여 처리 할 Discord 명령은 어떤 식으로 구성하든 상관은 없지만, 보통 접두어, 명령이름, 인자로 구성합니다.

접두어는 무엇이든 될 수 있지만, 그냥 일반적인 대화와의 구분을 위해 보통 느낌표(!) 같은 특수문자를 사용한다. 이 글의 실습에서도 접두어로 느낌표를 사용하겠습니다.

명령이름은 사용자가 사용하려는 명령의 이름입니다. 접두어 뒤에 오는 단어를 명령어로 식별하도록 하겠습니다.

인자는 명령에 전달하는 특정한 값이며 공백으로 구분하여 명령이름 뒤에 작성하도록 하겠습니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js

위와 같은 예시의 경우 ! 가 접두어, ping이 명령이름, 1이 인자입니다.

index.js 를 아래와 같이 수정합니다.

const Discord = require("discord.js");
const config = require("./config.json");
const prefix = "!";

const client = new Discord.Client();

client.on("message", function(message) {
    // message 작성자가 봇이면 그냥 return
    if (message.author.bot) return;
    // message 시작이 prefix가 아니면 return
    if (!message.content.startsWith(prefix)) return;

    const commandBody = message.content.slice(prefix.length);
    const args = commandBody.split(' ');
    const command = args.shift().toLowerCase();
    
    if (command === "ping") {
        message.reply(`pong!`);
    }
});

client.login(config.BOT_TOKEN);

위와 같이 명령과 인자를 분리하여 파싱한 후 커맨드에 대한 처리를 해줍니다. 

다시 어플리케이션을 실행한 후, 디스코드에서 !ping 을 작성하면 봇이 응답하는 것을 확인할 수 있습니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js
핑퐁!

4. 인자를 처리하는 명령 작성

이번에는 인자를 받아 처리하는 명령을 작성해보겠습니다. 인자를 여러 개 받아 모두 합해주는 sum 명령을 작성해보도록 합시다.

index.js

const Discord = require("discord.js");
const config = require("./config.json");
const prefix = "!";

const client = new Discord.Client();

client.on("message", function(message) {
    // message 작성자가 봇이면 그냥 return
    if (message.author.bot) return;
    // message 시작이 prefix가 아니면 return
    if (!message.content.startsWith(prefix)) return;

    const commandBody = message.content.slice(prefix.length);
    const args = commandBody.split(' ');
    const command = args.shift().toLowerCase();
    
    if (command === "ping") {
        message.reply(`pong!`);
    } else if (command === "sum") {
        const numArgs = args.map(x => parseFloat(x));
        const sum = numArgs.reduce((counter, x) => counter += x);
        message.reply(`Sum result: ${sum}`);
    }
});

client.login(config.BOT_TOKEN);

명령이 sum 일 경우, 인자들을 모두 합해주고 reply 해주는 로직을 추가했습니다.

디스코드 봇 만들기 js - diseukodeu bos mandeulgi js
1 + 2 + 3 = 6

기능이 잘 동작하는 것을 확인할 수 있습니다.

커맨드 개수가 많아질 경우에는 아래와 같이 switch case 문으로 작성하는 것이 가독성이 더 좋은 것 같습니다.

const Discord = require("discord.js");
const config = require("./config.json");
const prefix = "!";

const client = new Discord.Client();

client.on("message", function (message) {
    // message 작성자가 봇이면 그냥 return
    if (message.author.bot) return;
    // message 시작이 prefix가 아니면 return
    if (!message.content.startsWith(prefix)) return;

    const commandBody = message.content.slice(prefix.length);
    const args = commandBody.split(' ');
    const command = args.shift().toLowerCase();

    switch (command) {
        case "ping":
            message.reply(`pong!`);
            break;
        case "sum":
            const numArgs = args.map(x => parseFloat(x));
            const sum = numArgs.reduce((counter, x) => counter += x);
            message.reply(`Sum result: ${sum}`);
            break;
    }
});

client.login(config.BOT_TOKEN);

참고

https://www.digitalocean.com/community/tutorials/how-to-build-a-discord-bot-with-node-js