Skip to content

Commit

Permalink
Merge pull request #93 from Yeghro/merge
Browse files Browse the repository at this point in the history
Merge miro upstream
  • Loading branch information
bitkarrot authored Nov 26, 2024
2 parents 8066167 + 2d0e2e2 commit b350067
Show file tree
Hide file tree
Showing 31 changed files with 2,773 additions and 1,218 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Free WebRTC - SFU - Simple, Secure, Scalable Real-Time Video Conferences with su
- Right-click options on video elements for additional controls.
- Supports [REST API](app/api/README.md) (Application Programming Interface).
- Integration with [Slack](https://api.slack.com/apps/) for enhanced communication.
- Integration with [Discord](https://discord.com) for enhanced communication.
- Integration with [Mattermost](https://mattermost.com/) for enhanced communication.
- Utilizes [Sentry](https://sentry.io/) for error reporting.
- And much more...

Expand Down Expand Up @@ -205,6 +207,10 @@ $ PORT=3011 npm start
- Install [docker engine](https://docs.docker.com/engine/install/) and [docker compose](https://docs.docker.com/compose/install/)

```bash
# Clone this repo
$ git clone https://github.com/miroslavpejic85/mirotalksfu.git
# Go to to dir mirotalksfu
$ cd mirotalksfu
# Copy app/src/config.template.js in app/src/config.js IMPORTANT (edit it according to your needs)
$ cp app/src/config.template.js app/src/config.js
# Copy docker-compose.template.yml in docker-compose.yml and edit it if needed
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ We would like to extend our gratitude to the following individuals for their res
| Name | Contact |
| ----------------- | ------------------------------- |
| `Hendrik Siewert` | [email protected] |
| `Caio Fook` | caio.fook@gmail.com |
| `Caio Fook` | https://github.com/caiofook |
| `Nishant Jain` | https://twitter.com/realArcherL |

Their dedication to security has contributed to the continuous improvement of our systems, ensuring the safety and privacy of our users and data.
75 changes: 75 additions & 0 deletions app/src/Discord.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict';

const { Client, GatewayIntentBits } = require('discord.js');

const { v4: uuidV4 } = require('uuid');

const Logger = require('./Logger');

const log = new Logger('Discord');

// Discord Bot Class Implementation
class Discord {
constructor(token, commands) {
this.token = token;
this.commands = commands;
this.discordClient = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent, // Make sure this is enabled in your Discord Developer Portal
],
});

this.setupEventHandlers();

this.discordClient.login(this.token).catch((error) => {
log.error('Failed to login to Discord:', error);
});
}

setupEventHandlers() {
this.discordClient.once('ready', () => {
log.info(`Discord Bot Logged in as ${this.discordClient.user.tag}!`, '😎');
});

this.discordClient.on('error', (error) => {
log.error(`Discord Client Error: ${error.message}`, { stack: error.stack });
});

this.discordClient.on('messageCreate', async (message) => {
if (message.author.bot) return;

for (const command of this.commands) {
if (message.content.startsWith(command.name)) {
switch (command.name) {
case '/sfu':
const roomId = this.generateMeetingRoom(command.baseUrl);
await this.sendMessage(message.channel, `${command.message} ${roomId}`);
break;
//....
default:
await this.sendMessage(message.channel, command.message);
break;
}
break; // Exit the loop after finding the command
}
}
});
}

generateMeetingRoom(baseUrl) {
const roomId = uuidV4();
return `${baseUrl}${roomId}`;
}

async sendMessage(channel, content) {
try {
await channel.send(content);
} catch (error) {
log.error(`Failed to send message: ${error.message}`);
}
}
}

module.exports = Discord;
27 changes: 0 additions & 27 deletions app/src/Host.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
module.exports = class Host {
constructor() {
this.authorizedIPs = new Map();
this.roomActive = false;
}

/**
Expand All @@ -30,7 +29,6 @@ module.exports = class Host {
*/
setAuthorizedIP(ip, authorized) {
this.authorizedIPs.set(ip, authorized);
this.setRoomActive();
}

/**
Expand All @@ -42,37 +40,12 @@ module.exports = class Host {
return this.authorizedIPs.has(ip);
}

/**
* Host room status
* @returns boolean
*/
isRoomActive() {
return this.roomActive;
}

/**
* Set host room activate
*/
setRoomActive() {
this.roomActive = true;
}

/**
* Set host room deactivate
*/
setRoomDeactivate() {
this.roomActive = false;
}

/**
* Delete ip from authorized IPs
* @param {string} ip
* @returns boolean
*/
deleteIP(ip) {
if (this.isAuthorizedIP(ip)) {
this.setRoomDeactivate();
}
return this.authorizedIPs.delete(ip);
}
};
100 changes: 100 additions & 0 deletions app/src/Mattermost.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
'use strict';

const { Client4 } = require('@mattermost/client');

const { v4: uuidV4 } = require('uuid');

const config = require('./config');

const Logger = require('./Logger');

const log = new Logger('Mattermost');

class Mattermost {
constructor(app) {
const {
enabled,
token,
serverUrl,
username,
password,
commands = '/sfu',
texts = '/sfu',
} = config.mattermost || {};

if (!enabled) return; // Check if Mattermost integration is enabled

this.app = app;
this.allowed = config.api.allowed && config.api.allowed.mattermost;
this.token = token;
this.serverUrl = serverUrl;
this.username = username;
this.password = password;
this.commands = commands;
this.texts = texts;

this.client = new Client4();
this.client.setUrl(this.serverUrl);
this.authenticate();
this.setupEventHandlers();
}

async authenticate() {
try {
const user = await this.client.login(this.username, this.password);
log.debug('--------> Logged into Mattermost as', user.username);
} catch (error) {
log.error('Failed to log into Mattermost:', error);
}
}

setupEventHandlers() {
this.app.post('/mattermost', (req, res) => {
//
if (!this.allowed) {
return res
.status(403)
.send('This endpoint has been disabled. Please contact the administrator for further information.');
}

log.debug('Mattermost request received:', { header: req.header, body: req.body });

const { token, text, command, channel_id } = req.body;
if (token !== this.token) {
log.error('Invalid token attempt', { token });
return res.status(403).send('Invalid token');
}

const payload = { text: '', channel_id };
if (this.processInput(command, payload, req) || this.processInput(text, payload, req)) {
return res.json(payload);
}

return res.status(200).send('Command not recognized');
});
}

processInput(input, payload, req) {
for (const cmd of [...this.commands, ...this.texts]) {
if (input.trim() === cmd.name) {
switch (cmd.name) {
case '/sfu':
payload.text = `${cmd.message} ${this.getMeetingURL(req)}`;
break;
default:
break;
}
return true;
}
}
return false;
}

getMeetingURL(req) {
const host = req.headers.host;
const protocol = host.includes('localhost') ? 'http' : 'https';
return `${protocol}://${host}/join/${uuidV4()}`;
}
}

module.exports = Mattermost;
6 changes: 6 additions & 0 deletions app/src/Peer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = class Peer {
peer_name,
peer_presenter,
peer_audio,
peer_audio_volume,
peer_video,
peer_video_privacy,
peer_recording,
Expand All @@ -29,6 +30,7 @@ module.exports = class Peer {
this.peer_presenter = peer_presenter;
this.peer_audio = peer_audio;
this.peer_video = peer_video;
this.peer_audio_volume = peer_audio_volume;
this.peer_video_privacy = peer_video_privacy;
this.peer_recording = peer_recording;
this.peer_hand = peer_hand;
Expand Down Expand Up @@ -84,6 +86,10 @@ module.exports = class Peer {
this.peer_info.peer_recording = data.status;
this.peer_recording = data.status;
break;
case 'peerAudio':
this.peer_info.peer_audio_volume = data.volume;
this.peer_audio_volume = data.volume;
break;
default:
break;
}
Expand Down
19 changes: 19 additions & 0 deletions app/src/Room.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = class Room {
screen_cant_share: false,
chat_cant_privately: false,
chat_cant_chatgpt: false,
media_cant_sharing: false,
};
this.survey = config.survey;
this.redirect = config.redirect;
Expand All @@ -65,6 +66,11 @@ module.exports = class Room {

// Polls
this.polls = [];

this.isHostProtected = config.host.protected;

// Share Media
this.shareMediaData = {};
}

// ####################################################
Expand All @@ -87,15 +93,25 @@ module.exports = class Room {
fromUrl: this.rtmp && this.rtmp.fromUrl,
fromStream: this.rtmp && this.rtmp.fromStream,
},
hostProtected: this.isHostProtected,
moderator: this._moderator,
survey: this.survey,
redirect: this.redirect,
videoAIEnabled: this.videoAIEnabled,
thereIsPolls: this.thereIsPolls(),
shareMediaData: this.shareMediaData,
peers: JSON.stringify([...this.peers]),
};
}

// ##############################################
// SHARE MEDIA
// ##############################################

updateShareMedia(data) {
this.shareMediaData = data;
}

// ##############################################
// POLLS
// ##############################################
Expand Down Expand Up @@ -449,6 +465,9 @@ module.exports = class Room {
case 'chat_cant_chatgpt':
this._moderator.chat_cant_chatgpt = data.status;
break;
case 'media_cant_sharing':
this._moderator.media_cant_sharing = data.status;
break;
default:
break;
}
Expand Down
Loading

0 comments on commit b350067

Please sign in to comment.