/**

  • INSTRUCCIONES:
    1. Ve a https://script.google.com y crea un nuevo proyecto.
    1. Pega este código completo.
    1. Reemplaza FOLDER_ID con el ID de tu carpeta de Drive
  • (lo encuentras en la URL: …/folders/ESTE_ES_EL_ID)
    1. Ejecuta la función “iniciar” UNA SOLA VEZ.
    1. Autoriza los permisos que te pida (Drive, Sheets, Triggers).
    1. A partir de ahí el script se ejecuta SOLO cada 1 minuto, procesando
  • de 200 en 200 archivos, hasta terminar toda la carpeta.
    1. Cuando termine, el trigger se autoelimina y verás el mensaje
  • “PROCESO COMPLETADO” en el registro de ejecución (Ver > Registro).
  • Si necesitas cancelarlo a la mitad, ejecuta la función “detener”.
    */

var LOTE = 200; // Archivos por ejecución
var PROP = PropertiesService.getScriptProperties();

function iniciar() {
var FOLDER_ID = ‘1ompP8jvldiR4sGZf7xc_38rDJBO4eB57’;

// Si ya había un proceso previo sin terminar, lo limpiamos primero
detener();

var folder = DriveApp.getFolderById(FOLDER_ID);

// Crear spreadsheet nuevo, una sola vez
var ss = SpreadsheetApp.create(‘Links públicos - ’ + folder.getName());
var sheet = ss.getActiveSheet();
sheet.appendRow([‘Nombre del archivo’, ‘Link público’]);

PROP.setProperty(‘FOLDER_ID’, FOLDER_ID);
PROP.setProperty(‘SPREADSHEET_ID’, ss.getId());
PROP.setProperty(‘CONTADOR’, ‘0’);
PROP.deleteProperty(‘TOKEN’); // sin token = empieza desde el principio

Logger.log(‘Spreadsheet creado: ’ + ss.getUrl());
Logger.log(‘Iniciando procesamiento automático por lotes de ’ + LOTE + ’…’);

// Crear trigger que se ejecuta cada 1 minuto
ScriptApp.newTrigger(‘procesarLote’)
.timeBased()
.everyMinutes(1)
.create();

// Procesar el primer lote de inmediato
procesarLote();
}

function procesarLote() {
var folderId = PROP.getProperty(‘FOLDER_ID’);
var spreadsheetId = PROP.getProperty(‘SPREADSHEET_ID’);
var token = PROP.getProperty(‘TOKEN’);
var contador = parseInt(PROP.getProperty(‘CONTADOR’) || ‘0’, 10);

if (!folderId || !spreadsheetId) {
Logger.log(‘No hay un proceso activo. Ejecuta “iniciar” primero.’);
detener();
return;
}

var sheet = SpreadsheetApp.openById(spreadsheetId).getActiveSheet();

// Reanudar el iterador exactamente donde quedó (evita repetir archivos)
var archivos = token
? DriveApp.continueFileIterator(token)
: DriveApp.getFolderById(folderId).getFiles();

var filas = [];
var procesadosEnEsteLote = 0;

while (procesadosEnEsteLote < LOTE && archivos.hasNext()) {
var archivo = archivos.next();

// Compartir en modo público: cualquiera con el link puede ver
archivo.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);

filas.push([archivo.getName(), archivo.getUrl()]);
procesadosEnEsteLote++;
contador++;

}

if (filas.length > 0) {
sheet.getRange(sheet.getLastRow() + 1, 1, filas.length, 2).setValues(filas);
}

if (archivos.hasNext()) {
// Aún quedan archivos: guardar el punto exacto donde quedamos
PROP.setProperty(‘TOKEN’, archivos.getContinuationToken());
PROP.setProperty(‘CONTADOR’, String(contador));
Logger.log(‘Lote procesado. Total acumulado: ’ + contador + ’. Continuará en 1 minuto…’);
} else {
// Terminamos
Logger.log(‘PROCESO COMPLETADO. Total de archivos procesados: ’ + contador);
Logger.log(‘Spreadsheet final: ’ + SpreadsheetApp.openById(spreadsheetId).getUrl());
detener();
}
}

function detener() {
// Elimina todos los triggers de procesarLote
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === ‘procesarLote’) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
PROP.deleteProperty(‘TOKEN’);
PROP.deleteProperty(‘CONTADOR’);
// No borramos FOLDER_ID ni SPREADSHEET_ID por si quieres revisar logs,
// pero se sobreescriben si vuelves a ejecutar “iniciar”
}