const listmonkService = require('../services/listmonk'); const nocodbService = require('../services/nocodb'); const logger = require('../utils/logger'); // Get Listmonk sync status exports.getSyncStatus = async (req, res) => { try { const status = listmonkService.getSyncStatus(); // Also check connection if it's enabled if (status.enabled && !status.connected) { // Try to reconnect const reconnected = await listmonkService.checkConnection(); status.connected = reconnected; } res.json(status); } catch (error) { logger.error('Failed to get Listmonk status', error); res.status(500).json({ success: false, error: 'Failed to get sync status' }); } }; // Sync all campaign participants to Listmonk exports.syncCampaignParticipants = async (req, res) => { try { if (!listmonkService.syncEnabled) { return res.status(400).json({ success: false, error: 'Listmonk sync is disabled' }); } // Get all campaign emails (use campaignEmails table, not emails) const emailsData = await nocodbService.getAll(nocodbService.tableIds.campaignEmails); const emails = emailsData?.list || []; // Get all campaigns for reference const campaigns = await nocodbService.getAllCampaigns(); if (!emails || emails.length === 0) { return res.json({ success: true, message: 'No campaign participants to sync', results: { total: 0, success: 0, failed: 0, errors: [] } }); } const results = await listmonkService.bulkSyncCampaignParticipants(emails, campaigns); res.json({ success: true, message: `Campaign participants sync completed: ${results.success} succeeded, ${results.failed} failed`, results }); } catch (error) { logger.error('Campaign participants sync failed', error); res.status(500).json({ success: false, error: 'Failed to sync campaign participants to Listmonk' }); } }; // Sync all custom recipients to Listmonk exports.syncCustomRecipients = async (req, res) => { try { if (!listmonkService.syncEnabled) { return res.status(400).json({ success: false, error: 'Listmonk sync is disabled' }); } // Get all custom recipients const recipientsData = await nocodbService.getAll(nocodbService.tableIds.customRecipients); const recipients = recipientsData?.list || []; // Get all campaigns for reference const campaigns = await nocodbService.getAllCampaigns(); if (!recipients || recipients.length === 0) { return res.json({ success: true, message: 'No custom recipients to sync', results: { total: 0, success: 0, failed: 0, errors: [] } }); } const results = await listmonkService.bulkSyncCustomRecipients(recipients, campaigns); res.json({ success: true, message: `Custom recipients sync completed: ${results.success} succeeded, ${results.failed} failed`, results }); } catch (error) { logger.error('Custom recipients sync failed', error); res.status(500).json({ success: false, error: 'Failed to sync custom recipients to Listmonk' }); } }; // Sync everything (participants and custom recipients) exports.syncAll = async (req, res) => { try { if (!listmonkService.syncEnabled) { return res.status(400).json({ success: false, error: 'Listmonk sync is disabled' }); } let results = { participants: { total: 0, success: 0, failed: 0, errors: [] }, customRecipients: { total: 0, success: 0, failed: 0, errors: [] } }; // Get campaigns once for both syncs const campaigns = await nocodbService.getAllCampaigns(); // Sync campaign participants try { const emailsData = await nocodbService.getAll(nocodbService.tableIds.campaignEmails); const emails = emailsData?.list || []; if (emails && emails.length > 0) { results.participants = await listmonkService.bulkSyncCampaignParticipants(emails, campaigns); } } catch (error) { logger.error('Failed to sync campaign participants during full sync', error); results.participants.errors.push({ error: error.message }); } // Sync custom recipients try { const recipientsData = await nocodbService.getAll(nocodbService.tableIds.customRecipients); const recipients = recipientsData?.list || []; if (recipients && recipients.length > 0) { results.customRecipients = await listmonkService.bulkSyncCustomRecipients(recipients, campaigns); } } catch (error) { logger.error('Failed to sync custom recipients during full sync', error); results.customRecipients.errors.push({ error: error.message }); } const totalSuccess = results.participants.success + results.customRecipients.success; const totalFailed = results.participants.failed + results.customRecipients.failed; res.json({ success: true, message: `Complete sync finished: ${totalSuccess} succeeded, ${totalFailed} failed`, results }); } catch (error) { logger.error('Complete sync failed', error); res.status(500).json({ success: false, error: 'Failed to perform complete sync' }); } }; // Get Listmonk list statistics exports.getListStats = async (req, res) => { try { if (!listmonkService.syncEnabled) { return res.json({ success: false, error: 'Listmonk sync is disabled', stats: null }); } const stats = await listmonkService.getListStats(); // Convert stats object to array format for frontend let statsArray = []; if (stats && typeof stats === 'object') { statsArray = Object.entries(stats).map(([key, list]) => ({ id: key, name: list.name, subscriberCount: list.subscriber_count || 0, description: `Email list for ${key}` })); } res.json({ success: true, stats: statsArray }); } catch (error) { logger.error('Failed to get Listmonk list stats', error); res.status(500).json({ success: false, error: 'Failed to get list statistics' }); } }; // Test Listmonk connection exports.testConnection = async (req, res) => { try { const connected = await listmonkService.checkConnection(); if (connected) { res.json({ success: true, message: 'Listmonk connection successful', connected: true }); } else { res.json({ success: false, message: listmonkService.lastError || 'Connection failed', connected: false }); } } catch (error) { logger.error('Failed to test Listmonk connection', error); res.status(500).json({ success: false, error: 'Failed to test connection' }); } }; // Reinitialize Listmonk lists exports.reinitializeLists = async (req, res) => { try { if (!listmonkService.syncEnabled) { return res.status(400).json({ success: false, error: 'Listmonk sync is disabled' }); } const initialized = await listmonkService.initializeLists(); if (initialized) { res.json({ success: true, message: 'Listmonk lists reinitialized successfully' }); } else { res.json({ success: false, message: listmonkService.lastError || 'Failed to initialize lists' }); } } catch (error) { logger.error('Failed to reinitialize Listmonk lists', error); res.status(500).json({ success: false, error: 'Failed to reinitialize lists' }); } };