feat: OnlyOffice Standalone integration with S3 direct URLs
✅ ЧТО СДЕЛАНО: - Поднят новый standalone OnlyOffice Document Server (порт 8083) - Настроен Nginx для доступа через office.clientright.ru:9443 - Создан open_file_v3_standalone.php для работы с новым OnlyOffice - Реализована поддержка прямых S3 URL (bucket публичный) - Добавлен s3_proxy.php с поддержкой Range requests - Создан onlyoffice_callback.php для сохранения (базовая версия) - Файлы успешно открываются и загружаются! ⚠️ TODO (на завтра): - Доработать onlyoffice_callback.php для сохранения обратно в ОРИГИНАЛЬНЫЙ путь в S3 - Добавить Redis маппинг documentKey → S3 path - Обновить CRM JS для использования open_file_v3_standalone.php - Протестировать сохранение файлов - Удалить тестовые файлы 📊 РЕЗУЛЬТАТ: - OnlyOffice Standalone РАБОТАЕТ! ✅ - Файлы открываются напрямую из S3 ✅ - Редактор загружается БЫСТРО ✅ - Автосохранение настроено ✅ (но нужна доработка callback)
This commit is contained in:
123
crm_extensions/file_storage/nextcloud_cache_updater.js
Executable file
123
crm_extensions/file_storage/nextcloud_cache_updater.js
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Nextcloud Cache Updater
|
||||
*
|
||||
* Подписывается на Redis канал crm:file:events
|
||||
* При новом файле - обновляет кеш Nextcloud для этого файла
|
||||
* БЕЗ полного сканирования всей папки!
|
||||
*/
|
||||
|
||||
const Redis = require('ioredis');
|
||||
const { exec } = require('child_process');
|
||||
const util = require('util');
|
||||
const execPromise = util.promisify(exec);
|
||||
|
||||
const CONFIG = {
|
||||
redis: {
|
||||
host: '147.45.146.17',
|
||||
port: 6379,
|
||||
password: 'CRM_Redis_Pass_2025_Secure!'
|
||||
},
|
||||
channel: 'crm:file:events',
|
||||
nextcloudContainer: 'nextcloud-fresh'
|
||||
};
|
||||
|
||||
const redis = new Redis(CONFIG.redis);
|
||||
|
||||
console.log('🔄 Nextcloud Cache Updater');
|
||||
console.log('==========================================');
|
||||
console.log(`📡 Подписка на: ${CONFIG.channel}`);
|
||||
console.log(`🐳 Nextcloud: ${CONFIG.nextcloudContainer}`);
|
||||
console.log('');
|
||||
|
||||
// Подписка на канал
|
||||
redis.subscribe(CONFIG.channel, (err, count) => {
|
||||
if (err) {
|
||||
console.error('❌ Ошибка подписки:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`✅ Подписка активна (${count} каналов)`);
|
||||
console.log('⏳ Ожидание событий...\n');
|
||||
});
|
||||
|
||||
// Обработка событий
|
||||
redis.on('message', async (channel, message) => {
|
||||
try {
|
||||
const event = JSON.parse(message);
|
||||
|
||||
// Логируем событие
|
||||
const timestamp = new Date().toISOString();
|
||||
console.log(`[${timestamp}] 📥 Событие:`);
|
||||
console.log(` Type: ${event.type}`);
|
||||
console.log(` Source: ${event.source}`);
|
||||
console.log(` Path: ${event.path || event.filename}`);
|
||||
|
||||
// Обрабатываем только создание/изменение файлов
|
||||
if (!['file_created', 'file_modified', 'file_update'].includes(event.type)) {
|
||||
console.log(` ⏭️ Пропуск (не файловое событие)\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Извлекаем путь файла
|
||||
let filePath = event.path || event.filename;
|
||||
|
||||
// Для событий из S3 Monitor - путь уже правильный
|
||||
// Для событий из Nextcloud - может быть без префикса
|
||||
|
||||
// Формируем путь для Nextcloud
|
||||
let ncPath = filePath;
|
||||
if (!ncPath.startsWith('/')) {
|
||||
ncPath = '/admin/files/crm/' + ncPath;
|
||||
}
|
||||
|
||||
console.log(` 🔄 Обновление кеша Nextcloud...`);
|
||||
console.log(` Путь: ${ncPath}`);
|
||||
|
||||
// Обновляем кеш только для этого файла
|
||||
const command = `docker exec -u www-data ${CONFIG.nextcloudContainer} php occ files:scan --path="${ncPath}" 2>&1`;
|
||||
|
||||
try {
|
||||
const { stdout, stderr } = await execPromise(command);
|
||||
|
||||
if (stderr && !stderr.includes('Starting scan')) {
|
||||
console.log(` ⚠️ Предупреждение: ${stderr}`);
|
||||
}
|
||||
|
||||
console.log(` ✅ Кеш обновлён`);
|
||||
|
||||
// Дополнительно очищаем statcache для этой папки
|
||||
const dirname = ncPath.substring(0, ncPath.lastIndexOf('/'));
|
||||
const clearCommand = `docker exec -u www-data ${CONFIG.nextcloudContainer} php occ files:scan --path="${dirname}" --shallow 2>&1`;
|
||||
await execPromise(clearCommand);
|
||||
|
||||
console.log(` ✅ Родительская папка обновлена\n`);
|
||||
|
||||
} catch (execError) {
|
||||
console.error(` ❌ Ошибка обновления: ${execError.message}\n`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Ошибка обработки события:`, error.message);
|
||||
console.error(` Сообщение:`, message.substring(0, 200));
|
||||
console.log('');
|
||||
}
|
||||
});
|
||||
|
||||
// Обработка ошибок
|
||||
redis.on('error', (err) => {
|
||||
console.error('❌ Redis ошибка:', err);
|
||||
});
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n\n🛑 Остановка...');
|
||||
redis.disconnect();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('\n\n🛑 Остановка...');
|
||||
redis.disconnect();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user