473 lines
18 KiB
JavaScript
473 lines
18 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* ==============================================
|
|
* MiroTalk P2P v.1.7.58 - Configuration File
|
|
* ==============================================
|
|
*
|
|
* This file is the central configuration source.
|
|
* All environment variables are read here so the
|
|
* rest of the codebase imports config values
|
|
* instead of reading process.env directly.
|
|
*
|
|
* Setup:
|
|
* cp app/src/config.template.js app/src/config.js
|
|
* Then edit config.js to match your environment.
|
|
*
|
|
* Docker/container environments inject values via
|
|
* environment variables which are read at startup.
|
|
*
|
|
* Branding and customizations require a license:
|
|
* https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
|
|
*/
|
|
|
|
require('dotenv').config();
|
|
|
|
const packageJson = require('../../package.json');
|
|
|
|
// Helper: parse env string to boolean
|
|
function getEnvBoolean(key, force_true_if_undefined = false) {
|
|
if (key == undefined && force_true_if_undefined) return true;
|
|
return key == 'true' ? true : false;
|
|
}
|
|
|
|
// Helper: safely parse JSON env vars with a fallback
|
|
function parseJsonEnv(envValue, fallback) {
|
|
if (!envValue) return fallback;
|
|
try {
|
|
return JSON.parse(envValue);
|
|
} catch (e) {
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
const port = process.env.PORT || 3000;
|
|
|
|
module.exports = {
|
|
// ==========================================
|
|
// Server
|
|
// ==========================================
|
|
server: {
|
|
port: port,
|
|
host: process.env.HOST || `http://localhost:${port}`,
|
|
environment: process.env.NODE_ENV || 'development',
|
|
trustProxy: !!getEnvBoolean(process.env.TRUST_PROXY),
|
|
},
|
|
|
|
// ==========================================
|
|
// CORS
|
|
// ==========================================
|
|
cors: {
|
|
origin: parseJsonEnv(process.env.CORS_ORIGIN, '*'),
|
|
methods: parseJsonEnv(process.env.CORS_METHODS, ['GET', 'POST']),
|
|
},
|
|
|
|
// ==========================================
|
|
// Host Protection
|
|
// ==========================================
|
|
host: {
|
|
protected: getEnvBoolean(process.env.HOST_PROTECTED),
|
|
userAuth: getEnvBoolean(process.env.HOST_USER_AUTH),
|
|
users: parseJsonEnv(process.env.HOST_USERS, [{ username: 'MiroTalk', password: 'P2P' }]),
|
|
maxLoginAttempts: process.env.HOST_MAX_LOGIN_ATTEMPTS || 5,
|
|
minLoginBlockTime: process.env.HOST_MIN_LOGIN_BLOCK_TIME || 15, // in minutes
|
|
maxRoomParticipants: parseInt(process.env.ROOM_MAX_PARTICIPANTS) || 1000,
|
|
showActiveRooms: getEnvBoolean(process.env.SHOW_ACTIVE_ROOMS) || false,
|
|
},
|
|
|
|
// ==========================================
|
|
// JWT
|
|
// ==========================================
|
|
jwt: {
|
|
key: process.env.JWT_KEY || 'mirotalk_jwt_secret',
|
|
exp: process.env.JWT_EXP || '1h',
|
|
},
|
|
|
|
// ==========================================
|
|
// Presenters
|
|
// ==========================================
|
|
presenters: parseJsonEnv(process.env.PRESENTERS, ['MiroTalk P2P']),
|
|
|
|
// ==========================================
|
|
// API
|
|
// ==========================================
|
|
api: {
|
|
keySecret: process.env.API_KEY_SECRET || 'mirotalkp2p_default_secret',
|
|
disabled: parseJsonEnv(process.env.API_DISABLED, ['token', 'meetings']),
|
|
},
|
|
|
|
// ==========================================
|
|
// Ngrok
|
|
// ==========================================
|
|
ngrok: {
|
|
enabled: getEnvBoolean(process.env.NGROK_ENABLED),
|
|
authToken: process.env.NGROK_AUTH_TOKEN,
|
|
},
|
|
|
|
// ==========================================
|
|
// WebRTC ICE Servers
|
|
// ==========================================
|
|
webrtc: {
|
|
stun: {
|
|
enabled: getEnvBoolean(process.env.STUN_SERVER_ENABLED),
|
|
url: process.env.STUN_SERVER_URL,
|
|
},
|
|
turn: {
|
|
enabled: getEnvBoolean(process.env.TURN_SERVER_ENABLED),
|
|
url: process.env.TURN_SERVER_URL,
|
|
username: process.env.TURN_SERVER_USERNAME,
|
|
credential: process.env.TURN_SERVER_CREDENTIAL,
|
|
},
|
|
},
|
|
|
|
// ==========================================
|
|
// IP Lookup
|
|
// ==========================================
|
|
ipLookup: {
|
|
enabled: getEnvBoolean(process.env.IP_LOOKUP_ENABLED),
|
|
},
|
|
|
|
// ==========================================
|
|
// Survey
|
|
// ==========================================
|
|
survey: {
|
|
enabled: getEnvBoolean(process.env.SURVEY_ENABLED),
|
|
url: process.env.SURVEY_URL || 'https://www.questionpro.com/t/AUs7VZq00L',
|
|
},
|
|
|
|
// ==========================================
|
|
// Redirect
|
|
// ==========================================
|
|
redirect: {
|
|
enabled: getEnvBoolean(process.env.REDIRECT_ENABLED),
|
|
url: process.env.REDIRECT_URL || '/newcall',
|
|
},
|
|
|
|
// ==========================================
|
|
// Sentry
|
|
// ==========================================
|
|
sentry: {
|
|
enabled: getEnvBoolean(process.env.SENTRY_ENABLED),
|
|
dsn: process.env.SENTRY_DSN,
|
|
tracesSampleRate: parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE || '0.0'),
|
|
logLevels: process.env.SENTRY_LOG_LEVELS
|
|
? process.env.SENTRY_LOG_LEVELS.split(',').map((level) => level.trim())
|
|
: ['error'],
|
|
},
|
|
|
|
// ==========================================
|
|
// Slack
|
|
// ==========================================
|
|
slack: {
|
|
enabled: getEnvBoolean(process.env.SLACK_ENABLED),
|
|
signingSecret: process.env.SLACK_SIGNING_SECRET,
|
|
},
|
|
|
|
// ==========================================
|
|
// ChatGPT / OpenAI
|
|
// ==========================================
|
|
chatGPT: {
|
|
enabled: getEnvBoolean(process.env.CHATGPT_ENABLED),
|
|
basePath: process.env.CHATGPT_BASE_PATH,
|
|
apiKey: process.env.CHATGPT_APIKEY,
|
|
model: process.env.CHATGPT_MODEL,
|
|
max_tokens: parseInt(process.env.CHATGPT_MAX_TOKENS),
|
|
temperature: parseInt(process.env.CHATGPT_TEMPERATURE),
|
|
},
|
|
|
|
// ==========================================
|
|
// IP Whitelist
|
|
// ==========================================
|
|
ipWhitelist: {
|
|
enabled: getEnvBoolean(process.env.IP_WHITELIST_ENABLED),
|
|
allowed: parseJsonEnv(process.env.IP_WHITELIST_ALLOWED, []),
|
|
},
|
|
|
|
// ==========================================
|
|
// OIDC - OpenID Connect
|
|
// ==========================================
|
|
oidc: {
|
|
enabled: process.env.OIDC_ENABLED ? getEnvBoolean(process.env.OIDC_ENABLED) : false,
|
|
allowRoomCreationForAuthUsers: process.env.OIDC_ALLOW_ROOMS_CREATION_FOR_AUTH_USERS
|
|
? getEnvBoolean(process.env.OIDC_ALLOW_ROOMS_CREATION_FOR_AUTH_USERS)
|
|
: false,
|
|
baseUrlDynamic: process.env.OIDC_BASE_URL_DYNAMIC ? getEnvBoolean(process.env.OIDC_BASE_URL_DYNAMIC) : false,
|
|
config: {
|
|
issuerBaseURL: process.env.OIDC_ISSUER_BASE_URL,
|
|
clientID: process.env.OIDC_CLIENT_ID,
|
|
clientSecret: process.env.OIDC_CLIENT_SECRET,
|
|
baseURL: process.env.OIDC_BASE_URL,
|
|
secret: process.env.SESSION_SECRET,
|
|
authorizationParams: {
|
|
response_type: 'code',
|
|
scope: 'openid profile email',
|
|
},
|
|
authRequired: process.env.OIDC_AUTH_REQUIRED ? getEnvBoolean(process.env.OIDC_AUTH_REQUIRED) : false,
|
|
auth0Logout: process.env.OIDC_AUTH_LOGOUT ? getEnvBoolean(process.env.OIDC_AUTH_LOGOUT) : true,
|
|
routes: {
|
|
callback: '/auth/callback',
|
|
login: false,
|
|
logout: '/logout',
|
|
},
|
|
},
|
|
},
|
|
|
|
// ==========================================
|
|
// Mattermost
|
|
// ==========================================
|
|
mattermost: {
|
|
enabled: getEnvBoolean(process.env.MATTERMOST_ENABLED),
|
|
serverUrl: process.env.MATTERMOST_SERVER_URL,
|
|
username: process.env.MATTERMOST_USERNAME,
|
|
password: process.env.MATTERMOST_PASSWORD,
|
|
token: process.env.MATTERMOST_TOKEN,
|
|
roomTokenExpire: process.env.MATTERMOST_ROOM_TOKEN_EXPIRE,
|
|
},
|
|
|
|
// ==========================================
|
|
// Stats / Analytics
|
|
// ==========================================
|
|
stats: {
|
|
enabled: process.env.STATS_ENABLED ? getEnvBoolean(process.env.STATS_ENABLED) : true,
|
|
src: process.env.STATS_SCR || 'https://stats.mirotalk.com/script.js',
|
|
id: process.env.STATS_ID || 'c7615aa7-ceec-464a-baba-54cb605d7261',
|
|
},
|
|
|
|
// ==========================================
|
|
// Email
|
|
// ==========================================
|
|
email: {
|
|
alert: process.env.EMAIL_ALERT === 'true' || false,
|
|
host: process.env.EMAIL_HOST,
|
|
port: Number(process.env.EMAIL_PORT),
|
|
username: process.env.EMAIL_USERNAME,
|
|
password: process.env.EMAIL_PASSWORD,
|
|
from: process.env.EMAIL_FROM || process.env.EMAIL_USERNAME,
|
|
sendTo: process.env.EMAIL_SEND_TO,
|
|
https: process.env.HTTPS === 'true' || false,
|
|
serverPort: process.env.PORT || 3000,
|
|
},
|
|
|
|
// ==========================================
|
|
// Branding (UI customizations)
|
|
// ==========================================
|
|
brand: {
|
|
htmlInjection: true,
|
|
app: {
|
|
language: 'en', // https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
|
|
name: 'MiroTalk',
|
|
title: '<h1>MiroTalk</h1>Free browser based Real-time video calls.<br />Simple, Secure, Fast.',
|
|
description:
|
|
'Start your next video call with a single click. No download, plug-in, or login is required. Just get straight to talking, messaging, and sharing your screen.',
|
|
joinDescription: 'Pick a room name.<br />How about this one?',
|
|
joinButtonLabel: 'JOIN ROOM',
|
|
customizeRoomButtonLabel: 'CUSTOMIZE ROOM',
|
|
joinLastLabel: 'Your recent room:',
|
|
},
|
|
og: {
|
|
type: 'app-webrtc',
|
|
siteName: 'MiroTalk',
|
|
title: 'Click the link to make a call.',
|
|
description:
|
|
'MiroTalk calling provides real-time HD quality and latency simply not available with traditional technology.',
|
|
image: 'https://p2p.mirotalk.com/images/preview.png',
|
|
url: 'https://p2p.mirotalk.com',
|
|
},
|
|
site: {
|
|
shortcutIcon: '../images/logo.svg',
|
|
appleTouchIcon: '../images/logo.svg',
|
|
landingTitle: 'MiroTalk a Free Secure Video Calls, Chat & Screen Sharing.',
|
|
newCallTitle: 'MiroTalk a Free Secure Video Calls, Chat & Screen Sharing.',
|
|
newCallRoomTitle: 'Pick name. <br />Share URL. <br />Start conference.',
|
|
newCallRoomDescription:
|
|
"Each room has its disposable URL. Just pick a room name and share your custom URL. It's that easy.",
|
|
loginTitle: 'MiroTalk - Host Protected login required.',
|
|
loginHeading: 'Welcome back',
|
|
loginDescription: 'Enter your credentials to continue.',
|
|
loginButtonLabel: 'Login',
|
|
joinRoomTitle: 'Pick name.<br />Share URL.<br />Start conference.',
|
|
joinRoomButtonLabel: 'JOIN ROOM',
|
|
clientTitle: 'MiroTalk WebRTC Video call, Chat Room & Screen Sharing.',
|
|
privacyPolicyTitle: 'MiroTalk - privacy and policy.',
|
|
stunTurnTitle: 'Test Stun/Turn Servers.',
|
|
notFoundTitle: 'MiroTalk - 404 Page not found.',
|
|
waitingRoomTitle: 'MiroTalk - Waiting for host to start the meeting',
|
|
waitingRoomHeading: 'Waiting for host...',
|
|
waitingRoomDescription:
|
|
"The meeting hasn't started yet.<br />You'll join automatically when the host opens the room.",
|
|
waitingRoomStatus: 'Checking room status...',
|
|
waitingRoomReady: 'Room is ready! Joining...',
|
|
waitingRoomWaiting: 'Waiting for host to start the meeting...',
|
|
waitingRoomHostLink: 'Are you the host?',
|
|
waitingRoomLoginLink: 'Login here',
|
|
waitingRoomElapsedJust: 'Just started waiting',
|
|
waitingRoomElapsedMinutes: 'Waiting for {minutes}',
|
|
waitingRoomSongUrl: '../sounds/waiting-music.mp3',
|
|
},
|
|
html: {
|
|
topSponsors: true,
|
|
features: true,
|
|
browsers: true,
|
|
teams: true, // please keep me always true ;)
|
|
tryEasier: true,
|
|
poweredBy: true,
|
|
sponsors: true,
|
|
advertisers: true,
|
|
supportUs: true,
|
|
footer: true,
|
|
},
|
|
about: {
|
|
imageUrl: '../images/mirotalk-logo.gif',
|
|
title: `WebRTC P2P v${packageJson.version}`,
|
|
html: `
|
|
<button
|
|
id="support-button"
|
|
data-umami-event="Support button"
|
|
onclick="window.open('https://codecanyon.net/user/miroslavpejic85')">
|
|
<i class="fas fa-heart" ></i> Support
|
|
</button>
|
|
<br /><br /><br />
|
|
Author:<a
|
|
id="linkedin-button"
|
|
data-umami-event="Linkedin button"
|
|
href="https://www.linkedin.com/in/miroslav-pejic-976a07101/" target="_blank">
|
|
Miroslav Pejic
|
|
</a>
|
|
<br />
|
|
Email:<a
|
|
id="email-button"
|
|
data-umami-event="Email button"
|
|
href="mailto:miroslav.pejic.85@gmail.com?subject=MiroTalk P2P info">
|
|
miroslav.pejic.85@gmail.com
|
|
</a>
|
|
<br /><br />
|
|
<hr />
|
|
<span>© 2025 MiroTalk P2P, all rights reserved</span>
|
|
<hr />
|
|
`,
|
|
},
|
|
// https://docs.mirotalk.com/mirotalk-p2p/integration/#widgets-integration
|
|
widget: {
|
|
enabled: false,
|
|
roomId: 'support-room',
|
|
theme: 'dark',
|
|
widgetState: 'minimized',
|
|
widgetType: 'support',
|
|
supportWidget: {
|
|
position: 'top-right',
|
|
expertImages: [
|
|
'https://photo.cloudron.pocketsolution.net/uploads/original/95/7d/a5f7f7a2c89a5fee7affda5f013c.jpeg',
|
|
],
|
|
buttons: {
|
|
audio: true,
|
|
video: true,
|
|
screen: true,
|
|
chat: true,
|
|
join: true,
|
|
},
|
|
checkOnlineStatus: false,
|
|
isOnline: true,
|
|
customMessages: {
|
|
heading: 'Need Help?',
|
|
subheading: 'Get instant support from our expert team!',
|
|
connectText: 'connect in < 5 seconds',
|
|
onlineText: 'We are online',
|
|
offlineText: 'We are offline',
|
|
poweredBy: 'Powered by MiroTalk',
|
|
},
|
|
},
|
|
},
|
|
//...
|
|
},
|
|
/**
|
|
* Configuration for controlling the visibility of buttons in the MiroTalk P2P client.
|
|
* Set properties to true to show the corresponding buttons, or false to hide them.
|
|
* captionBtn, showSwapCameraBtn, showScreenShareBtn, showFullScreenBtn, showVideoPipBtn, showDocumentPipBtn -> (auto-detected).
|
|
*/
|
|
buttons: {
|
|
main: {
|
|
showAudioBtn: true,
|
|
showVideoBtn: true,
|
|
showScreenBtn: true, // autodetected
|
|
showMyHandBtn: true,
|
|
showChatRoomBtn: true,
|
|
showParticipantsBtn: true,
|
|
showMySettingsBtn: true,
|
|
showExtraBtn: true,
|
|
showShareQr: true,
|
|
showShareRoomBtn: true, // For guests
|
|
showHideMeBtn: true,
|
|
showRecordStreamBtn: true,
|
|
showFullScreenBtn: true,
|
|
showRoomEmojiPickerBtn: true,
|
|
showCaptionRoomBtn: true,
|
|
showWhiteboardBtn: true,
|
|
showSnapshotRoomBtn: true,
|
|
showFileShareBtn: true,
|
|
showDocumentPipBtn: true,
|
|
showAboutBtn: true, // Please keep me always true, Thank you!
|
|
},
|
|
chat: {
|
|
showTogglePinBtn: true,
|
|
showMaxBtn: true,
|
|
showSaveMessageBtn: true,
|
|
showMarkDownBtn: true,
|
|
showChatGPTBtn: true,
|
|
showFileShareBtn: true,
|
|
showShareVideoAudioBtn: true,
|
|
showParticipantsBtn: true,
|
|
},
|
|
caption: {
|
|
showTogglePinBtn: true,
|
|
showMaxBtn: true,
|
|
},
|
|
settings: {
|
|
showActiveRoomsBtn: true,
|
|
showMicOptionsBtn: true,
|
|
showTabRoomPeerName: true,
|
|
showTabRoomParticipants: true,
|
|
showTabRoomSecurity: true,
|
|
showTabEmailInvitation: true,
|
|
showCaptionEveryoneBtn: true,
|
|
showMuteEveryoneBtn: true,
|
|
showHideEveryoneBtn: true,
|
|
showEjectEveryoneBtn: true,
|
|
showLockRoomBtn: true,
|
|
showUnlockRoomBtn: true,
|
|
showShortcutsBtn: true,
|
|
customNoiseSuppression: true,
|
|
},
|
|
remote: {
|
|
showAudioVolume: true,
|
|
audioBtnClickAllowed: true,
|
|
videoBtnClickAllowed: true,
|
|
showVideoPipBtn: true,
|
|
showKickOutBtn: true,
|
|
showSnapShotBtn: true,
|
|
showFileShareBtn: true,
|
|
showShareVideoAudioBtn: true,
|
|
showGeoLocationBtn: true,
|
|
showPrivateMessageBtn: true,
|
|
showZoomInOutBtn: false,
|
|
showVideoFocusBtn: true,
|
|
},
|
|
local: {
|
|
showVideoPipBtn: true,
|
|
showSnapShotBtn: true,
|
|
showVideoCircleBtn: true,
|
|
showZoomInOutBtn: false,
|
|
showVideoFocusBtn: true,
|
|
},
|
|
whiteboard: {
|
|
whiteboardLockBtn: false,
|
|
},
|
|
},
|
|
// ==========================================
|
|
// Webhook
|
|
// ==========================================
|
|
webhook: {
|
|
enabled: false, // Enable webhook functionality
|
|
url: 'http://localhost:8888/webhook-endpoint', // Webhook server URL
|
|
},
|
|
};
|