지난 시간에 자동 직위조정 명령어를 만들어봤다.
Discord.js로 메이플스토리 디스코드 봇 만들기 (6)
지난 시간에는 길드컨텐츠 참여 내역 정보를 생성하고 수정하는 명령어를 만들어봤다. Discord.js로 메이플스토리 디스코드 봇 만들기 (5) 지난 시간에 길드원 정보를 mongoDB 데이터베이스에 생성하
huzan2.tistory.com
이번 시간에는 부캐 정보 입력과 길드원 정보 출력 명령어를 만들어보고 이제 메이플봇 만들기를 마무리해보려고 한다.
부캐 정보 입력
부캐 정보를 생성할 때, 기존 길드원 관리 명령어에 subcommand를 더할까 생각해봤지만, 본캐 정보를 추가로 입력해야 하기에 새로 명령어를 만드는 것이 낫겠다는 생각이 들어 명령어를 하나 더 만들어주기로 했다.
commands 폴더에 subCharacter.js를 생성하고, option으로 본캐 닉네임, 부캐 닉네임, 부캐 직업을 받도록 해준 다음, 각 option들을 불러와 변수에 저장해주었다.
run: ({ interaction }) => {
const inputNick = interaction.options.get("본캐닉네임").value;
const subCharNick = interaction.options.get("부캐닉네임").value;
const subCharJob = interaction.options.get("직업").value;
}
이미 존재하는 부캐 닉네임일 경우 정보 삭제, 존재하지 않는 닉네임인 경우 새로 생성해주도록 구현해줄 것이다. 먼저 길드원 본캐의 닉네임 유효성 검사를 거쳐준 다음, 입력받은 부캐 닉네임의 존재 여부를 확인해보자.
run: async ({ interaction }) => {
const inputNick = interaction.options.get("본캐닉네임").value;
const subCharNick = interaction.options.get("부캐닉네임").value;
const subCharJob = interaction.options.get("직업").value;
const ifexist = await memberDB.exists({nickName: inputNick});
if(!ifexist){
interaction.reply("해당 길드원 정보를 찾을 수 없습니다.");
return;
}
const doc = await memberDB.findOne({nickName: inputNick});
const ifsubexist = doc.subChar.includes(subCharNick);
if(ifsubexist){
// 부캐 정보가 존재하는 경우 -> 정보 삭제
} else{
//부캐 정보가 존재하지 않는 경우 -> 정보 생성
}
}
부캐 생성의 경우 길드원 정보 생성과 동일한 방식으로 짜주면 된다. 직위는 "부캐"가 될 것이고, subChar 배열에 본캐의 닉네임만 넣어주면 될 것이다.
else {
doc.subChar.push(subCharNick);
doc.save();
const newSubChar = new memberDB({
nickName: subCharNick,
grade: "부캐",
job: subCharJob,
subChar: [`${inputNick}`],
});
newSubChar.save();
interaction.reply(
`${inputNick} 길드원의 부캐 ${subCharNick}의 정보를 생성했습니다. 직업: ${subCharJob}`
);
}
본캐의 문서에 부캐 정보를 push해주는 코드까지 작성해주면 생성 부분 명령어는 끝이다.
다음으로 삭제 부분을 짜보자. 이전 길드컨텐츠 관련 명령어를 구현할 때와 마찬가지로 target index를 찾아 해당 부분을 splice()로 잘라내 줄 것이다.
if (ifsubexist) {
const targetIndex = doc.subChar.findIndex((e) => e === subCharNick);
doc.subChar.splice(targetIndex, 1);
doc.save();
}
다음으로 부캐의 db 문서도 불러와서 삭제해주도록 하자. deleteOne() 쿼리를 이용하면 손쉽게 삭제할 수 있다.
memberDB.deleteOne({ nickName: subCharNick });
테스트를 진행해보면...
사실 원래는 pop()을 이용해서 구현했지만, pop으로는 배열의 맨 마지막 요소만 삭제할 수 있다는 것을 테스트 도중 깨닫고 splice()로 바꿔 구현했다. 아래에 코드 전문을 첨부한다.
const { SlashCommandBuilder } = require("discord.js");
const memberDB = require("../models/memberSchema");
module.exports = {
managerOnly: true,
run: async ({ interaction }) => {
const inputNick = interaction.options.get("본캐닉네임").value;
const subCharNick = interaction.options.get("부캐닉네임").value;
const subCharJob = interaction.options.get("직업").value;
const ifexist = await memberDB.exists({ nickName: inputNick });
if (!ifexist) {
interaction.reply("해당 길드원 정보를 찾을 수 없습니다.");
return;
}
const doc = await memberDB.findOne({ nickName: inputNick });
const ifsubexist = doc.subChar.includes(subCharNick);
if (ifsubexist) {
const targetIndex = doc.subChar.findIndex((e) => e === subCharNick);
doc.subChar.splice(targetIndex, 1);
doc.save();
memberDB.deleteOne({ nickName: subCharNick });
interaction.reply(
`${inputNick} 길드원의 부캐 ${subCharNick}의 정보를 삭제했습니다.`
);
} else {
doc.subChar.push(subCharNick);
doc.save();
const newSubChar = new memberDB({
nickName: subCharNick,
grade: "부캐",
job: subCharJob,
subChar: [`${inputNick}`],
});
newSubChar.save();
interaction.reply(
`${inputNick} 길드원의 부캐 ${subCharNick}의 정보를 생성했습니다. 직업: ${subCharJob}`
);
}
},
data: new SlashCommandBuilder()
.setName("부캐")
.setDescription("길드원의 부캐 정보를 생성/삭제합니다.")
.addStringOption((option) =>
option
.setName("본캐닉네임")
.setDescription("길드원의 본캐 닉네임")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("부캐닉네임")
.setDescription("길드원의 부캐 닉네임")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("직업")
.setDescription(
"추가할 부캐의 직업 (삭제시에는 아무거나 입력해도 괜찮습니다)"
)
.setRequired(true)
),
};
길드원 정보 출력
이제 마지막으로 길드원 정보 출력 명령어를 만들어 볼 것이다. 사실 완전 마지막 명령어는 아니고 이것저것 자잘한 명령어를 더 만들어서 서버에서 사용할 예정이지만, 이전 포스팅에서 작성한 내용들과 거의 비슷한 방법으로 구현 가능한 명령어들이라 굳이 포스팅에서는 더 다루지 않기로 했다.
아무튼 /누구세요 명령어를 이용해서 길드원의 정보를 불러오도록 해보자. 이전에 2~3편에서 캐릭터 불러오기 명령어를 만들었던 것을 참고해서 embed에 출력해보도록 하겠다.
Discord.js로 메이플스토리 디스코드 봇 만들기 (2)
지난 시간까지는 discord.js와 djs-commander를 이용해서 디스코드 봇을 작동시키는 법을 익혔고, 이제부터는 본격적으로 메이플스토리 봇을 만들어 볼 것이다. Discord.js로 메이플스토리 디스코드 봇
huzan2.tistory.com
commands 폴더에 whoAreYou.js 파일을 만들어주고, SlashCommandBuilder, EmbedBuilder와 mongoose model을 불러온 후, option으로는 닉네임을 받도록 만들어주자.
앞선 다른 명령어들과 마찬가지로 길드원 정보가 존재하는지 확인해주고, db에서 해당 길드원의 문서를 찾아 각 필드의 정보를 가져와줄 것이다.
run: async ({ interaction }) => {
const inputNick = interaction.options.get("닉네임").value;
const ifexist = await memberDB.exists({ nickName: inputNick });
if (!ifexist) {
interaction.reply("해당 길드원 정보를 찾을 수 없습니다.");
return;
}
try {
const doc = await memberDB.findOne({ nickName: inputNick });
const memberJob = doc.job;
const memberGrade = doc.grade;
const memberSubChar = doc.subChar;
console.log(memberJob, memberGrade, memberSubChar);
interaction.reply(`${memberJob}, ${memberGrade}, ${memberSubChar}`);
} catch (error) {
interaction.reply(`오류 발생: ${error}`);
}
}
명령어를 실행해보자.
데이터베이스에 존재하는 그대로 잘 가져오는 것을 확인할 수 있다. 사실 처음 개발할 때는 doc.toObject()로 변환해주지 않으면 undefined가 불러와지는 현상이 발생했지만, 어째서인지 블로그를 작성하며 다시 개발할 때에는 object로 변환해주지 않아도 정상적으로 데이터를 불러온다. 아마도 명령어 핸들링에 라이브러리를 이용하며 처리 방식이 바뀐 탓이 아닐까 싶다.
아무튼 본격적으로 embed를 구성해보자. 기존 캐릭터 명령어에서 크롤링해온 캐릭터 코디 이미지를 가져오고, 닉네임, 직업, 직위, 부캐(본캐) 정보 정도를 넣어주면 될 것이다.
캐릭터 이미지를 불러오고, embed를 구성하는 과정은 지난 포스팅을 참고하자.
Discord.js로 메이플스토리 디스코드 봇 만들기 (2)
지난 시간까지는 discord.js와 djs-commander를 이용해서 디스코드 봇을 작동시키는 법을 익혔고, 이제부터는 본격적으로 메이플스토리 봇을 만들어 볼 것이다. Discord.js로 메이플스토리 디스코드 봇
huzan2.tistory.com
직위조정 좀 편하게 하고 이것저것 정보 좀 편하게 모아보고 싶어서 시작했던 봇 개발이 어느덧 마무리 단계이다. 포스팅에서 따로 설명하진 않았지만 자주 검색하는 내용(무기 종류별 추가옵션 표, 사냥터 루트 등등...)을 가져오는 명령어는 포스팅을 잘 따라왔다면 쉽게 만들 수 있을 거라 생각한다.아래에 서버에서 실제 사용 중인 초기버전 봇의 작동사진을 첨부하고, 길었던 discord.js 시리즈는 마무리해보도록 하겠다.
(아직 외전 한 편이 남긴 했다. 초기버전 봇을 만들 때 사용했던 방법도 한번 정리해서 올려보도록 하겠다)
'Node.js > Discord.js' 카테고리의 다른 글
Discord.js로 메이플스토리 디스코드 봇 만들기 외전(1) (1) | 2023.08.30 |
---|---|
Discord.js로 메이플스토리 디스코드 봇 만들기 (6) (0) | 2023.08.27 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (5) (0) | 2023.08.27 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (4) (0) | 2023.08.26 |
Discord.js로 메이플스토리 디스코드 봇 만들기 (3) (0) | 2023.08.25 |