Portal de Desarrolladores
Experimental La plataforma de bots y apps está en desarrollo activo. La compatibilidad con servidores autoalojados llegó el 13-08-2026 con menos funciones que la nube. Consulta qué se admite.
← Documentación

Snowflakes

GameVox devuelve IDs en el formato snowflake de 64 bits de Discord allí donde lo haría la API de Discord. La distribución de bits, el orden y las operaciones para extraer la marca de tiempo son idénticos: tu código actual de análisis de snowflakes funciona sin cambios.

Formato

Idéntico al de Discord: marca de tiempo de 42 bits + worker de 5 bits + proceso de 5 bits + contador de 12 bits, big-endian dentro de un entero de 64 bits sin signo.

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

Cada segmento coincide con Discord:

  • Marca de tiempo (42 bits) — milisegundos desde la época de GameVox, ver abajo.
  • ID de worker (5 bits) — se asigna a cada tarea api en ejecución al arrancar mediante un contador atómico en Redis.
  • ID de proceso (5 bits) — junto al worker forma un grupo de generación único.
  • Contador (12 bits) — secuencia por milisegundo y por (worker, proceso).

Época

GameVox usa la misma época que Discord: 1420070400000 (01/01/2015 00:00:00 UTC). Un analizador de snowflakes escrito para Discord funciona con los IDs de GameVox sin modificar — no hay ninguna constante que cambiar.

const SNOWFLAKE_EPOCH = 1420070400000n;

Formato de cable

Cada snowflake en el cable REST / gateway se serializa como cadena JSON, no como número. JavaScript pierde precisión por encima de Number.MAX_SAFE_INTEGER (253-1) y una snowflake lo supera con frecuencia. Analiza siempre con BigInt cuando necesites operar, y guárdala como cadena en el resto de casos.

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

// Incorrecto — pérdida silenciosa de precisión
const id = Number(message.id);

Extraer la marca de tiempo

JavaScript

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

console.log(snowflakeToDate('182955831900192769'));
// → objeto Date — cuándo se generó esta snowflake

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);

Orden

Como la marca de tiempo está en los bits altos, comparar dos snowflakes como cadenas las ordena cronológicamente, igual que en Discord. Por eso la paginación con before / after / around en el endpoint de mensajes funciona sin un campo de fecha explícito.

// En un array de mensajes, del más antiguo al más nuevo:
messages.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);

Datos nativos y la tabla de alias

Por dentro, los objetos nativos de GameVox (servidores, canales, usuarios, mensajes, etc.) usan UUIDv4. La capa de compatibilidad genera una snowflake estable la primera vez que un objeto se expone a un bot y guarda la correspondencia en la tabla snowflake_aliases. Cada referencia posterior a ese objeto —por REST o gateway— usa la misma snowflake.

En los mensajes rellenamos las snowflakes con el created_at del mensaje como marca de tiempo de origen, para que los mensajes históricos se ordenen bien cuando un bot entra por primera vez en un canal. Para todo lo demás el alias se genera de forma perezosa en la primera exposición usando NOW(), así que la snowflake refleja cuándo lo vio el bot, no necesariamente cuándo se creó.

Hash de sharding

La fórmula de shard estándar de Discord funciona tal cual:

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

Los bots con menos de 2.500 servidores funcionan en un solo shard ([0, 1]) y no necesitan pensar en esto. Los bots más grandes obtienen la misma distribución bastante uniforme que en Discord, porque los 42 bits superiores son monótonos en el tiempo, no aleatorios.

Detalles a tener en cuenta

  • No compares snowflakes con == contra un literal numérico. En el cable son cadenas: compara con una cadena o convierte ambas a BigInt.
  • La marca de tiempo de 42 bits desborda unos 139 años después de la época. Las snowflakes de GameVox son válidas hasta 2165.
  • No deduzcas la fecha de creación de un servidor / canal / rol a partir de su snowflake. Los objetos nativos anteriores a la plataforma de bots recibieron su snowflake en la primera exposición a un bot, no al crearse. Los mensajes son la excepción (rellenados con created_at).

← Volver a la documentación