Skip to content

Commit

Permalink
[mirotalkwebrtc] - make OG customizable, add Language, improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
miroslavpejic85 committed Jan 31, 2025
1 parent 6e9b127 commit 91d2454
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 56 deletions.
9 changes: 9 additions & 0 deletions backend/config.template.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
'use strict';

module.exports = {
Language: 'en', // https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
App: {
Name: 'MiroTalk',
Logo: '../Images/logo.png',
},
OG: {
type: 'app-webrtc',
siteName: 'MiroTalk WebRTC',
title: 'Click the link to schedule the Meeting',
description: 'MiroTalk WEB Easy Room Scheduler for Meetings & Video Conferencing.',
image: 'https://webrtc.mirotalk.com/Images/mirotalk-bro.png',
url: 'https://webrtc.mirotalk.com',
},
Author: {
Email: '[email protected]',
Profile: 'https://www.linkedin.com/in/miroslav-pejic-976a07101/',
Expand Down
13 changes: 9 additions & 4 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const url = require('./middleware/url');
const corsOptions = require('./config/cors');
const cors = require('cors');
const compression = require('compression');
const HtmlInjector = require('./utils/HtmlInjector');
const helmet = require('helmet');
const api = require('./routes/api');
const room = require('./routes/room');
Expand Down Expand Up @@ -49,15 +50,19 @@ const frontendDir = path.join(__dirname, '../', 'frontend');
const login = path.join(__dirname, '../', 'frontend/html/home.html');
const client = path.join(__dirname, '../', 'frontend/html/client.html');

// File to cache and inject custom HTML data like OG tags and any other elements.
const filesPath = [login, client];
const htmlInjector = new HtmlInjector(filesPath, config || null);

mongoose.set('strictQuery', true);

mongoose
.connect(MONGO_URL, { dbName: MONGO_DATABASE })
.then(() => {
const app = express();

app.use(helmet.xssFilter()); // Enable XSS protection
app.use(helmet.noSniff()); // Enable content type sniffing prevention
app.use(helmet.xssFilter()); // Enable XSS protection
app.use(helmet.noSniff()); // Enable content type sniffing prevention
app.use(cors(corsOptions()));
app.use(compression());
app.use(express.static(frontendDir));
Expand All @@ -82,11 +87,11 @@ mongoose
app.use(apiPath, users);

app.get('/', (req, res) => {
res.sendFile(login);
htmlInjector.injectHtml(login, res);
});

app.get('/client', auth, (req, res) => {
res.sendFile(client);
htmlInjector.injectHtml(client, res);
});

app.get('/config', auth, (req, res) => {
Expand Down
94 changes: 94 additions & 0 deletions backend/utils/HtmlInjector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const fs = require('fs');

const logs = require('../common/logs');

const log = new logs('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.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 WEB',
OG_TITLE: this.config?.OG?.title || 'Click the link to schedule the Meeting',
OG_DESCRIPTION:
this.config?.OG?.description || 'MiroTalk WEB Easy Room Scheduler for Meetings & Video Conferencing.',
OG_IMAGE: this.config?.OG?.image || 'https://webrtc.mirotalk.com/Images/mirotalk-web.png',
OG_URL: this.config?.OG?.url || 'https://webrtc.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 a file for changes and reload the cache
watchFileForChanges(filePath) {
fs.watch(filePath, (eventType) => {
if (eventType === 'change') {
log.debug(`File changed: ${filePath}`);
this.loadFileToCache(filePath);
log.debug(`Reload the file ${filePath} into cache`);
}
});
}

// Function to watch all files for changes
watchFiles(filePaths) {
filePaths.forEach((filePath) => this.watchFileForChanges(filePath));
}

// 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');
}
}
}
}

module.exports = HtmlInjector;
17 changes: 0 additions & 17 deletions frontend/css/client.css
Original file line number Diff line number Diff line change
Expand Up @@ -889,23 +889,6 @@ tr:nth-child(even) {
background: transparent;
}

/* google translate */
.skiptranslate iframe,
.goog-te-banner-frame.skiptranslate,
.VIpgJd-ZVi9od-aZ2wEe-wOHMyf,
.VIpgJd-ZVi9od-aZ2wEe-OiiCO,
#goog-gt-tt,
#goog-gt-tt *,
#goog-gt-vt,
#goog-gt-vt * {
display: none !important;
}

#google_translate_element select {
background: var(--secondary-color) !important;
color: var(--text-color) !important;
}

.fadeIn {
-webkit-animation: fadeIn ease-in 1;
-moz-animation: fadeIn ease-in 1;
Expand Down
20 changes: 20 additions & 0 deletions frontend/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,23 @@
::-webkit-scrollbar-track {
background: #1a1b1f;
}

/*--------------------------------------------------------------
# Google Translate
--------------------------------------------------------------*/

.skiptranslate iframe,
.goog-te-banner-frame.skiptranslate,
.VIpgJd-ZVi9od-aZ2wEe-wOHMyf,
.VIpgJd-ZVi9od-aZ2wEe-OiiCO,
#goog-gt-tt,
#goog-gt-tt *,
#goog-gt-vt,
#goog-gt-vt * {
display: none !important;
}

#google_translate_element select {
background: var(--secondary-color) !important;
color: var(--text-color) !important;
}
34 changes: 18 additions & 16 deletions frontend/html/client.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@
<html lang="en">
<head>
<title>MiroTalk WebRTC admin</title>
<link rel="apple-touch-icon" href="../Images/apple-touch-icon.png" />
<link rel="icon" type="image/x-icon" href="../Images/favicon.ico" />

