본문 바로가기

FrontEnd/JavaScript

[JS] 디스코드 봇 만든 후기

이 글은 디스코드 봇을 만든 후기입니다. 

계기

어느날 디스코드를 하는 도중 타이머 기능이 필요했는데 타이머 기능 정도는 직접 만들 수 있지 않을까?라는 생각을 하게 되어서 만들게 되었습니다. 또한 타이머 기능 외에 다른 기능을 만들면 재밌겠다 생각이 들어서 만들게 되었습니다. 

 

일단 디스코드를 만드는 방법은 python을 사용한다던지, 자바스크립트를 사용한다던지 여러가지 방법이 있어서 본인에게 편한 언어를 사용할 수 있습니다. 저는 자바스크립트를 채택했습니다. 

후기

이번에 직접 디스코드 봇을 만들어 보니까 직접 명령어를 통해서 상호작용 가능한 봇을 만든다는 점이 재밌었습니다. 

그래서 추후에 필요한 기능이 있을 경우 다른 봇을 추가하기 보다는 직접 만들어서 커스텀해서 넣으면 뿌듯하기도 하고 내가 원하는 방향대로 디스코드 봇 기능을 확장할 수 있는 점이 매력적이라고 느꼈습니다.

+ 날씨 기능 추가 

현재는 날씨 기능도 추가해서 날씨 기능까지 만들어진 상태입니다 !!

날씨 기능은 자바스크립트로 네이버 날씨를 크롤링해서 해당 데이터를 활용해서 뿌려주는 식으로 개발했습니다. 

그래서 광주, 서울 등 어떤 지역이든 날씨를 확인할 수 있습니다. (크롤링을 활용하면 날씨 외에 다른 정보들도 보여주는 게 가능합니다.)

개발 과정 

자바스크립트로 디스코드 봇을 개발하기 위해서는 discord.js가 필요했는데, 이때 버전별로 사용법이 달라서 많은 오류를 겪었습니다. 그래서 discord.js npm 사이트에 들어가서 각 버전별 정보를 수집해 lts버전인 13 버전을 선택하게 되었습니다.

 

전체 코드 예시

import Discord from "discord.js";
import { TOKEN } from "./env.js";
import { getLocalTemp } from "./crawller.js";
import { Timer } from "./src/timer.js";

const client = new Discord.Client({
  intents: [Discord.Intents.FLAGS.GUILDS, Discord.Intents.FLAGS.GUILD_MESSAGES],
});

client.on("ready", async () => {
  console.log("봇이 준비되었습니다.");
});

client.on("messageCreate", async (message) => {
  if (message.content.startsWith("^^타이머")) {
    const [, content] = message.content.split(" ");

    if (!validateContent(content))
      return message.channel.send(
        `형식을 지켜주세요. (^^타이머 1시간 or ^^타이머 1분)`
      );

    message.channel.send(`⏰ 째깍째깍 ~ 타이머가 시작되었습니다. ⏰`);
    const result = await Timer(content);
    message.channel.send(result);
  }
});

client.login(TOKEN);

messageCreate 속성을 사용해서 즉 디스코드에 특정 명령어가 입력되었을 경우 타이머가 동작하도록 했는데, 타이머를 ^^타이머 1시간 or ^^타이머 30분 이런 식으로 동작시킬수 있도록 설계했습니다.

 

^^타이머 1시간 이런식으로 들어오면 split메서드를 통해서 뒤에 필요한 콘텐츠만 가져옵니다.

validateContent() 함수를 실행시켜서 content내에 시간 or 분이 들어있는지 확인해줍니다.

function validateContent(content) {
  if (!content.includes("시간") && !content.includes("분")) return false;
  return true;
}

 

콘텐츠가 유효하다면 Timer() 함수를 실행시킵니다. 

Timer함수 내부는 이런 식으로 이루어져 있습니다. 

// Main Fucntion
export async function Timer(content) {
  const unit = convertHourAndMinute(content);
  const [time] = content.split(unit);
  const timeout = getTimeout(unit, +time);

  await Delay(timeout);

  return `@everyone ${content}이 지났습니다.`;
}

 

convertAndMinute함수를 실행해서 해당 코드 내에 시간, 분 단위로 전처리를 합니다.

그 이후 unit을 토대로 시간 or, 분에 숫자를 추출합니다.

getTimeout함수에 unit, time을 넣으면 해당하는 시간을 ms단위로 return 해줍니다.

 

ms 변환된 timeout을 가지고 Delay함수를 실행시켜서 타이머를 동작시킵니다.

이때 setTimeout()을 그냥 쓰지 않고 Delay() 함수로 분리한 이유가독성 측면에서 Delay() 함수를 사용하는 게 더 좋기 때문입니다.

그래서 분리를 안 하면 아래와 같은 코드의 결과물이 나오게 됩니다.

// Main Fucntion
export async function Timer(content) {
  const unit = convertHourAndMinute(content);
  const [time] = content.split(unit);
  const timeout = getTimeout(unit, +time);

  setTimeout(() => {
    // login
  },timeout)

  return `@everyone ${content}이 지났습니다.`;
}

 

추후에 return 된 결과물을 채널에 send 하게 됩니다. 

message.channel.send(`⏰ 째깍째깍 ~ 타이머가 시작되었습니다. ⏰`);
const result = await Timer(content);
message.channel.send(result);