# XenoSign Discord Bot

제노싸인 Discord 서버용 봇입니다. 명령을 실행한 사람이 접속 중인 음성 채널의 사람들을 무작위로 섞고, 입력한 최대 인원수에 맞춰 팀을 만듭니다. 봇 계정은 팀에서 제외합니다.

```text
!팀짜기 4
/팀짜기 인원:4
```

8명이 있으면 4명씩 2팀, 5명이 있으면 4명과 1명으로 나뉩니다.

```text
1팀: **@이유찬**, **@POLY**, **@런투유**, **@승룡**
2팀: **@훈2**
```

## Discord 앱 만들기 및 서버에 추가하기

1. [Discord Developer Portal](https://discord.com/developers/applications)에서 **New Application**을 누르고 앱을 만듭니다.
2. **Bot** 메뉴에서 토큰을 발급합니다. 토큰은 비밀번호와 같으므로 Git이나 채팅에 올리지 마세요.
3. 같은 **Bot** 메뉴의 **Privileged Gateway Intents**에서 **Message Content Intent**를 켭니다. 이 설정은 `!팀짜기` 명령에 필요합니다.
4. **Installation** 메뉴에서 Guild Install의 scopes로 `bot`, `applications.commands`를 선택합니다.
5. Bot Permissions는 `View Channels`, `Send Messages`만 선택합니다.
6. 생성된 Install Link를 열고 **서버 관리** 권한이 있는 계정으로 제노싸인 서버에 앱을 추가합니다.

직접 링크를 만들 때는 아래 URL의 `CLIENT_ID`를 **General Information > Application ID**로 교체합니다.

```text
https://discord.com/oauth2/authorize?client_id=CLIENT_ID&permissions=3072&integration_type=0&scope=bot+applications.commands
```

테스트할 서버에서 Discord의 개발자 모드를 켜고 서버 아이콘을 우클릭해 **서버 ID 복사**를 선택합니다. 이 값을 `DISCORD_GUILD_ID`로 설정하면 `/팀짜기`가 해당 서버에 즉시 등록됩니다.

## 환경 변수

```bash
cp .env.example .env
```

`.env`에 다음 값을 입력합니다.

```dotenv
DISCORD_CLIENT_ID=Developer Portal의 Application ID
DISCORD_TOKEN=Developer Portal의 Bot Token
DISCORD_GUILD_ID=제노싸인 Discord 서버 ID
COMMAND_PREFIX=!
HTTP_HOST=0.0.0.0
PORT=6700
```

`DISCORD_GUILD_ID`를 비워 두면 slash 명령을 global 명령으로 등록합니다. 운영 서버가 하나라면 서버 ID를 입력하는 구성을 권장합니다.

봇은 Apache reverse proxy가 연결할 HTTP 상태 서버를 `6700` 포트에 엽니다. `/`는 서비스 상태를, `/health`는 Discord 연결이 정상일 때 HTTP 200과 `"status":"ok"`를 반환합니다. Apache upstream은 `http://127.0.0.1:6700`으로 지정합니다.

## 로컬 실행

Node.js 20 이상이 필요합니다.

```bash
npm ci
npm test
npm run dev
```

## 서버 최초 준비

자동배포는 저장소가 아래 경로에 clone되어 있다고 가정합니다.

```bash
sudo mkdir -p /var/www/back
sudo chown -R "$USER":"$USER" /var/www/back
git clone --branch live git@github.com:k-ssoft/xenosign_discord.git /var/www/back/xenosign_discord
cd /var/www/back/xenosign_discord
cp .env.example .env
nano .env
```

서버에 Node.js 20 이상과 PM2가 있어야 합니다. PM2가 없다면 한 번만 설치하고 부팅 자동 시작을 설정합니다.

```bash
npm install -g pm2
pm2 startup
```

`pm2 startup`이 출력한 `sudo ...` 명령도 이어서 실행해야 합니다. 첫 배포가 끝나면 워크플로가 `pm2 save`를 실행합니다.

비공개 저장소라면 서버가 위 SSH clone URL을 읽을 수 있도록 GitHub Deploy Key도 서버에 설정해야 합니다. 사용자가 처음 clone을 정상 완료했다면 추가 설정은 필요하지 않습니다.

## GitHub 자동배포

GitHub 저장소의 **Settings > Secrets and variables > Actions**에 기존 서버와 동일한 아래 4개 Repository Secret을 등록합니다.

| Secret | 값 |
| --- | --- |
| `SERVER_HOST` | `xenosign.officialsite.kr` |
| `SERVER_USER` | SSH 사용자명 |
| `SERVER_SSH_KEY` | SSH 개인 키 전문 |
| `SERVER_PORT` | SSH 포트 |

`live` 브랜치에 push되면 [배포 워크플로](.github/workflows/deploy-xenosign-discord.yml)가 다음 작업을 자동 수행합니다.

1. `/var/www/back/xenosign_discord`를 `origin/live`로 fast-forward 갱신
2. 의존성 설치, 테스트, 타입 검사, 빌드
3. 모든 검증이 성공한 경우에만 `xenosign-discord` PM2 프로세스 시작 또는 재시작
4. `.env`의 `PORT`에 설정된 주소(기본 `http://127.0.0.1:6700/health`)에서 Discord 연결 상태 확인
5. 프로세스 PID와 HTTP health 확인 후 PM2 상태 저장

서버의 추적 파일에 직접 수정 사항이 있으면 덮어쓰지 않고 배포를 중단합니다. `.env`는 Git에서 제외되어 계속 유지됩니다. 수동 재배포가 필요하면 GitHub의 **Actions > Deploy XenoSign Discord Bot > Run workflow**를 사용합니다.

## 운영 명령

```bash
pm2 status xenosign-discord
pm2 logs xenosign-discord
pm2 restart xenosign-discord
```
