الملفات
codepill-sfu/app/src/HtmlInjector.js
2025-03-22 20:37:03 +01:00

112 أسطر
3.8 KiB
JavaScript

const fs = require('fs');
const chokidar = require('chokidar');
const Logger = require('./Logger');
const log = new Logger('HtmlInjector');
class HtmlInjector {
constructor(filesPath, config) {
this.filesPath = filesPath; // Array of file paths to cache
this.cache = {}; // Object to store cached files
this.config = config; // Configuration containing metadata (OG, title, etc.)
this.injectData = this.getInjectData(); // Initialize dynamic injection data
this.watcher = null; // File watcher instance
this.preloadPages(filesPath); // Preload pages at startup
this.watchFiles(filesPath); // Watch files for changes
log.info('filesPath cached', this.filesPath);
}
// Function to get dynamic data for injection (e.g., OG data, title, etc.)
getInjectData() {
return {
OG_TYPE: this.config?.og?.type || 'app-webrtc',
OG_SITE_NAME: this.config?.og?.siteName || 'MiroTalk SFU',
OG_TITLE: this.config?.og?.title || 'Click the link to make a call.',
OG_DESCRIPTION:
this.config?.og?.description ||
'MiroTalk SFU calling provides real-time video calls, messaging and screen sharing.',
OG_IMAGE: this.config?.og?.image || 'https://sfu.mirotalk.com/images/mirotalksfu.png',
OG_URL: this.config?.og?.url || 'https://sfu.mirotalk.com',
// Add more data here as needed with fallbacks
};
}
// Function to load a file into the cache
loadFileToCache(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
this.cache[filePath] = content; // Store the content in cache
} catch (err) {
log.error(`Error reading file: ${filePath}`, err);
}
}
// Function to preload pages into the cache
preloadPages(filePaths) {
filePaths.forEach((filePath) => this.loadFileToCache(filePath));
}
// Function to watch files for changes using chokidar
watchFiles(filePaths) {
if (this.watcher) {
this.watcher.close(); // Close existing watcher if any
}
this.watcher = chokidar.watch(filePaths, {
persistent: true,
ignoreInitial: true, // Ignore initial 'add' events
});
this.watcher
.on('change', (filePath) => {
log.debug(`File changed: ${filePath}`);
this.loadFileToCache(filePath);
log.debug(`Reloaded file ${filePath} into cache`);
})
.on('error', (error) => {
log.error(`Watcher error: ${error.message}`);
});
}
// Function to inject dynamic data (e.g., OG, TITLE, etc.) into a given file
injectHtml(filePath, res) {
// return res.send(this.cache[filePath]);
if (!this.cache[filePath]) {
log.error(`File not cached: ${filePath}`);
if (!res.headersSent) {
return res.status(500).send('Server Error');
}
return;
}
try {
// Replace placeholders with dynamic data (OG, TITLE, etc.)
const modifiedHTML = this.cache[filePath].replace(
/{{(OG_[A-Z_]+)}}/g,
(_, key) => this.injectData[key] || '',
);
if (!res.headersSent) {
res.send(modifiedHTML);
}
} catch (error) {
log.error('Error injecting HTML data:', error);
if (!res.headersSent) {
res.status(500).send('Server Error');
}
}
}
// Cleanup watcher when the instance is no longer needed
cleanup() {
if (this.watcher) {
this.watcher.close();
}
}
}
module.exports = HtmlInjector;