Introducción

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

¿Cómo funciona?

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.

Estructura técnica de iTXt

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)

1. Datos de Licencia

Utilizado por el generador de licencias (id.html) y el protocolo LAG-ID.

KEYWORD convoyrama-data

FORMATO iTXt (UTF-8)

Estructura JSON Completa

{
  "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..."
}

2. Datos de Evento

Utilizado por el creador de flyers (event.html).

KEYWORD convoyrama-event-data

FORMATO iTXt (UTF-8)

Estructura JSON Completa

{
  "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..."
}

Implementación del Lector (Algoritmo Robusto)

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

Ejemplo en Node.js

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