Las herramientas de Convoyrama no solo crean imágenes visuales, sino que también incrustan metadatos estructurados (JSON) dentro de los archivos PNG generados. Esto permite que bots de Discord y otras aplicaciones lean la información directamente desde la imagen sin necesidad de OCR, soportando UTF-8 nativo (acentos, emojis y caracteres especiales).
Los datos se almacenan en un chunk auxiliar de tipo iTXt (International Text) dentro de la estructura del PNG. Este formato es el estándar moderno para texto internacional y asegura que la codificación sea siempre UTF-8. Usamos claves específicas (Keywords) para diferenciar el tipo de contenido.
Para decodificar manualmente el bloque, se debe seguir este orden de bytes:
1. Keyword: (1-79 bytes) + [00] (Separador nulo)
2. Compression Flag: [00] (1 byte, 0 = sin comprimir)
3. Compression Method: [00] (1 byte, 0 = deflate)
4. Language Tag: (0+ bytes) + [00] (Separador nulo)
5. Translated Keyword: (0+ bytes) + [00] (Separador nulo)
6. Text Data: (Resto del bloque en UTF-8)
Utilizado por el generador de licencias (id.html) y el protocolo LAG-ID.
KEYWORD convoyrama-data
FORMATO iTXt (UTF-8)
{
"name": "Nombre del Usuario",
"license_number": "UY12345",
"country": "UY", // ISO 3166-1 alpha-2
"rank": 5, // Nivel (1-12)
"is_verified": true,
"tmp_join_date": "2020-01-15 14:30:00",
"truckersmp_link": "https://truckersmp.com/user/123",
"vtc_link": "https://truckersmp.com/vtc/456",
"social_network": "instagram",
"social_link": "https://...",
"generated_at": "2026-05-04T..."
}
Utilizado por el creador de flyers (event.html).
KEYWORD convoyrama-event-data
FORMATO iTXt (UTF-8)
{
"eventName": "Nombre del Convoy",
"eventLink": "https://...",
"startPlace": "Ciudad A",
"destination": "Ciudad B",
"server": "Simulation 1",
"description": "Ruta detallada...",
"meetingTimestamp": 1704067200, // Unix Seconds
"departureTimestamp": 1704068100,
"arrivalTimestamp": 1704070800,
"meetingGameTime": { "hours": 20, "minutes": 40 },
"arrivalGameTime": { "hours": 2, "minutes": 15 },
"ianaTimeZone": "America/Montevideo",
"generatedAt": "2026-05-04T..."
}
Para garantizar la compatibilidad con caracteres UTF-8 y evitar errores por variaciones en los separadores nulos, el algoritmo recomendado para parsear un chunk iTXt es:
// 1. Identificar el Keyword (primeros bytes hasta el nulo 00)
const keyword = data.slice(0, data.indexOf(0)).toString('utf8');
// 2. Localizar el inicio del JSON buscando el carácter '{'
// (Evita errores de desplazamiento por flags o tags de idioma)
const jsonStart = data.indexOf(123); // 123 es '{'
// 3. Extraer y parsear el resto como UTF-8
const jsonText = data.slice(jsonStart).toString('utf8');
const metadata = JSON.parse(jsonText);
Usando la librería png-chunks-extract:
const extract = require('png-chunks-extract');
const chunks = extract(imageBuffer);
const chunk = chunks.find(c => c.name === 'iTXt' || c.name === 'tEXt');
if (chunk) {
const data = Buffer.from(chunk.data);
const jsonStart = data.indexOf(123);
if (jsonStart !== -1) {
const json = JSON.parse(data.slice(jsonStart).toString('utf8'));
console.log("Evento:", json.eventName);
}
}