Discord에서 마이그레이션
설정값 두 개(REST 기본 URL과 게이트웨이 URL)만 바꾸면 기존 Discord 봇을 GameVox에서 실행할 수 있습니다. 코드 변경도, SDK 교체도 필요 없습니다.
1. GameVox 봇 애플리케이션 만들기
- developers.gamevox.com에 로그인
- 새 애플리케이션 클릭
- 생성 창에서 봇 토큰을 복사(한 번만 표시되므로 바로 저장하세요)
2. 라이브러리를 GameVox로 향하게 하기
discord.js(Node, v14+)
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
rest: { api: 'https://bot-api.gamevox.com/api' },
ws: { gatewayURL: 'wss://gateway.gamevox.com' },
});
client.login(process.env.GAMEVOX_BOT_TOKEN); discord.py
import discord
discord.http.Route.BASE = 'https://bot-api.gamevox.com/api/v10'
discord.gateway.DiscordWebSocket.DEFAULT_GATEWAY = (
'wss://gateway.gamevox.com/?v=10&encoding=json'
)
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
client.run(GAMEVOX_BOT_TOKEN) JDA(Java)
JDA jda = JDABuilder.createDefault(GAMEVOX_BOT_TOKEN)
.setGatewayEncoding(GatewayEncoding.JSON)
.setRestConfig(new RestConfig().setBaseUrl("https://bot-api.gamevox.com/api"))
.setGatewayPool(scheduler)
.build();
// JDA는 시작할 때 /gateway/bot 에서 게이트웨이 URL을 읽습니다.
// 저희 REST 심은 여기서 wss://gateway.gamevox.com 을 반환합니다. Eris(Node)
const Eris = require('eris');
const client = new Eris(GAMEVOX_BOT_TOKEN, {
rest: { baseURL: 'https://bot-api.gamevox.com/api/v10' },
ws: { gateway: 'wss://gateway.gamevox.com' },
// Eris는 기본적으로 ETF를 씁니다. JSON을 강제하세요(GameVox는 아직 ETF를 지원하지 않습니다).
});
client.connect(); DSharpPlus(.NET)
var discord = new DiscordClient(new DiscordConfiguration
{
Token = Environment.GetEnvironmentVariable("GAMEVOX_BOT_TOKEN"),
TokenType = TokenType.Bot,
Intents = DiscordIntents.AllUnprivileged | DiscordIntents.MessageContents,
ApiChannelEndpoint = "https://bot-api.gamevox.com/api/v10",
GatewayUri = new Uri("wss://gateway.gamevox.com"),
});
await discord.ConnectAsync(); serenity(Rust)
let mut client = Client::builder(&token, intents)
.event_handler(Handler)
.api_base("https://bot-api.gamevox.com/api/v10")
.gateway_url("wss://gateway.gamevox.com")
.await?;
client.start().await?; 3. 봇을 서버에 설치하기
개발자 포털에서 애플리케이션의 OAuth2 탭을 열고, 필요한 권한으로 설치 URL을 만들어 공유하세요. URL은 Discord와 같은 형태입니다.
https://gamevox.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=8 서버 소유자가 링크를 눌러, 자신이 소유한 GameVox 서버를 고르고 확인하면 됩니다.
4. 다른 점
호환성은 100%를 목표로 합니다. 봇 로직이 “Discord가 아니다”라는 사실을 알 필요는 없습니다. 다만 알아 두면 좋은 몇 가지가 있습니다.
- 앱 설정은 클라이언트 안에서 합니다. GameVox는 서버 설정 안에 앱의 설정 폼을 렌더링할 수 있어, 설정이 있는 봇도 더 이상 호스팅된 대시보드가 필요하지 않습니다. 이는 의도적인 유일한 비호환이자, Discord에 대응물이 없는 유일한 부분입니다. 전체 문서 →
- Snowflake 에포크: Discord와 동일합니다(
1420070400000, 2015-01-01 UTC). Discord용으로 작성한 파서는 GameVox ID에서도 그대로 동작합니다. 자세히 → - 스레드 / 포럼 게시물은 아직 지원하지 않습니다.
- 음성은 Lavalink로 동작합니다. 별도 설정은 없습니다.
VOICE_SERVER_UPDATE가compatible-voice-gateway-{region}.gamevox.com을 가리키기만 하면 나머지는 Lavalink가 처리합니다. - 커스텀 이모지: 서버 소유 이모지는 Discord와 똑같이 메시지에서 동작합니다. 앱 소유 이모지는 당분간 개발자 포털에서 관리하며, 봇 API는
GET만 제공합니다. 이모지를 참고하세요. - 자체 호스팅 서버: 고객은 자체 하드웨어에서 GameVox를 운영할 수 있습니다. 봇도 거기서 동작하지만 기능 범위는 더 좁습니다(아직 웹훅과 인터랙션은 없습니다). 자체 호스팅 문서를 참고하세요.
- EU / AP 쓰기 지연: us-east 밖에서 호스팅되는 봇은 Aurora 쓰기 전달로 인해 쓰기 작업에서 약 80~150ms의 추가 지연이 생깁니다. 최상의 성능을 원한다면 us-east에서 호스팅하세요.
5. GameVox 안에서 앱 설정하기
Discord에서는 설정이 조금이라도 있는 봇이면 웹 대시보드를 함께 만들게 됩니다. 도메인, OAuth2 로그인, 세션, 권한 확인, 호스팅까지 — 대개는 운영자가 로그 채널을 고르고 기능 세 개를 켜고 끄게 하려는 것뿐입니다. GameVox는 운영자가 누구인지, 어떤 서버를 설정하는지, 그럴 권한이 있는지 이미 알고 있으므로 그 화면을 앱에 바로 제공합니다.
앱은 게이트웨이로 폼을 기술하고, GameVox가 서버 설정 ▸ 통합 ▸ 설정에 렌더링한 뒤 편집된 값을 그대로 돌려줍니다. GameVox는 아무것도 저장하지 않으며, 설정의 소유자는 오직 여러분의 앱입니다.
통합 전체는 게이트웨이 핸들러 하나와 REST 호출 하나뿐입니다.
client.on("raw", async (packet) => {
if (packet.t !== "APP_SETTINGS_REQUEST") return;
const { nonce, server_id, action, values } = packet.d;
const body = action === "save"
? { message: await save(server_id, values) }
: { version: 2, sections: await describe(server_id) };
await client.rest.post("/applications/@me/settings-response", {
body: { nonce, ...body },
query: new URLSearchParams({ server_id }),
});
}); GameVox가 내용을 채워 주는 채널·역할 선택기를 포함해 12가지 필드 유형, 조건부 필드, 가려진 시크릿, 섹션을 사용할 수 있습니다. 앱 내 설정 →
6. 확인해 보기
가장 간단한 확인 방법은 !ping에 pong으로 답하는 것입니다.
client.on(Events.MessageCreate, async (msg) => {
if (msg.author.bot) return;
if (msg.content === '!ping') {
await msg.reply('pong');
}
}); READY가 로그에 찍히고 답장이 도착하면 봇은 완전히 연결된 것입니다. 슬래시 명령어, 음성, 컴포넌트도 변경이 필요 없습니다.