Discord.js v14를 기반으로 한 다기능 Discord 봇입니다. 레벨링 시스템, 음성 채널 관리, 환영 메시지, 파티 예약 모집, 반응 역할, 로그 관리 등 다양한 기능을 제공합니다.
- 레벨링 시스템: 메시지 기반 XP 및 레벨 시스템
- 음성 채널 관리: 자동 생성되는 임시 음성 채널 관리 (Voice Master)
- 환영 메시지: 새 멤버 환영 메시지 자동 전송
- 파티 예약 시스템: 예약 시간에 맞춰 음성채널 생성 및 참가자 DM 초대
- 반응 역할 시스템: 이모지 반응으로 역할 자동 부여/제거
- 사용자 로그 시스템: 서버 사용자들의 모든 활동 로그 기록 및 관리 (관리자 전용)
- 커뮤니티 명령어: 투표, 게이브어웨이, 파티 모집 지원
- 유틸리티 명령어: 서버 정보, 사용자 정보, 밈, 가이드 등
- Node.js: v22.0.0 이상 (권장: v22.x 또는 v24.x LTS)
- npm: Node.js와 함께 설치됨
- Discord 봇 토큰: Discord Developer Portal에서 생성
# Git을 사용하는 경우
git clone <repository-url>
cd discord_bot
# 또는 ZIP 파일을 다운로드한 경우
# 압축을 풀고 해당 디렉토리로 이동npm install프로젝트 루트 디렉토리에서 config.example.json을 복사해 config.json 파일을 만든 뒤 값을 채워 넣습니다:
cp config.example.json config.jsonconfig.json 예시는 다음과 같습니다:
{
"clientId": "YOUR_BOT_CLIENT_ID",
"token": "YOUR_BOT_TOKEN"
}-
Bot Token (토큰):
- Discord Developer Portal 접속
- 애플리케이션 선택 → 왼쪽 메뉴에서 "Bot" 클릭
- "Reset Token" 또는 "Copy" 버튼으로 토큰 복사
⚠️ 주의: 토큰을 절대 공개하지 마세요!
-
Client ID (봇 ID):
- 같은 페이지에서 "Application ID" 복사
- 또는 "OAuth2" → "General"에서 확인
data 폴더가 존재하는지 확인하고, 없으면 자동으로 생성됩니다. 다음 파일들이 필요합니다:
data/leveling.json- 레벨 데이터 (자동 생성)data/levelConfig.json- 레벨 설정 (자동 생성)data/voiceMasterChannels.json- 음성 채널 설정 (자동 생성)data/welcomeSettings.json- 환영 메시지 설정 (자동 생성)data/userLogs.json- 사용자 활동 로그 데이터 (자동 생성)data/parties.json- 파티 예약 및 참여 데이터 (자동 생성)data/reactionRoles.json- 반응 역할 설정 데이터 (자동 생성)data/activeVotes.json- 진행 중 투표 및 투표자 데이터 (자동 생성)data/activeGiveaways.json- 진행 중 게이브어웨이 데이터 (자동 생성)data/tempVoiceChannels.json- 임시 음성 채널 소유권 데이터 (자동 생성)data/images/- 이미지 저장 폴더 (필요시)
봇을 실행하기 전에 슬래시 명령어를 Discord에 등록해야 합니다:
npm run deploy -- --dry-run위 명령으로 현재 로드되는 명령어 목록을 먼저 확인할 수 있습니다. 이 단계는 Discord API에 실제 등록하지 않습니다.
npm run deploy성공 메시지가 표시되면 명령어가 등록된 것입니다.
npm start봇이 정상적으로 실행되면 콘솔에 준비 완료! <봇 태그>로 로그인했습니다. 메시지가 표시됩니다.
- Discord Developer Portal 접속
- 애플리케이션 선택 → "OAuth2" → "URL Generator"
- Scopes에서
bot과applications.commands선택 - Bot Permissions에서 필요한 권한 선택:
Send Messages(메시지 보내기)View Channel(채널 보기)Manage Channels(채널 관리)Move Members(Voice Master 사용자를 임시 채널로 이동)Create Instant Invite(초대 링크 만들기)Connect(음성 채널 연결)Speak(음성 채널에서 말하기)Attach Files(파일 첨부)Embed Links(링크 임베드)Add Reactions(반응 추가)Read Message History(메시지 기록 읽기)Manage Roles(역할 관리, 반응 역할 기능에 필요)Manage Messages(once/remove/toggle 반응 역할에서 유저 반응 정리에 필요)Use External Emojis(외부 커스텀 이모지 반응 역할에 필요)
- 생성된 URL로 봇을 서버에 초대
Discord Developer Portal의 Bot 메뉴에서 다음 항목을 활성화해야 합니다.
SERVER MEMBERS INTENT: 환영 메시지와 멤버 입장/퇴장/역할 변경 로그에 필요MESSAGE CONTENT INTENT: 메시지 로그, 레벨 XP,!레벨,!랭킹에 필요
discord_bot/
├── config.example.json # 커밋 가능한 설정 예시 파일
├── config.json # 로컬 전용 봇 설정 파일 (Git 추적 제외)
├── package.json # 프로젝트 의존성 및 스크립트
├── src/
│ ├── index.js # 메인 진입점, 봇 초기화 및 실행
│ ├── deploy-commands.js # 슬래시 명령어 배포 스크립트
│ ├── commands/ # 명령어 파일들
│ │ ├── party/ # 파티 예약 모집 명령어
│ │ ├── utility/ # 유틸리티 명령어
│ │ └── voice/ # 음성 채널 관련 명령어
│ ├── events/ # 이벤트 핸들러
│ │ ├── ready.js # 봇 준비 완료 이벤트
│ │ ├── interactionCreate.js # 슬래시 명령어 처리
│ │ ├── messageReactionAdd.js # 파티 참여 및 반응 역할 추가 처리
│ │ ├── messageReactionRemove.js # 파티 참여 취소 및 반응 역할 제거 처리
│ │ ├── messageCreate.js # 메시지 이벤트 (레벨링 등)
│ │ ├── messageUpdate.js # 메시지 수정 이벤트 (로그 기록)
│ │ ├── messageDelete.js # 메시지 삭제 이벤트 (로그 기록)
│ │ ├── guildMemberAdd.js # 새 멤버 환영
│ │ ├── guildMemberRemove.js # 멤버 퇴장 이벤트 (로그 기록)
│ │ ├── guildMemberUpdate.js # 멤버 정보 변경 이벤트 (로그 기록)
│ │ └── voiceStateUpdate.js # 음성 채널 상태 변경
│ ├── services/ # 기능 서비스 계층
│ │ ├── partyService.js
│ │ ├── reactionRoleService.js
│ │ ├── schedulerService.js
│ │ ├── dmService.js
│ │ ├── levelPersistenceService.js
│ │ ├── lifecycleService.js
│ │ ├── tempVoiceChannelService.js
│ │ └── voiceChannelService.js
│ ├── storage/ # 데이터 저장소 모듈
│ │ ├── levelStore.js # 레벨 데이터 관리
│ │ ├── voiceMasterStore.js # 음성 채널 데이터 관리
│ │ ├── welcomeStore.js # 환영 메시지 설정 관리
│ │ ├── logStore.js # 사용자 로그 데이터 관리
│ │ ├── partyStore.js # 파티 예약 데이터 관리
│ │ ├── reactionRoleStore.js # 반응 역할 데이터 관리
│ │ ├── voteStore.js # 진행 중 투표 상태 관리
│ │ ├── activeGiveawayStore.js # 진행 중 게이브어웨이 상태 관리
│ │ ├── tempVoiceChannelStore.js # 임시 음성 채널 소유권 관리
│ │ └── jsonFileStore.js # 원자적 JSON 저장 및 손상 복구
│ └── utils/ # 명령어/이벤트 로더와 공통 메타데이터
├── test/ # Node.js 내장 테스트 러너 기반 회귀 테스트
└── data/ # 데이터 저장 폴더
├── leveling.json # 사용자 레벨/XP 데이터
├── levelConfig.json # 레벨 시스템 설정
├── voiceMasterChannels.json # 음성 채널 설정
├── welcomeSettings.json # 환영 메시지 설정
├── userLogs.json # 사용자 활동 로그 데이터
├── parties.json # 파티 예약/참여 데이터
├── reactionRoles.json # 반응 역할 설정 데이터
├── activeVotes.json # 진행 중 투표 데이터
├── activeGiveaways.json # 진행 중 게이브어웨이 데이터
├── tempVoiceChannels.json # 임시 음성 채널 소유권 데이터
└── images/ # 이미지 파일 저장소
- 3자 이상의 메시지에 대해 서버 설정 쿨타임마다 XP 획득 (기본 60초)
- 일정 XP 달성 시 자동 레벨업
/레벨명령어로 자신의 레벨 확인/랭킹명령어로 서버 내 순위 확인/레벨설정명령어로 레벨링 설정 관리
- 특정 음성 채널에 입장하면 자동으로 임시 음성 채널 생성
- 생성된 채널에서 마지막 사용자가 나가 채널이 비면 자동 삭제
/음성채널설정명령어로 Voice Master 채널 설정/채널인원제한명령어로 채널 인원 제한 설정/채널이름변경명령어로 채널 이름 변경/채널비공개명령어로 채널 공개/비공개 설정
- 새 멤버가 서버에 입장하면 자동으로 환영 메시지 전송
/환영메시지명령어로 환영 메시지 설정 관리- 지원 서브커맨드:
채널설정,배경설정,배경목록,메시지설정,설정확인,초기화
/파티생성명령어를 실행하면 입력 모달이 열리고, 제출 시 파티 모집 임베드 생성- 생성자는 자동으로 참여자에 포함되며, 다른 멤버는 모집 메시지에
✅반응으로 참여 - 모집 마감 또는 최대 인원 초과 시 추가 참여 자동 제한
- 예약 시간이 되면 봇이 음성채널을 생성하고 초대 링크를 만들어 참가자 전원에게 DM 전송
- 생성된 파티 음성채널은 생성 후 5분이 지나고 비어 있으면 주기적으로 자동 삭제
- 완료 또는 실패한 파티 기록은 30일간 보존한 뒤 자동 정리
제목(필수, 최대 100자)집합 시간(필수,YYYY-MM-DD HH:mm또는MM-DD HH:mm)설명(선택, 최대 500자)모집 마감 시간(선택, 동일 형식, 비워두면 집합 시간까지 모집)최대 인원, 채널 이름(선택)
마지막 입력칸은 Discord 모달 제한 때문에 두 값을 한 칸에 함께 입력합니다. 예시는 다음과 같습니다:
5, 발로란트 내전인원=5, 채널=발로란트 내전발로란트 내전(최대 인원 없이 채널 이름만 설정)
- 서버 사용자들의 모든 활동을 자동으로 기록
- 기록되는 활동:
- 메시지 전송/수정/삭제
- 서버 입장/퇴장
- 닉네임 변경
- 역할 변경
- 음성 채널 입장/퇴장
/로그조회명령어로 로그 조회:- 특정 사용자의 로그 조회
- 서버 전체 로그 조회
- 타입별 필터링 지원
- 개수 제한 설정 가능
/로그관리명령어로 로그 관리:- 로그 통계 확인
- 사용자별/전체/타입별 로그 삭제
- JSON 파일로 로그 내보내기
현재 코드에서 로드되는 슬래시 명령어는 총 19개입니다. Discord 안에서는 /가이드 명령어로 권한에 맞는 목록을 확인할 수 있습니다.
/가이드는 현재 실행 중인 봇 프로세스에 로드된 명령어를 기준으로 생성됩니다. Discord에 실제 배포된 명령어와 일치시키려면 명령어 변경 후 npm run deploy를 실행하고 봇 프로세스도 재시작해야 합니다. 응답은 명령어를 실행한 사용자에게만 보이며, 권한에 맞는 명령어와 실제 서브커맨드/필수 옵션을 표시합니다.
- 기본 안내:
/가이드,/핑,/서버,/사용자,/밈 - 레벨:
/레벨,/랭킹,/레벨설정 - 로그:
/로그조회,/로그관리 - 음성 채널:
/음성채널설정,/채널이름변경,/채널인원제한,/채널비공개 - 커뮤니티:
/투표,/게이브어웨이,/환영메시지,/파티생성,/반응역할생성
권한별 표시 기준:
- 일반 유저: 공개 명령어만 표시
Manage Roles권한 사용자: 공개 명령어와/반응역할생성표시- 관리자: 전체 명령어 표시
Zira bot처럼 사용자가 특정 이모지 반응을 누르면 역할을 자동으로 부여하거나 제거합니다. normal, once, remove, toggle 모드를 지원하며, 반응 역할 설정은 data/reactionRoles.json에 저장되어 봇 재시작 후에도 유지됩니다.
- 관리자가
/반응역할생성에서 채널, 기본 역할, 동작 방식, 토글 그룹을 선택 - 봇이 Zira식 설정 임베드를 표시
- 관리자가 필요하면 역할 선택지 패널에서 역할을 추가
- 관리자가 각 역할마다 서버 이모지, 자주 쓰는 이모지, 또는 직접 입력 방식으로 이모지를 하나씩 배정
- 봇이 제목/설명 모달을 표시
- 관리자가 제목과 설명을 입력하고 제출
- 봇이 선택한 채널에 반응 역할 안내 임베드를 생성
- 봇이 역할별 이모지를 안내 메시지에 자동으로 추가
- 사용자가 특정 이모지를 누르면 해당 이모지에 연결된 역할만 모드에 맞게 부여/제거
normal과toggle은 반응 제거 시 역할도 제거toggle은 같은 그룹의 기존 역할과 기존 반응 표시를 함께 정리해 하나의 선택만 남김once,remove,toggle은 유저 반응을 정리하기 위해 봇의메시지 관리권한이 필요
Discord 모달은 텍스트 입력만 지원하므로 채널/역할/동작 방식은 모달 안에서 고르지 않습니다. 대신 /반응역할생성을 입력했을 때 Discord가 보여주는 슬래시 명령어 옵션에서 서버에 맞는 항목을 선택합니다.
슬래시 명령어 옵션:
채널(필수)- 반응 역할 안내 임베드를 보낼 텍스트 채널
- 직접 ID를 입력하지 않고 Discord 채널 선택 목록에서 고릅니다.
- 예:
#role-select,#rules
역할(필수)- 반응으로 부여하거나 제거할 기본 서버 역할
- 직접 ID를 입력하지 않고 Discord 역할 선택 목록에서 고릅니다.
동작방식(선택)- 기본값:
normal - 직접 입력하지 않고 Discord 선택지에서 고릅니다.
- 선택지:
normal,once,remove,toggle
- 기본값:
토글그룹(선택)toggle모드에서 하나만 유지할 그룹 이름- 예:
파트,학년,닉네임색상
이모지 선택:
- 설정 임베드 상단의
역할 선택지 추가/변경패널에서 역할 선택지를 추가할 수 있습니다. - 기본 역할 1개에 추가 역할을 더해 최대 10개 역할 선택지를 한 메시지에 구성할 수 있습니다.
- 각 역할 선택지에는 이모지를 하나씩 배정합니다. 예:
🎮 @게임,🎵 @음악,📢 @공지 - 추가 역할을 선택하지 않으면 기본 역할 1개에 이모지 1개만 배정합니다.
- 서버 커스텀 이모지가 있으면 서버 이모지 선택 목록이 표시됩니다.
- 일반 이모지는 공지, 알림, 이벤트, 취미, 색상, 상태 반응처럼 Discord 서버에서 자주 쓰는 25개 이모지 목록에서 클릭해 선택할 수 있습니다.
- 자주 쓰는 이모지 항목은 서버에 의미가 맞는 커스텀 이모지가 있으면 해당 서버 이모지를 우선 사용합니다. 예:
notice,notification,event,music,voice,verified - 서버 이모지 이름은 항목 라벨과 별칭으로 매칭합니다. 예를 들어 서버에
notice이모지가 있으면공지항목은📢대신 서버의notice이모지를 사용합니다. - 목록에 없는 이모지는
이모지 직접 입력버튼을 눌러 붙여넣을 수 있습니다. - 커스텀 이모지를 직접 입력할 때는
<:name:id>또는<a:name:id>형식을 지원합니다. - Discord 슬래시 명령/모달은 전체 이모지 피커를 제공하지 않으므로, 임의의 일반 이모지는 직접 입력 방식으로 보완합니다.
모달 입력:
채널과 역할은 이미 슬래시 명령어 옵션에서 선택했으므로 모달에는 나타나지 않습니다.
제목(필수)- 예:
게임 알림 역할
- 예:
설명(선택)- 예:
아래 이모지를 누르면 게임 모집 알림을 받을 수 있습니다.
- 예:
- 직접 입력 방식을 선택한 경우
이모지입력란도 함께 표시됩니다.
normal- 반응 추가 시 해당 이모지에 연결된 역할 부여
- 반응 제거 시 해당 이모지에 연결된 역할 제거
- 알림 구독, 관심사 선택, 게임 역할 선택에 적합
once- 반응 추가 시 해당 이모지에 연결된 역할 부여
- 반응 제거 여부와 무관하게 역할 유지
- 규칙 동의, 인증 완료, 온보딩에 적합
remove- 반응 추가 시 해당 이모지에 연결된 역할 제거
- 알림 해제, 임시 역할 제거에 적합
toggle- 반응 추가 시 해당 이모지에 연결된 역할 부여
- 같은 토글 그룹의 다른 역할과 기존 유저 반응을 제거
- 여러 반응 역할 메시지로 하나의 그룹을 구성해도 Discord 반응 UI가 실제 역할 상태와 어긋나지 않도록 정리
- 파트, 학년, 닉네임 색상처럼 하나만 선택해야 하는 역할에 적합
반응 역할 설정은 재시작 후에도 유지되도록 JSON 파일에 저장합니다.
- 저장 모듈:
src/storage/reactionRoleStore.js - 저장 파일:
data/reactionRoles.json
저장 형태:
{
"MESSAGE_ID": {
"guildId": "GUILD_ID",
"channelId": "CHANNEL_ID",
"messageId": "MESSAGE_ID",
"emoji": "🎮",
"emojiId": null,
"emojiName": "🎮",
"roleId": "ROLE_ID",
"roleIds": ["ROLE_ID", "EXTRA_ROLE_ID"],
"items": [
{
"roleId": "ROLE_ID",
"emoji": "🎮",
"emojiId": null,
"emojiName": "🎮"
},
{
"roleId": "EXTRA_ROLE_ID",
"emoji": "🎵",
"emojiId": null,
"emojiName": "🎵"
}
],
"title": "게임 알림 역할",
"description": "아래 이모지를 누르면 게임 모집 알림을 받을 수 있습니다.",
"mode": "toggle",
"groupName": "파트",
"createdBy": "USER_ID",
"createdAt": 1710000000000
}
}파티 참여 기능도 반응 기반이므로, messageReactionAdd와 messageReactionRemove 이벤트에서 파티 반응을 먼저 처리한 뒤 반응 역할 메시지를 처리합니다.
messageReactionAdd- 저장된 반응 역할 메시지인지 확인
- 이모지가 일치하는지 확인
- 봇 사용자 반응은 무시
- 모드에 따라 해당 이모지에 연결된 역할 부여, 역할 제거, 또는 토글 그룹 정리
toggle모드는 같은 그룹의 다른 반응 역할 메시지에서 해당 유저 반응도 제거
messageReactionRemove- 저장된 반응 역할 메시지인지 확인
- 이모지가 일치하는지 확인
- 봇 사용자 반응은 무시
normal/toggle이면 해당 이모지에 연결된 역할 제거once/remove이면 역할 상태 유지
반응 역할 기능은 Discord 역할 계층과 권한 제한을 강하게 받습니다. 명령 실행 시 다음 조건을 검증합니다.
- 명령 실행자 권한:
Manage Roles또는Administrator
- 봇 권한:
Manage RolesSend MessagesEmbed LinksAdd ReactionsRead Message HistoryManage Messages(once,remove,toggle모드에서 유저 반응 정리)Use External Emojis(외부 커스텀 이모지 사용 시)
- 역할 계층:
- 봇의 최고 역할이 부여 대상 역할보다 위에 있어야 함
현재 구현은 /반응역할생성으로 새 반응 역할 메시지를 만드는 흐름을 제공합니다. 운영 편의성을 위해 아래 명령어를 후속으로 추가할 수 있습니다.
/반응역할삭제: 메시지 ID 기준으로 반응 역할 설정 삭제/반응역할목록: 현재 서버의 반응 역할 설정 목록 확인
- 봇이 온라인 상태인지 확인 (Discord에서 확인)
- 봇에게 필요한 권한이 있는지 확인
- 콘솔에 에러 메시지가 있는지 확인
config.json파일의 토큰이 올바른지 확인
npm run deploy명령어를 다시 실행- 실제 등록 전에
npm run deploy -- --dry-run으로 명령어가 정상 로드되는지 확인 - 봇이 서버에 초대되어 있는지 확인
clientId가 올바른지 확인- 봇에
applications.commands스코프가 있는지 확인 - 새 기능이 추가됐다면 글로벌 명령어 전파에 수 분 이상 걸릴 수 있으니 잠시 기다린 뒤 다시 확인
- 명령어 배포 후 봇 프로세스를 재시작해
/가이드의 로컬 명령어 목록도 갱신
data폴더에 쓰기 권한이 있는지 확인data폴더가 존재하는지 확인 (없으면 자동 생성됨)- 콘솔에 에러 메시지 확인
⚠️ 절대config.json파일을 Git에 커밋하지 마세요!- 이 저장소는
config.json을 Git 추적에서 제외하도록 설정되어 있습니다. - 팀원과 설정 형식을 공유할 때는
config.example.json만 사용하세요. - 토큰이 노출되면 즉시 Discord Developer Portal에서 토큰을 재설정하세요
- Discord.js 버전: v14.26.5
- Node.js 권장 버전: v22.x 또는 v24.x LTS
- 패키지 관리자: npm
- 파티 시스템 저장 방식:
data/parties.json기반 영속화 + ready 시 스케줄러 복구 - 반응 역할 저장 방식:
data/reactionRoles.json기반 영속화 + 반응 add/remove 이벤트 처리 - 진행 상태 복구: 투표, 게이브어웨이, 임시 음성 채널을 재시작 시 복원 및 정합성 확인
- 실패 재시도: 투표와 게이브어웨이 종료 실패는 제한된 횟수만 재시도하며, 삭제된 원본 메시지의 런타임 상태는 즉시 정리
- JSON 안전성: 같은 디렉토리의 임시 파일에 쓴 뒤 rename하며, 손상 파일은
.corrupt.bak으로 한 번 보존하고 기본값으로 복구 - 로그 보존: 메모리 버퍼를 15초마다 저장하며 30일이 지난 기록과 사용자별 10,000건 초과 기록 정리
npm test
npx eslint src test
npm run deploy -- --dry-runnpm test는 저장 안정성, 타이머 복구, 상호작용 오류 응답, 가이드 동기화와 주요 런타임 생명주기를 검증합니다.
ISC