<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta name="description" content="MiroTalk WebRTC admin panel, for rooms scheduling." />

<meta property="og:type" content="app-mirotalk" />
<meta property="og:site_name" content="MiroTalk WebRTC" />
<meta property="og:title" content="Click the link to open the dashboard" />
<meta property="og:description" content="MiroTalk WebRTC rooms scheduler" />
<!-- https://ogp.me -->

<link rel="apple-touch-icon" href="../Images/apple-touch-icon.png" />
<link rel="icon" type="image/x-icon" href="../Images/favicon.ico" />
<meta property="og:type" content="{{OG_TYPE}}" />
<meta property="og:site_name" content="{{OG_SITE_NAME}}" />
<meta property="og:title" content="{{OG_TITLE}}" />
<meta property="og:description" content="{{OG_DESCRIPTION}}" />
<meta property="og:image" content="{{OG_IMAGE}}" />
<meta property="og:url" content="{{OG_URL}}" />

<link rel="stylesheet" href="../css/client.css" />
<link rel="stylesheet" href="../css/common.css" />
<!-- https://iconscout.com/unicons/explore/line | https://unicons.iconscout.com/release/v1.0.0/index.html -->
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css" />
Expand All @@ -31,8 +33,6 @@
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/qrious.min.js"></script>

<!-- <script type="text/javascript" src="https://unpkg.com/@popperjs/core@2"></script>
<script type="text/javascript" src="https://unpkg.com/tippy.js@6"></script> -->
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js"
Expand Down Expand Up @@ -138,7 +138,7 @@
</div>

<a id="myProfile" href="https://www.linkedin.com/in/miroslav-pejic-976a07101/" target="_blank">
<img src="../Images/profile.png" alt="miroslav-pejic" />
<img src="../Images/profile.png" />
</a>
</div>

Expand Down Expand Up @@ -261,10 +261,10 @@
<i id="add-close-btn" class="uil uil-multiply"></i>
<label id="rowAppName" for="mirotalk">MiroTalk</label>
<select id="add-type" class="add-row-select-options" required>
<option value="P2P">P2P</option>
<option value="SFU">SFU</option>
<option value="C2C">C2C</option>
<option value="BRO">BRO</option>
<option translate="no" value="P2P">P2P</option>
<option translate="no" value="SFU">SFU</option>
<option translate="no" value="C2C">C2C</option>
<option translate="no" value="BRO">BRO</option>
</select>
<label for="tag">Tag</label>
<input id="add-tag" type="text" placeholder="Tag" name="tag" required />
Expand Down Expand Up @@ -309,8 +309,6 @@

<div id="settingsDiv" class="settingsDiv hidden">
<i id="settings-close-btn" class="uil uil-multiply"></i>
<label for="google_translate_element">Language</label>
<div id="google_translate_element"></div>
<ul class="settings-ul">
<li class="mode">
<a href="javascript:void(0)">
Expand All @@ -321,6 +319,10 @@
<span class="switch"></span>
</div>
</li>
<li>
<label for="google_translate_element">Language</label>
<div id="google_translate_element"></div>
</li>
</ul>
</div>

