@@ -12,7 +12,7 @@ const translations = {
1212 initialMessage : "Haz clic en \"Generar Serial\"" ,
1313 generating : "Generando..." ,
1414 errorPrefix : "Error:" ,
15- errorMessage : "Asegúrate de que tu navegador soporta Web Crypto API y los valores son válidos ." ,
15+ errorMessage : "Intenta recargar la página o usa un navegador más reciente ." ,
1616 copyError : "No se pudo copiar el serial. Por favor, cópialo manualmente." ,
1717 generatorTab : "Generar Serial" ,
1818 decoderTab : "Decodificar Fecha" ,
@@ -36,7 +36,7 @@ const translations = {
3636 initialMessage : "Click \"Generate Serial\"" ,
3737 generating : "Generating..." ,
3838 errorPrefix : "Error:" ,
39- errorMessage : "Make sure your browser supports Web Crypto API and the values are valid ." ,
39+ errorMessage : "Try refreshing the page or use a more recent browser ." ,
4040 copyError : "Could not copy the serial. Please copy it manually." ,
4141 generatorTab : "Generate Serial" ,
4242 decoderTab : "Decode Date" ,
@@ -81,6 +81,11 @@ async function generateHighEntropySerialNumber(
8181 totalRandomLength = 24 ,
8282 prefix = null
8383) {
84+ // Verificar si Web Crypto API está disponible
85+ if ( ! window . crypto || ! window . crypto . getRandomValues ) {
86+ throw new Error ( 'Web Crypto API no está disponible en este navegador' ) ;
87+ }
88+
8489 // Validaciones y Ajustes de Parámetros
8590 const validatedSegmentLength = Math . max ( 1 , Math . min ( 12 , segmentLength ) ) ;
8691 const validatedTotalRandomLength = Math . max ( 6 , Math . min ( 50 , totalRandomLength ) ) ;
@@ -96,8 +101,13 @@ async function generateHighEntropySerialNumber(
96101
97102 const getSecureRandomByte = ( ) => {
98103 if ( byteBufferIndex >= BYTE_BUFFER_SIZE ) {
99- window . crypto . getRandomValues ( byteBuffer ) ;
100- byteBufferIndex = 0 ;
104+ try {
105+ window . crypto . getRandomValues ( byteBuffer ) ;
106+ byteBufferIndex = 0 ;
107+ } catch ( error ) {
108+ console . error ( 'Error con getRandomValues:' , error ) ;
109+ throw new Error ( 'No se pudieron generar valores aleatorios seguros' ) ;
110+ }
101111 }
102112 return byteBuffer [ byteBufferIndex ++ ] ;
103113 } ;
@@ -142,6 +152,61 @@ async function generateHighEntropySerialNumber(
142152 return finalSerialParts . join ( '-' ) ;
143153}
144154
155+ // Función de respaldo usando Math.random() si Web Crypto API falla
156+ function generateFallbackSerialNumber (
157+ segmentLength = 6 ,
158+ totalRandomLength = 24 ,
159+ prefix = null
160+ ) {
161+ console . warn ( 'Usando generador de respaldo con Math.random()' ) ;
162+
163+ // Validaciones y Ajustes de Parámetros
164+ const validatedSegmentLength = Math . max ( 1 , Math . min ( 12 , segmentLength ) ) ;
165+ const validatedTotalRandomLength = Math . max ( 6 , Math . min ( 50 , totalRandomLength ) ) ;
166+
167+ // Configuración de Caracteres
168+ const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
169+ const charsLength = chars . length ;
170+
171+ // 1. Generar la Parte de la Marca de Tiempo
172+ const timestampPart = Date . now ( ) . toString ( 36 ) . toUpperCase ( ) ;
173+
174+ // 2. Generar los Caracteres Aleatorios usando Math.random()
175+ let rawRandomChars = '' ;
176+ for ( let i = 0 ; i < validatedTotalRandomLength ; i ++ ) {
177+ const randomIndex = Math . floor ( Math . random ( ) * charsLength ) ;
178+ rawRandomChars += chars [ randomIndex ] ;
179+ }
180+
181+ // 3. Formato de la Parte Aleatoria con Guiones
182+ let formattedRandomPart = '' ;
183+ let currentPos = 0 ;
184+
185+ while ( currentPos < validatedTotalRandomLength ) {
186+ const remainingLength = validatedTotalRandomLength - currentPos ;
187+ const currentSegmentLength = Math . min ( validatedSegmentLength , remainingLength ) ;
188+
189+ formattedRandomPart += rawRandomChars . substring ( currentPos , currentPos + currentSegmentLength ) ;
190+ currentPos += currentSegmentLength ;
191+
192+ if ( currentPos < validatedTotalRandomLength ) {
193+ formattedRandomPart += '-' ;
194+ }
195+ }
196+
197+ // 4. Construir el Serial Final
198+ const finalSerialParts = [ ] ;
199+
200+ if ( prefix && String ( prefix ) . trim ( ) . length > 0 ) {
201+ finalSerialParts . push ( String ( prefix ) . toUpperCase ( ) . trim ( ) ) ;
202+ }
203+
204+ finalSerialParts . push ( timestampPart ) ;
205+ finalSerialParts . push ( formattedRandomPart ) ;
206+
207+ return finalSerialParts . join ( '-' ) ;
208+ }
209+
145210// Función para decodificar la fecha de un serial
146211function decodeSerialTimestamp ( serial ) {
147212 if ( ! serial || typeof serial !== 'string' ) {
@@ -298,25 +363,59 @@ function updateUI() {
298363
299364// Función para manejar la generación del serial
300365async function handleGenerateSerial ( ) {
366+ console . log ( 'handleGenerateSerial called' ) ; // Debug
367+
301368 const t = translations [ currentLanguage ] ;
302369 const serialOutput = document . getElementById ( 'serialOutput' ) ;
303370 const copyButton = document . getElementById ( 'copyButton' ) ;
304371
372+ if ( ! serialOutput ) {
373+ console . error ( 'serialOutput element not found' ) ;
374+ return ;
375+ }
376+
377+ if ( ! copyButton ) {
378+ console . error ( 'copyButton element not found' ) ;
379+ return ;
380+ }
381+
305382 serialOutput . textContent = t . generating ;
306383 serialOutput . style . color = '#72ef72' ; // Resetear color a verde
307384 copyButton . classList . remove ( 'copied' ) ; // Asegurar que el botón de copiar no esté en estado "copiado"
308385 copyButton . textContent = t . copyButton ; // Resetear texto del botón de copiar
309386
310387 try {
311- const segmentLen = parseInt ( document . getElementById ( 'segmentLength' ) . value ) ;
312- const totalRandomLen = parseInt ( document . getElementById ( 'totalRandomLength' ) . value ) ;
313- const prefixVal = document . getElementById ( 'prefix' ) . value . trim ( ) ;
314-
315- const generatedSerial = await generateHighEntropySerialNumber (
316- segmentLen ,
317- totalRandomLen ,
318- prefixVal
319- ) ;
388+ const segmentLenElement = document . getElementById ( 'segmentLength' ) ;
389+ const totalRandomLenElement = document . getElementById ( 'totalRandomLength' ) ;
390+ const prefixElement = document . getElementById ( 'prefix' ) ;
391+
392+ if ( ! segmentLenElement || ! totalRandomLenElement || ! prefixElement ) {
393+ throw new Error ( 'No se pudieron encontrar los elementos del formulario' ) ;
394+ }
395+
396+ const segmentLen = parseInt ( segmentLenElement . value ) || 6 ;
397+ const totalRandomLen = parseInt ( totalRandomLenElement . value ) || 24 ;
398+ const prefixVal = prefixElement . value . trim ( ) ;
399+
400+ console . log ( 'Generating serial with params:' , { segmentLen, totalRandomLen, prefixVal } ) ; // Debug
401+
402+ let generatedSerial ;
403+ try {
404+ generatedSerial = await generateHighEntropySerialNumber (
405+ segmentLen ,
406+ totalRandomLen ,
407+ prefixVal
408+ ) ;
409+ } catch ( cryptoError ) {
410+ console . warn ( 'Web Crypto API falló, usando método de respaldo:' , cryptoError ) ;
411+ generatedSerial = generateFallbackSerialNumber (
412+ segmentLen ,
413+ totalRandomLen ,
414+ prefixVal
415+ ) ;
416+ }
417+
418+ console . log ( 'Generated serial:' , generatedSerial ) ; // Debug
320419
321420 currentSerial = generatedSerial ;
322421 serialOutput . textContent = generatedSerial ;
@@ -351,6 +450,18 @@ function copyToClipboard() {
351450
352451// Inicialización cuando el DOM esté listo
353452document . addEventListener ( 'DOMContentLoaded' , ( ) => {
453+ console . log ( 'DOM Content Loaded' ) ; // Debug
454+
455+ // Verificar que todos los elementos críticos existan
456+ const requiredElements = [ 'title' , 'generateButton' , 'serialOutput' , 'copyButton' ] ;
457+ const missingElements = requiredElements . filter ( id => ! document . getElementById ( id ) ) ;
458+
459+ if ( missingElements . length > 0 ) {
460+ console . error ( 'Elementos críticos faltantes:' , missingElements ) ;
461+ alert ( 'Error: La página no se cargó correctamente. Elementos faltantes: ' + missingElements . join ( ', ' ) ) ;
462+ return ;
463+ }
464+
354465 // Cargar preferencias del localStorage
355466 const savedLanguage = localStorage . getItem ( 'preferredLanguage' ) || 'en-US' ;
356467 const savedTab = localStorage . getItem ( 'preferredTab' ) || 'generator' ;
0 commit comments