슬래시 커맨드
execute(interaction, ctx) 하나로 완성되는 기본형이에요. 옵션은
25개까지, 한글 이름도 그대로 돼요.
풀문 디스코드 봇은 외부 개발자의 모듈을 직접 실행해요. 슬래시 커맨드 한 개에서 버튼 인터랙션과 주기 작업까지 — 파일 하나의 export 셋이면 충분해요. 운영자가 한 줄씩 심사하고 나면, 봇은 재시작조차 없이 모듈을 받아들여요.
execute(interaction, ctx) 하나로 완성되는 기본형이에요. 옵션은
25개까지, 한글 이름도 그대로 돼요.
모듈이 렌더링한 버튼의 클릭이 onButton으로 돌아와요. customId는
ctx.componentId()가 모듈 전용 네임스페이스로 만들어줘요.
schedules에 간격과 함수를 선언하면 봇이 살아 있는 동안 주기적으로
실행돼요. 최소 5분, 모듈당 2개까지.
ctx.economy로 잔액·순위·거래·이벤트·카지노 통계를 읽어요.
economy-api와 같은 감사된 SELECT만 제공되고, 쓰기 경로는 존재하지 않아요.
파일 하나에 named export 세 개. 이게 전부예요. 완성된 모듈은 저장소의 dice-fortune.mjs에서 볼 수 있어요.
export const meta = { author: '닉네임', version: '1.0.0' };
export const command = {
name: '운세', // 소문자·숫자·한글 1~32자
description: '오늘의 운세를 봐요', // 1~100자
options: [],
};
export async function execute(interaction, ctx) {
await ctx.reply(`🔮 ${ctx.user.displayName}님, 오늘은 무리하지 말아요.`);
}
계정 id를 생략하면 커맨드를 호출한 유저가 기본값이에요. 범위 밖 값은 에러가 아니라 경계값으로 조정돼요.
export async function execute(interaction, ctx) {
const w = await ctx.economy.wallet();
if (!w) return ctx.reply('먼저 /연동코드로 계정을 만들어 주세요.');
// 잔액 0이면 rank가 null이에요 — 서버 순위는 잔액이 있을 때만 표시.
const rank = w.rank ? ` (서버 ${w.rank}위)` : '';
await ctx.reply(`**${ctx.user.displayName}님** — ${w.balance.toLocaleString('ko-KR')}원${rank}`);
}
| 메서드 | 반환 | 설명 |
|---|---|---|
wallet(id?) | 잔액 + 서버 순위 | 계정이 없으면 null |
transactions(id?, {limit, before}) | 거래 페이지 + 커서 | 최신순, limit 1~50 |
leaderboard(limit?) | 상위권 목록 | 1~50명 |
events() | 진행 중 이벤트 | 최대 25개 |
guilds() | 길드 + 기금 + 인원 | 기금 순, 최대 25개 |
casinoToday() | 오늘(UTC) 게임별 집계 | wagered / paidOut / netBurn |
casinoHistory(days?) | 일별 집계 | 1~90일 |
필요할 때만 export하면 돼요. 없으면 무시돼요.
customId는 반드시 ctx.componentId(action)로 만드세요 —
cm:커맨드이름:action 네임스페이스로 클릭이 이 모듈로만 돌아와요.
3초 안에 update()·reply()·deferUpdate() 중 하나를
호출해야 해요.
export async function execute(interaction, ctx) {
await ctx.reply({
content: '주사위를 굴렸어요!',
components: [{ type: 1, components: [{
type: 2, style: 1,
customId: ctx.componentId('다시'), // ctx가 네임스페이스를 보장해요
label: '한 번 더',
}] }],
});
}
export async function onButton(interaction, ctx) {
await interaction.update({ content: `다시 굴려서 ${1 + Math.floor(Math.random() * 6)}이 나왔어요!` });
}
봇이 살아 있는 동안 주기적으로 도는 타이머예요. 모듈을 고치면 재시작 없이 새 타이머로 교체돼요.
export const schedules = [{
everyMinutes: 30, // 5 이상의 정수, 모듈당 최대 2개
run: async (tools) => {
const top = await tools.economy.leaderboard(3);
await tools.send('채널ID', `현재 1위: ${top[0]?.mcUsername ?? '없음'}`);
},
}];
tools.send는 텍스트 채널 전용이고, 멘션은 유저 멘션만
허용돼요(@everyone·역할 멘션은 봇이 걸러줘요). 내용은 2000자로 잘려요.
대부분은 로더와 심사가 막아주지만, 처음부터 알면 수정 없이 통과해요.
| 규칙 | 설명 |
|---|---|
import는 discord.js와 node: 빌트인만 | 서드파티 패키지는 거절돼요 |
eval·new Function·동적 import(변수) 금지 | 난독화·minified 코드도 마찬가지예요 |
fetch·child_process·process.env 접근 금지 | 외부 호출이 필요하면 심사에서 상의해요 |
| 원장 쓰기 금지 | 읽기는 ctx.economy로만 — 자체 SQL은 불가해요 |
| 커맨드·옵션 이름은 소문자·숫자·한글 | 대문자(라틴 포함 모든 문자)는 등록이 거부돼요 |
ctx.economy 대량 반복 호출 자제 | 원장 쿼리는 같은 DB를 읽어요 |