Portal do Desenvolvedor
Experimental A plataforma de bots e apps está em desenvolvimento ativo. O suporte a servidores auto-hospedados chegou em 13/08/2026 com menos recursos que a nuvem. Veja o que é suportado.
← Documentação

Snowflakes

O GameVox devolve IDs no formato snowflake de 64 bits do Discord sempre que a API do Discord faria isso. A disposição dos bits, a ordenação e a matemática de extração do carimbo de tempo são idênticas — seu código de análise atual funciona sem mudanças.

Formato

Idêntico ao do Discord: carimbo de 42 bits + worker de 5 bits + processo de 5 bits + contador de 12 bits, big-endian dentro de um inteiro de 64 bits sem sinal.

┌─ 42 bits ─────────────────┬─ 5 ─┬─ 5 ─┬─ 12 ────────┐
│ ms desde a época GameVox  │ wkr │ prc │ increment   │
└───────────────────────────┴─────┴─────┴─────────────┘
 63                       22  21 17 16 12 11           0

Cada segmento corresponde ao do Discord:

  • Carimbo de tempo (42 bits) — milissegundos desde a época do GameVox, veja abaixo.
  • ID do worker (5 bits) — atribuído a cada tarefa api em execução na inicialização, via contador atômico no Redis.
  • ID do processo (5 bits) — junto com o worker forma um pool de geração único.
  • Contador (12 bits) — sequência por milissegundo, por (worker, processo).

Época

O GameVox usa a mesma época do Discord: 1420070400000 (01/01/2015 00:00:00 UTC). Um analisador de snowflakes escrito para o Discord funciona com IDs do GameVox sem modificação — nenhuma constante para trocar.

const SNOWFLAKE_EPOCH = 1420070400000n;

Formato de transporte

Toda snowflake no transporte REST / gateway é serializada como string JSON, não como número. O JavaScript perde precisão acima de Number.MAX_SAFE_INTEGER (253-1) e uma snowflake passa disso com frequência. Sempre analise via BigInt quando precisar fazer contas, e guarde como string no resto dos casos.

// Correto
const id = BigInt(message.id);

// Errado — perda silenciosa de precisão
const id = Number(message.id);

Extraindo o carimbo de tempo

JavaScript

function snowflakeToDate(snowflake) {
  const EPOCH = 1420070400000n;          // igual ao Discord
  const ms = Number((BigInt(snowflake) >> 22n) + EPOCH);
  return new Date(ms);
}

console.log(snowflakeToDate('182955831900192769'));
// → objeto Date — quando esta snowflake foi gerada

Python

from datetime import datetime, timezone

SNOWFLAKE_EPOCH = 1420070400000

def snowflake_to_dt(snowflake):
    ms = (int(snowflake) >> 22) + SNOWFLAKE_EPOCH
    return datetime.fromtimestamp(ms / 1000, tz=timezone.utc)

Java

long SNOWFLAKE_EPOCH = 1420070400000L;
long ms = (Long.parseUnsignedLong(snowflake) >>> 22) + SNOWFLAKE_EPOCH;
Instant when = Instant.ofEpochMilli(ms);

Ordenação

Como o carimbo fica nos bits mais altos, comparar duas snowflakes como strings já as ordena cronologicamente — igual ao Discord. É por isso que a paginação com before / after / around no endpoint de mensagens funciona sem um campo de data explícito.

// Em um array de mensagens, da mais antiga à mais nova:
messages.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);

Dados nativos e a tabela de alias

Internamente, os objetos nativos do GameVox (servidores, canais, usuários, mensagens etc.) usam UUIDv4. A camada de compatibilidade gera uma snowflake estável na primeira vez que um objeto é exposto a um bot e guarda o par na tabela snowflake_aliases. Toda referência posterior a esse objeto — por REST ou gateway — usa a mesma snowflake.

Para mensagens, preenchemos as snowflakes retroativamente com o created_at da mensagem como carimbo de origem, para que mensagens antigas ordenem corretamente quando um bot entra num canal pela primeira vez. Para todo o resto o alias é gerado sob demanda na primeira exposição, com NOW() como carimbo, então a snowflake reflete quando o bot viu o objeto, não necessariamente quando ele foi criado.

Hash de sharding

A fórmula de shard padrão do Discord funciona sem alteração:

shardId = (BigInt(guildId) >> 22n) % BigInt(numShards);

Bots com menos de 2.500 servidores rodam em um único shard ([0, 1]) e não precisam pensar nisso. Bots maiores obtêm a mesma distribuição razoavelmente uniforme do Discord, porque os 42 bits mais altos são monotônicos no tempo, não aleatórios.

Pegadinhas

  • Não compare snowflakes com == contra um literal numérico. No transporte são strings — compare com uma string ou converta as duas para BigInt.
  • O carimbo de 42 bits estoura cerca de 139 anos após a época. As snowflakes do GameVox valem até 2165.
  • Não deduza a data de criação de um servidor / canal / cargo a partir da snowflake dele. Objetos nativos anteriores à plataforma de bots ganharam a snowflake na primeira exposição a um bot, não na criação. As mensagens são exceção (preenchidas com created_at).

← Voltar para a documentação