/** * DocuGenerate Google Docs Sync Script * * This script automatically syncs Google Docs with DocuGenerate templates. * When a document in the monitored folder is modified, it updates the corresponding * template in DocuGenerate, or creates a new one if it doesn't exist. */ // Configuration - Users need to set these values const CONFIG = { DOCUGENERATE_API_KEY: 'YOUR_API_KEY_HERE', // Get from DocuGenerate settings DOCUGENERATE_BASE_URL: 'https://api.docugenerate.com/v1', // Change region if needed MONITORED_FOLDER_ID: 'YOUR_FOLDER_ID_HERE' // Google Drive folder ID to monitor }; /** * Manual sync function - syncs all documents in the monitored folder * Useful for initial setup or bulk sync */ function manualSync() { try { console.log('Starting manual sync of all documents...'); const folder = DriveApp.getFolderById(CONFIG.MONITORED_FOLDER_ID); console.log(`Processing folder: ${folder.getName()}`); const files = folder.getFilesByType(MimeType.GOOGLE_DOCS); while (files.hasNext()) { const file = files.next(); console.log(`Processing: ${file.getName()}`); syncDocument(file); } console.log('Manual sync completed!'); } catch (error) { console.error('Error in manual sync:', error); } } /** * Sets up automatic sync with time-based triggers * Run this function once to initialize the sync */ function setupAutoSync() { try { // Delete existing triggers to avoid duplicates const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(trigger => { if (trigger.getHandlerFunction() === 'autoSync') { ScriptApp.deleteTrigger(trigger); } }); // Create time-based trigger that runs every 5 minutes ScriptApp.newTrigger('autoSync') .timeBased() .everyMinutes(5) .create(); console.log('Auto-sync setup completed successfully!'); console.log('Monitored folder:', CONFIG.MONITORED_FOLDER_ID); } catch (error) { console.error('Error setting up auto-sync:', error); } } /** * Automatically checks for modified documents and syncs them * This function is called automatically every 5 minutes */ function autoSync() { try { console.log('Running auto-sync check...'); const folder = DriveApp.getFolderById(CONFIG.MONITORED_FOLDER_ID); const files = folder.getFilesByType(MimeType.GOOGLE_DOCS); // Check for files modified in the last 5 minutes const lastCheck = new Date(Date.now() - 5 * 60 * 1000); let modifiedCount = 0; while (files.hasNext()) { const file = files.next(); // Check if file was modified recently if (file.getLastUpdated() > lastCheck) { console.log(`Auto-syncing recently modified document: ${file.getName()}`); syncDocument(file); modifiedCount++; } } if (modifiedCount === 0) { console.log('No recently modified documents found'); } else { console.log(`Synced ${modifiedCount} modified document(s)`); } } catch (error) { console.error('Error in periodic sync:', error); } } /** * Syncs a Google Doc to DocuGenerate */ function syncDocument(doc) { try { const docId = doc.getId(); const docName = doc.getName(); console.log(`Syncing document: ${docName} (${docId})`); // Check if document already has a template ID const docMetadata = Drive.Files.get(docId, { fields: 'properties' }); const docProperties = docMetadata.properties || {}; const existingTemplateId = docProperties['docugenerate_template_id']; // Convert Google Doc to Word format const wordBlob = convertToWordFormat(docId, docName); if (existingTemplateId) { console.log(`Updating existing template: ${existingTemplateId}`); updateTemplate(existingTemplateId, wordBlob, docName); } else { console.log('Creating new template'); const templateId = createTemplate(wordBlob, docName); if (templateId) { // Store the template ID in document properties Drive.Files.update({ properties: { 'docugenerate_template_id': templateId } }, docId); } } } catch (error) { console.error('Error syncing document:', error); } } /** * Converts a Google Doc to Word format (.docx) */ function convertToWordFormat(docId, docName) { try { // Export as Word document const url = `https://docs.google.com/document/d/${docId}/export?format=docx`; const response = UrlFetchApp.fetch(url, { headers: { 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() } }); // Return blob with proper name and content type return response.getBlob() .setName(`${docName}.docx`) .setContentType(MimeType.MICROSOFT_WORD); } catch (error) { console.error('Error converting to Word format:', error); throw error; } } /** * Creates a new template in DocuGenerate */ function createTemplate(wordBlob, templateName) { try { const payload = { 'file': wordBlob, 'name': templateName }; const options = { method: 'POST', headers: { 'Authorization': CONFIG.DOCUGENERATE_API_KEY // Don't set Content-Type - Apps Script will handle it automatically }, payload: payload }; const response = UrlFetchApp.fetch( `${CONFIG.DOCUGENERATE_BASE_URL}/template`, options ); if (response.getResponseCode() === 201) { const responseData = JSON.parse(response.getContentText()); console.log('Template created successfully:', responseData.id); return responseData.id; } else { console.error('Error creating template:', response.getContentText()); return null; } } catch (error) { console.error('Error creating template:', error); return null; } } /** * Updates an existing template in DocuGenerate */ function updateTemplate(templateId, wordBlob, templateName) { try { const payload = { 'file': wordBlob, 'name': templateName }; const options = { method: 'PUT', headers: { 'Authorization': CONFIG.DOCUGENERATE_API_KEY // Don't set Content-Type - Apps Script will handle it automatically }, payload: payload }; const response = UrlFetchApp.fetch( `${CONFIG.DOCUGENERATE_BASE_URL}/template/${templateId}`, options ); if (response.getResponseCode() === 200) { const responseData = JSON.parse(response.getContentText()); console.log('Template updated successfully:', templateId); return true; } else { console.error('Error updating template:', response.getContentText()); return false; } } catch (error) { console.error('Error updating template:', error); return false; } }