Expand Down
16 changes: 10 additions & 6 deletions frontend/html/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
<html lang="en">
<head>
<title>MiroTalk WebRTC admin login</title>
<link rel="apple-touch-icon" href="../Images/apple-touch-icon.png" />
<link rel="icon" type="image/x-icon" href="../Images/favicon.ico" />

<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="MiroTalk WebRTC admin panel, for rooms scheduling." />

<meta property="og:type" content="app-mirotalk" />
<meta property="og:site_name" content="MiroTalk WebRTC" />
<meta property="og:title" content="Click the link to login" />
<meta property="og:description" content="MiroTalk WebRTC rooms scheduler" />
<!-- https://ogp.me -->

<link rel="apple-touch-icon" href="../Images/apple-touch-icon.png" />
<link rel="icon" type="image/x-icon" href="../Images/favicon.ico" />
<meta property="og:type" content="{{OG_TYPE}}" />
<meta property="og:site_name" content="{{OG_SITE_NAME}}" />
<meta property="og:title" content="{{OG_TITLE}}" />
<meta property="og:description" content="{{OG_DESCRIPTION}}" />
<meta property="og:image" content="{{OG_IMAGE}}" />
<meta property="og:url" content="{{OG_URL}}" />

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
Expand All @@ -28,6 +31,7 @@
<script defer src="../js/swal.js"></script>
<script defer src="../js/api.js"></script>
<script defer src="../js/home.js"></script>
<script defer src="../js/translate.js"></script>
</head>
<body>
<div class="main">
Expand Down
14 changes: 7 additions & 7 deletions frontend/js/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @license For private project or commercial purposes contact us at: [email protected] or purchase it directly via Code Canyon:
* @license https://codecanyon.net/item/a-selfhosted-mirotalks-webrtc-rooms-scheduler-server/42643313
* @author Miroslav Pejic - [email protected]
* @version 1.1.36
* @version 1.1.40
*/

const userAgent = navigator.userAgent;
Expand Down Expand Up @@ -570,10 +570,10 @@ function getRow(obj) {
const isC2C = obj.type == 'C2C' ? 'selected' : '';
const isBRO = obj.type == 'BRO' ? 'selected' : '';

const optionP2P = config.MiroTalk.P2P.Visible ? `<option value="P2P" ${isP2P}>P2P</option>` : '';
const optionSFU = config.MiroTalk.SFU.Visible ? `<option value="P2P" ${isSFU}>SFU</option>` : '';
const optionC2C = config.MiroTalk.C2C.Visible ? `<option value="C2C" ${isC2C}>C2C</option>` : '';
const optionBRO = config.MiroTalk.BRO.Visible ? `<option value="BRO" ${isBRO}>BRO</option>` : '';
const optionP2P = config.MiroTalk.P2P.Visible ? `<option translate="no" value="P2P" ${isP2P}>P2P</option>` : '';
const optionSFU = config.MiroTalk.SFU.Visible ? `<option translate="no" value="P2P" ${isSFU}>SFU</option>` : '';
const optionC2C = config.MiroTalk.C2C.Visible ? `<option translate="no" value="C2C" ${isC2C}>C2C</option>` : '';
const optionBRO = config.MiroTalk.BRO.Visible ? `<option translate="no" value="BRO" ${isBRO}>BRO</option>` : '';

const setRandomRoomIcon =
config.BUTTONS.setRandomRoom && user.allowedRoomsALL
Expand Down Expand Up @@ -616,11 +616,11 @@ function getRow(obj) {
let rooms = `<td><input id="${obj._id}_room" type="text" placeholder="Room name" name="room" value="${obj.room}"/></td>`;

if (!user.allowedRoomsALL) {
rooms = `<select id="${obj._id}_room" class="select-options">`;
rooms = `<select translate="no" id="${obj._id}_room" class="select-options">`;

user.allowedRooms.forEach((room) => {
const selected = obj.room === room ? 'selected' : '';
rooms += `<option value="${room}" ${selected}>${room}</option>`;
rooms += `<option translate="no" value="${room}" ${selected}>${room}</option>`;
});

rooms += `</select>`;
Expand Down
Loading

0 comments on commit 91d2454

Please sign in to comment.