avatar
p1105_00

Discord.js #1

디스코드 봇 개발기
discordJS
Sep 24
·
6 min read

Prologue

초기 목표는 자주 사용하는 기능을 나만의 서버에서 사용하는 것으로 시작해 티켓의 개수를 입력하면 예상 보상을 출력해주는 디스코드 봇을 제작하였다. 그러다 서버로 이용했던 사이트의 아쉬운 성능과 해당 게임에 대한 관심이 떨어지며 자연스레 방치하게 되었고 디스코드 서버가 사라지며 정리를 하게 되었다. 그러다 다시금 찾게 된 게임을 통해 만난 사람들과 디스코드 서버를 꾸렸고 과거의 기억을 십분 발휘해 다시 봇을 개발하게 되었다.

GIthub에 있는 과거의 코드를 통해 기억을 떠올렸으나 그 동안의 기간동안 버전이 많이 바뀌었다. 미리 선언한 전치사를 통해 명령어와 일반 채팅을 구분했던 디스코드에서 / 전치사 통일로 바뀌었고, 해당 디스코드의 봇의 명령어를 미리 보여주는 기능이 생겼다.

첫 봇에 제작하는 데 있어 난관이던 것은 게임사의 api가 제공되지 않아 사이트의 해당 기능을 크롤링을 해야했던 것이었다. 하지만 지금은 이미 제공되고 있는 기능으로 게임 속 다양한 부분, 요소들을 확인할 수 있었다.

그렇게 빌고 빌었던 api는 우습게도 사용하기가 막막했다. 맨 땅에 헤딩식으로 했던 나의 공부 깊이는 너무나도 얕았던 것이다. 처음 사이트를 확인하고 벅찬 감정은 사라지고 이걸 어떻게 사용해야하는지를 한참이나 검색했다. 어찌저찌 찾아보고 코드를 짜 첫 원하는 결과물을 얻었을 때, 그 때의 기분은 잊을 수 없다. 막막했던 내게 힘껏 움직일 원동력이 되었다.


Goal

캐릭터의 정보를 알 수 있는 기능을 디스코드 봇 명령어에 담고 싶었다. 단순하게 명령어와 캐릭터의 닉네임을 입력하면 해당 캐릭터의 정보가 출력되게끔 제작하는 것이 목표였다.

해당 기능을 위해 axios를 사용하였다.

// components/axiosApiInstance.js
const axios = require('axios');
const dotenv = require('dotenv');

dotenv.config();

function axiosApiInstance(url){
   const axiosInstance = axios.create({
      baseURL: `${process.env.API_URL}${url}`,
      headers: {
         Accept: 'application/json',
         Authorization: `Bearer ${process.env.API_KEY}`
      }
   });
   return axiosInstance;
}

module.exports = axiosApiInstance;

추후 다른 컴포넌트에서 반복적으로 사용될 것이라는 생각으로 따로 인스턴스를 만들어 제작했다.

// components/research.js
const instance = require('./axiosApiInstance');

async function research(userNickName){
   try{
      const url = `...url/${userNickName}`;
      const inst = await instance(url);
      const res = await inst.get();
      return res.status === 200 ? await res.data : null;
   }catch(err){
      console.log(err);
   }
}

module.exports = research;

코드의 결과는 JSON 형식의 파일로 요청대로 캐릭터에 대한 정보가 담겨 있었다. 아이템, 레벨, 직업 등등 정보를 담고 있었지만 세부적인 데이터는 문자열 타입으로 html 태그들과 뒤죽박죽 섞여있었다.


Regexp

대학생 당시에 엉뚱하게 꽂히는 것이 있다면 수업, 학점 모두 신경쓰지 않고 몰두했었다. 정규 표현식 역시 한 때 이상하게 집착하고 찾아봤던 적이있었다. 그 때만 하더라도 이걸 어디에 사용할 지도 몰랐었는데 이번에 사용하게 되었다.

until-1462
// components/regexp.js
export default function regexp(string){
   const str = /(<([^>]+)>[\s]*)/gi;
   return string.replace(str, '');
}

섞여있던 html 태그들을 지워 세부적인 정보들을 객체의 하위 데이터로 사용할 수 있도록 만들 수 있었다.


Object

해당 객체에 정보들은 캐릭터의 성장치마다 다르게 출력되었다. 해당 성장치가 높으면 높을 수록 더 많은 양의 정보를 담고 있었다.

...
"Tooltip": {
   "Element_000": {
      "Type": "NameTagBox",
      "value": "+00 itemName"
   },
   "Element_001": {
      "type": "itemTitle",
      "value": {
         "bEquip": 0,
         "leftStr0": "itemGrade",
         "leftStr1": "itemQuality",
         ...
      }
   },
   "Element_002": { ... },
   ...
}

해당 게임의 특성상 무기와 방어구 5종에 부여되는 특수한 옵션들을 표시해야하는 상황 속에서, 어떤 경우에는 Element_007 그리고 또 어떤 경우에는 Element_009 처럼 고정된 하나의 키값을 사용할 수 없었다.


- 컬렉션 아티클






하나하나 배워나가고 있습니다.