[mirotalk] - #281 - Add Support for Custom Avatar via Options Object
This commit is contained in:
@@ -107,13 +107,14 @@
|
||||
<br/>
|
||||
|
||||
- You can `directly join a room` by using links like:
|
||||
- https://p2p.mirotalk.com/join?room=test&name=mirotalk&audio=0&video=0&screen=0&hide=0¬ify=0
|
||||
- https://mirotalk.up.railway.app/join?room=test&name=mirotalk&audio=0&video=0&screen=0&hide=0¬ify=0
|
||||
- https://p2p.mirotalk.com/join?room=test&name=mirotalk&avatar=0&audio=0&video=0&screen=0&hide=0¬ify=0
|
||||
- https://mirotalk.up.railway.app/join?room=test&name=mirotalk&avatar=0&audio=0&video=0&screen=0&hide=0¬ify=0
|
||||
|
||||
| Params | Type | Description |
|
||||
| ------ | ------- | --------------- |
|
||||
| room | string | Room Id |
|
||||
| name | string | User name |
|
||||
| avatar | Mixed | User avatar |
|
||||
| audio | boolean | Audio stream |
|
||||
| video | boolean | Video stream |
|
||||
| screen | boolean | Screen stream |
|
||||
@@ -233,33 +234,56 @@ To embed a meeting within `your service or app` using an iframe, you can use the
|
||||
|
||||
- `Rest API:` The [API documentation](https://docs.mirotalk.com/mirotalk-p2p/api/) uses [swagger](https://swagger.io/) at http://localhost:3000/api/v1/docs. Or check it out on [live](https://p2p.mirotalk.com/api/v1/docs).
|
||||
|
||||
### 1. Stats Endpoint (Get server statistics)
|
||||
|
||||
```bash
|
||||
# The response will give you the total of rooms and peers.
|
||||
$ curl -X GET "http://localhost:3000/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X GET "https://p2p.mirotalk.com/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X GET "https://mirotalk.up.railway.app/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
# The response will give you the active meetings (default disabled).
|
||||
$ curl -X GET "http://localhost:3000/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X GET "https://p2p.mirotalk.com/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X GET "mirotalk.up.railway.app/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
# The response will give you a entrypoint / Room URL for your meeting.
|
||||
$ curl -X POST "http://localhost:3000/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X POST "https://p2p.mirotalk.com/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
$ curl -X POST "https://mirotalk.up.railway.app/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
# The response will give you a entrypoint / URL for the direct join to the meeting.
|
||||
$ curl -X POST "http://localhost:3000/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true"}'
|
||||
$ curl -X POST "https://p2p.mirotalk.com/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true"}'
|
||||
$ curl -X POST "https://mirotalk.up.railway.app/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true"}'
|
||||
# The response will give you an entry point/URL for direct joining to the meeting with a token.
|
||||
$ curl -X POST "http://localhost:3000/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}'
|
||||
$ curl -X POST "https://p2p.mirotalk.com/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}'
|
||||
$ curl -X POST "https://mirotalk.up.railway.app/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}'
|
||||
# The response will give you a valid token for a meeting.
|
||||
$ curl -X POST "http://localhost:3000/api/v1/token" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":"true", "expire":"1h"}'
|
||||
$ curl -X POST "https://p2p.mirotalk.com/api/v1/token" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":"true", "expire":"1h"}'
|
||||
$ curl -X POST "https://mirotalk.up.railway.app/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":"true", "expire":"1h"}'
|
||||
curl -X GET "http://localhost:3000/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X GET "https://p2p.mirotalk.com/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X GET "https://mirotalk.up.railway.app/api/v1/stats" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
### 2. Meetings Endpoint (Get active meetings)
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:3000/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X GET "https://p2p.mirotalk.com/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X GET "https://mirotalk.up.railway.app/api/v1/meetings" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
### 3. Create Meeting
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X POST "https://p2p.mirotalk.com/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
curl -X POST "https://mirotalk.up.railway.app/api/v1/meeting" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
### 4. Join Meeting (Basic)
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","avatar":false,"audio":true,"video":true,"screen":false,"hide":false,"notify":true}'
|
||||
curl -X POST "https://p2p.mirotalk.com/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","avatar":false,"audio":true,"video":true,"screen":false,"hide":false,"notify":true}'
|
||||
curl -X POST "https://mirotalk.up.railway.app/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","avatar":false,"audio":true,"video":true,"screen":false,"hide":false,"notify":true}'
|
||||
```
|
||||
|
||||
### 5. Join Meeting with Token
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":true,"video":true,"screen":false,"hide":false,"notify":true,"token":{"username":"username","password":"password","presenter":true,"expire":"1h"}}'
|
||||
curl -X POST "https://p2p.mirotalk.com/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":true,"video":true,"screen":false,"hide":false,"notify":true,"token":{"username":"username","password":"password","presenter":true,"expire":"1h"}}'
|
||||
curl -X POST "https://mirotalk.up.railway.app/api/v1/join" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"room":"test","name":"mirotalk","audio":true,"video":true,"screen":false,"hide":false,"notify":true,"token":{"username":"username","password":"password","presenter":true,"expire":"1h"}}'
|
||||
```
|
||||
|
||||
### 6. Generate Token
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3000/api/v1/token" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":true,"expire":"1h"}'
|
||||
curl -X POST "https://p2p.mirotalk.com/api/v1/token" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":true,"expire":"1h"}'
|
||||
curl -X POST "https://mirotalk.up.railway.app/api/v1/token" -H "authorization: mirotalkp2p_default_secret" -H "Content-Type: application/json" --data '{"username":"username","password":"password","presenter":true,"expire":"1h"}'
|
||||
```
|
||||
|
||||
These commands should now work correctly with the MiroTalk P2P
|
||||
|
||||
</details>
|
||||
|
||||
<details open>
|
||||
|
||||
@@ -21,8 +21,9 @@ async function getJoin() {
|
||||
body: JSON.stringify({
|
||||
room: 'test',
|
||||
name: 'mirotalk',
|
||||
audio: true,
|
||||
video: true,
|
||||
avatar: false,
|
||||
audio: false,
|
||||
video: false,
|
||||
screen: false,
|
||||
hide: false,
|
||||
notify: true,
|
||||
|
||||
@@ -20,8 +20,9 @@ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
$data = array(
|
||||
"room" => "test",
|
||||
"name" => "mirotalk",
|
||||
"audio" => true,
|
||||
"video" => true,
|
||||
"avatar" => false,
|
||||
"audio" => false,
|
||||
"video" => false,
|
||||
"screen" => false,
|
||||
"hide" => false,
|
||||
"notify" => true,
|
||||
|
||||
@@ -15,8 +15,9 @@ headers = {
|
||||
data = {
|
||||
"room": "test",
|
||||
"name": "mirotalk",
|
||||
"audio": "true",
|
||||
"video": "true",
|
||||
"avatar": "false",
|
||||
"audio": "false",
|
||||
"video": "false",
|
||||
"screen": "false",
|
||||
"hide": "false",
|
||||
"notify": "true",
|
||||
|
||||
+26
-6
@@ -1,12 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Configuration
|
||||
API_KEY_SECRET="mirotalkp2p_default_secret"
|
||||
MIROTALK_URL="https://p2p.mirotalk.com/api/v1/join"
|
||||
# Alternative URLs:
|
||||
# MIROTALK_URL="http://localhost:3000/api/v1/join"
|
||||
# MIROTALK_URL = "https://mirotalk.up.railway.app/api/v1/join"
|
||||
# MIROTALK_URL="https://mirotalk.up.railway.app/api/v1/join"
|
||||
|
||||
curl $MIROTALK_URL \
|
||||
--header "authorization: $API_KEY_SECRET" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{"room":"test","name":"mirotalk","audio":"true","video":"true","screen":"false","hide":"false","notify":"true","token":{"username":"username","password":"password","presenter":"true", "expire":"1h"}}' \
|
||||
--request POST
|
||||
# Join request data
|
||||
REQUEST_DATA='{
|
||||
"room": "test",
|
||||
"name": "mirotalk",
|
||||
"avatar": false,
|
||||
"audio": false,
|
||||
"video": false,
|
||||
"screen": false,
|
||||
"hide": false,
|
||||
"notify": true,
|
||||
"token": {
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"presenter": true,
|
||||
"expire": "1h"
|
||||
}
|
||||
}'
|
||||
|
||||
# Make the API request
|
||||
curl -X POST "$MIROTALK_URL" \
|
||||
-H "authorization: $API_KEY_SECRET" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$REQUEST_DATA"
|
||||
@@ -84,6 +84,9 @@ paths:
|
||||
name:
|
||||
type: string
|
||||
default: 'mirotalk'
|
||||
avatar:
|
||||
type: string
|
||||
default: ''
|
||||
audio:
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -222,6 +225,8 @@ definitions:
|
||||
properties:
|
||||
peer_name:
|
||||
type: string
|
||||
peer_avatar:
|
||||
type: string
|
||||
peer_presenter:
|
||||
type: boolean
|
||||
peer_video:
|
||||
|
||||
+3
-1
@@ -53,10 +53,11 @@ module.exports = class ServerApi {
|
||||
|
||||
getJoinURL(data) {
|
||||
// Get data
|
||||
const { room, name, audio, video, screen, notify, hide, token } = data;
|
||||
const { room, name, avatar, audio, video, screen, notify, hide, token } = data;
|
||||
|
||||
const roomValue = room || uuidV4();
|
||||
const nameValue = name || 'User-' + this.getRandomNumber();
|
||||
const avatarValue = avatar || false;
|
||||
const audioValue = audio || false;
|
||||
const videoValue = video || false;
|
||||
const screenValue = screen || false;
|
||||
@@ -70,6 +71,7 @@ module.exports = class ServerApi {
|
||||
'/join?' +
|
||||
`room=${roomValue}` +
|
||||
`&name=${encodeURIComponent(nameValue)}` +
|
||||
`&avatar=${encodeURIComponent(avatarValue)}` +
|
||||
`&audio=${audioValue}` +
|
||||
`&video=${videoValue}` +
|
||||
`&screen=${screenValue}` +
|
||||
|
||||
+10
-4
@@ -45,7 +45,7 @@ dependencies: {
|
||||
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.4.99
|
||||
* @version 1.5.00
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1204,6 +1204,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
channel_password,
|
||||
peer_uuid,
|
||||
peer_name,
|
||||
peer_avatar,
|
||||
peer_token,
|
||||
peer_video,
|
||||
peer_audio,
|
||||
@@ -1310,6 +1311,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
// collect peers info grp by channels
|
||||
peers[channel][socket.id] = {
|
||||
peer_name: peer_name,
|
||||
peer_avatar: peer_avatar,
|
||||
peer_presenter: isPresenter,
|
||||
peer_video: peer_video,
|
||||
peer_audio: peer_audio,
|
||||
@@ -1458,7 +1460,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
// Prevent XSS injection
|
||||
const config = checkXSS(cfg);
|
||||
// log.debug('Peer name', config);
|
||||
const { room_id, peer_name_old, peer_name_new } = config;
|
||||
const { room_id, peer_name_old, peer_name_new, peer_avatar } = config;
|
||||
|
||||
let peer_id_to_update = null;
|
||||
|
||||
@@ -1481,6 +1483,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
const data = {
|
||||
peer_id: peer_id_to_update,
|
||||
peer_name: peer_name_new,
|
||||
peer_avatar: peer_avatar,
|
||||
};
|
||||
log.debug('[' + socket.id + '] emit peerName to [room_id: ' + room_id + ']', data);
|
||||
|
||||
@@ -1556,7 +1559,8 @@ io.sockets.on('connect', async (socket) => {
|
||||
// Prevent XSS injection
|
||||
const config = checkXSS(cfg);
|
||||
// log.debug('Peer action', config);
|
||||
const { room_id, peer_id, peer_uuid, peer_name, peer_use_video, peer_action, send_to_all } = config;
|
||||
const { room_id, peer_id, peer_uuid, peer_name, peer_avatar, peer_use_video, peer_action, send_to_all } =
|
||||
config;
|
||||
|
||||
// Only the presenter can do this actions
|
||||
const presenterActions = ['muteAudio', 'hideVideo', 'ejectAll'];
|
||||
@@ -1570,6 +1574,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
const data = {
|
||||
peer_id: peer_id,
|
||||
peer_name: peer_name,
|
||||
peer_avatar: peer_avatar,
|
||||
peer_action: peer_action,
|
||||
peer_use_video: peer_use_video,
|
||||
};
|
||||
@@ -1622,7 +1627,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
// Prevent XSS injection
|
||||
const config = checkXSS(cfg);
|
||||
// log.debug('File info', config);
|
||||
const { room_id, peer_id, peer_name, broadcast, file } = config;
|
||||
const { room_id, peer_id, peer_name, peer_avatar, broadcast, file } = config;
|
||||
|
||||
// check if valid fileName
|
||||
if (!isValidFileName(file.fileName)) {
|
||||
@@ -1639,6 +1644,7 @@ io.sockets.on('connect', async (socket) => {
|
||||
|
||||
log.debug('[' + socket.id + '] Peer [' + peer_name + '] send file to room_id [' + room_id + ']', {
|
||||
peerName: peer_name,
|
||||
peerAvatar: peer_avatar,
|
||||
fileName: file.fileName,
|
||||
fileSize: bytesToSize(file.fileSize),
|
||||
fileType: file.fileType,
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mirotalk",
|
||||
"version": "1.4.99",
|
||||
"version": "1.5.00",
|
||||
"description": "A free WebRTC browser-based video call",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
@@ -61,7 +61,7 @@
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"nodemailer": "^6.10.0",
|
||||
"openai": "^4.91.1",
|
||||
"openai": "^4.92.1",
|
||||
"qs": "^6.14.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
+1
-1
@@ -73,7 +73,7 @@ let brand = {
|
||||
},
|
||||
about: {
|
||||
imageUrl: '../images/mirotalk-logo.gif',
|
||||
title: 'WebRTC P2P v1.4.99',
|
||||
title: 'WebRTC P2P v1.5.00',
|
||||
html: `
|
||||
<button
|
||||
id="support-button"
|
||||
|
||||
+107
-34
@@ -15,7 +15,7 @@
|
||||
* @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon
|
||||
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661
|
||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||
* @version 1.4.99
|
||||
* @version 1.5.00
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -535,6 +535,7 @@ let isToggleExtraBtnClicked = false;
|
||||
let myPeerId; // This socket.id
|
||||
let myPeerUUID = getUUID(); // Unique peer id
|
||||
let myPeerName = getPeerName();
|
||||
let myPeerAvatar = getPeerAvatar();
|
||||
let myToken = getPeerToken(); // peer JWT
|
||||
let isPresenter = false; // True Who init the room (aka first peer joined)
|
||||
let myHandStatus = false;
|
||||
@@ -1037,6 +1038,23 @@ function getPeerName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if peer avatar is set
|
||||
* @returns {string} Peer Avatar
|
||||
*/
|
||||
function getPeerAvatar() {
|
||||
const qs = new URLSearchParams(window.location.search);
|
||||
const avatar = filterXSS(qs.get('avatar'));
|
||||
const avatarDisabled = avatar === '0' || avatar === 'false';
|
||||
|
||||
console.log('Direct join', { avatar: avatar });
|
||||
|
||||
if (avatarDisabled || !isImageURL(avatar)) {
|
||||
return false;
|
||||
}
|
||||
return avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is screen enabled on join room
|
||||
* @returns {boolean} true/false
|
||||
@@ -1940,9 +1958,9 @@ function checkPeerAudioVideo() {
|
||||
*/
|
||||
async function whoAreYouJoin() {
|
||||
myVideoParagraph.innerText = myPeerName + ' (me)';
|
||||
setPeerAvatarImgName('myVideoAvatarImage', myPeerName);
|
||||
setPeerAvatarImgName('myProfileAvatar', myPeerName);
|
||||
setPeerChatAvatarImgName('right', myPeerName);
|
||||
setPeerAvatarImgName('myVideoAvatarImage', myPeerName, myPeerAvatar);
|
||||
setPeerAvatarImgName('myProfileAvatar', myPeerName, myPeerAvatar);
|
||||
setPeerChatAvatarImgName('right', myPeerName, myPeerAvatar);
|
||||
joinToChannel();
|
||||
handleHideMe(isHideMeActive);
|
||||
}
|
||||
@@ -1959,6 +1977,7 @@ async function joinToChannel() {
|
||||
peer_info: peerInfo,
|
||||
peer_uuid: myPeerUUID,
|
||||
peer_name: myPeerName,
|
||||
peer_avatar: myPeerAvatar,
|
||||
peer_token: myToken,
|
||||
peer_video: useVideo,
|
||||
peer_audio: useAudio,
|
||||
@@ -3286,6 +3305,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
console.log('REMOTE PEER INFO', peers[peer_id]);
|
||||
|
||||
const peer_name = peers[peer_id]['peer_name'];
|
||||
const peer_avatar = peers[peer_id]['peer_avatar'];
|
||||
const peer_audio = peers[peer_id]['peer_audio'];
|
||||
const peer_video = peers[peer_id]['peer_video'];
|
||||
const peer_video_status = peers[peer_id]['peer_video_status'];
|
||||
@@ -3557,7 +3577,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
peer_privacy_status && setVideoPrivacyStatus(remoteMedia.id, peer_privacy_status);
|
||||
|
||||
// refresh remote peers avatar name
|
||||
setPeerAvatarImgName(remoteVideoAvatarImage.id, peer_name);
|
||||
setPeerAvatarImgName(remoteVideoAvatarImage.id, peer_name, peer_avatar);
|
||||
// refresh remote peers hand icon status and title
|
||||
setPeerHandStatus(peer_id, peer_name, peer_hand_status);
|
||||
// refresh remote peers video icon status and title
|
||||
@@ -3580,7 +3600,7 @@ async function loadRemoteMediaStream(stream, peers, peer_id, kind) {
|
||||
toggleClassElements('statusMenu', 'inline');
|
||||
|
||||
// notify if peer started to recording own screen + audio
|
||||
if (peer_rec_status) notifyRecording(peer_id, peer_name, 'Started');
|
||||
if (peer_rec_status) notifyRecording(peer_id, peer_name, peer_avatar, 'Started');
|
||||
|
||||
// Peer without camera, screen sharing OFF
|
||||
if (!peer_video && !peer_screen_status) {
|
||||
@@ -3782,15 +3802,24 @@ function genAvatarSvg(peerName, avatarImgSize) {
|
||||
* Refresh video - chat image avatar on name changes: https://eu.ui-avatars.com/
|
||||
* @param {string} videoAvatarImageId element id
|
||||
* @param {string} peerName
|
||||
* @param {string} peerAvatar
|
||||
*/
|
||||
function setPeerAvatarImgName(videoAvatarImageId, peerName) {
|
||||
function setPeerAvatarImgName(videoAvatarImageId, peerName, peerAvatar) {
|
||||
const videoAvatarImageElement = getId(videoAvatarImageId);
|
||||
videoAvatarImageElement.style.pointerEvents = 'none';
|
||||
if (useAvatarSvg) {
|
||||
|
||||
// If a valid avatar image URL is provided
|
||||
if (peerAvatar && isImageURL(peerAvatar)) {
|
||||
videoAvatarImageElement.setAttribute('src', peerAvatar);
|
||||
}
|
||||
// If not, use SVG based on the email validity
|
||||
else if (useAvatarSvg) {
|
||||
const avatarImgSize = isMobileDevice ? 128 : 256;
|
||||
const avatarImgSvg = isValidEmail(peerName) ? genGravatar(peerName) : genAvatarSvg(peerName, avatarImgSize);
|
||||
videoAvatarImageElement.setAttribute('src', avatarImgSvg);
|
||||
} else {
|
||||
}
|
||||
// Default fallback avatar
|
||||
else {
|
||||
videoAvatarImageElement.setAttribute('src', images.avatar);
|
||||
}
|
||||
}
|
||||
@@ -3799,9 +3828,15 @@ function setPeerAvatarImgName(videoAvatarImageId, peerName) {
|
||||
* Set Chat avatar image by peer name
|
||||
* @param {string} avatar position left/right
|
||||
* @param {string} peerName me or peer name
|
||||
* @param {string} peerAvatar me or peer avatar
|
||||
*/
|
||||
function setPeerChatAvatarImgName(avatar, peerName) {
|
||||
const avatarImg = isValidEmail(peerName) ? genGravatar(peerName) : genAvatarSvg(peerName, 32);
|
||||
function setPeerChatAvatarImgName(avatar, peerName, peerAvatar) {
|
||||
const avatarImg =
|
||||
peerAvatar && isImageURL(peerAvatar)
|
||||
? peerAvatar
|
||||
: isValidEmail(peerName)
|
||||
? genGravatar(peerName)
|
||||
: genAvatarSvg(peerName, 32);
|
||||
|
||||
switch (avatar) {
|
||||
case 'left':
|
||||
@@ -7215,12 +7250,14 @@ function getAudioStreamFromAudioElements() {
|
||||
* Notify me if someone start to recording they camera/screen/window + audio
|
||||
* @param {string} fromId peer_id
|
||||
* @param {string} from peer_name
|
||||
* @param {string} fromAvatar peer_avatar
|
||||
* @param {string} action recording action
|
||||
*/
|
||||
function notifyRecording(fromId, from, action) {
|
||||
function notifyRecording(fromId, from, fromAvatar, action) {
|
||||
const msg = '🔴 ' + action + ' conference recording';
|
||||
const chatMessage = {
|
||||
from: from,
|
||||
fromAvatar: fromAvatar,
|
||||
fromId: fromId,
|
||||
to: myPeerName,
|
||||
msg: msg,
|
||||
@@ -7829,7 +7866,7 @@ async function sendChatMessage() {
|
||||
return cleanMessageInput();
|
||||
}
|
||||
|
||||
isChatGPTOn ? await getChatGPTmessage(msg) : emitMsg(myPeerName, 'toAll', msg, false, myPeerId);
|
||||
isChatGPTOn ? await getChatGPTmessage(msg) : emitMsg(myPeerName, myPeerAvatar, 'toAll', msg, false, myPeerId);
|
||||
appendMessage(myPeerName, rightChatAvatar, 'right', msg, false);
|
||||
cleanMessageInput();
|
||||
}
|
||||
@@ -7843,6 +7880,7 @@ function handleDataChannelChat(dataMessage) {
|
||||
|
||||
// sanitize all params
|
||||
const msgFrom = filterXSS(dataMessage.from);
|
||||
const msgFromAvatar = filterXSS(dataMessage.fromAvatar);
|
||||
const msgFromId = filterXSS(dataMessage.fromId);
|
||||
const msgTo = filterXSS(dataMessage.to);
|
||||
const msg = filterXSS(dataMessage.msg);
|
||||
@@ -7871,7 +7909,7 @@ function handleDataChannelChat(dataMessage) {
|
||||
userLog('toast', `New message from: ${msgFrom}`);
|
||||
}
|
||||
|
||||
setPeerChatAvatarImgName('left', msgFrom);
|
||||
setPeerChatAvatarImgName('left', msgFrom, msgFromAvatar);
|
||||
appendMessage(msgFrom, leftChatAvatar, 'left', msg, msgPrivate, msgId, msgFrom);
|
||||
speechInMessages ? speechMessage(true, msgFrom, msg) : playSound('chatMessage');
|
||||
}
|
||||
@@ -7918,11 +7956,18 @@ function handleSpeechTranscript(config) {
|
||||
|
||||
config.text_data = filterXSS(config.text_data);
|
||||
config.peer_name = filterXSS(config.peer_name);
|
||||
config.peer_avatar = filterXSS(config.peer_avatar);
|
||||
|
||||
const { peer_name, text_data } = config;
|
||||
const { peer_name, peer_avatar, text_data } = config;
|
||||
|
||||
const time_stamp = getFormatDate(new Date());
|
||||
const avatar_image = isValidEmail(peer_name) ? genGravatar(peer_name) : genAvatarSvg(peer_name, 32);
|
||||
|
||||
const avatar_image =
|
||||
peer_avatar && isImageURL(peer_avatar)
|
||||
? peer_avatar
|
||||
: isValidEmail(peer_name)
|
||||
? genGravatar(peer_name)
|
||||
: genAvatarSvg(peer_name, 32);
|
||||
|
||||
if (!isCaptionBoxVisible) showCaptionDraggable();
|
||||
|
||||
@@ -8217,16 +8262,24 @@ async function msgerAddPeers(peers) {
|
||||
// add all current Participants
|
||||
for (const peer_id in peers) {
|
||||
const peer_name = peers[peer_id]['peer_name'];
|
||||
const peer_avatar = peers[peer_id]['peer_avatar'];
|
||||
// bypass insert to myself in the list :)
|
||||
if (peer_id != myPeerId && peer_name) {
|
||||
const exsistMsgerPrivateDiv = getId(peer_id + '_pMsgDiv');
|
||||
// if there isn't add it....
|
||||
if (!exsistMsgerPrivateDiv) {
|
||||
const avatarSvg = isValidEmail(peer_name) ? genGravatar(peer_name) : genAvatarSvg(peer_name, 24);
|
||||
//
|
||||
const chatAvatar =
|
||||
peer_avatar && isImageURL(peer_avatar)
|
||||
? peer_avatar
|
||||
: isValidEmail(peer_name)
|
||||
? genGravatar(peer_name)
|
||||
: genAvatarSvg(peer_name, 24);
|
||||
|
||||
const msgerPrivateDiv = `
|
||||
<div id="${peer_id}_pMsgDiv" class="msger-peer-inputarea">
|
||||
<span style="display: none">${peer_name}</span>
|
||||
<img id="${peer_id}_pMsgAvatar" class="peer-img" src="${avatarSvg}">
|
||||
<img id="${peer_id}_pMsgAvatar" class="peer-img" src="${chatAvatar}">
|
||||
<textarea
|
||||
rows="1"
|
||||
cols="1"
|
||||
@@ -8323,7 +8376,7 @@ function addMsgerPrivateBtn(msgerPrivateBtn, msgerPrivateMsgInput, peerId) {
|
||||
}
|
||||
|
||||
const toPeerName = msgerPrivateBtn.value;
|
||||
emitMsg(myPeerName, toPeerName, pMsg, true, peerId);
|
||||
emitMsg(myPeerName, myPeerAvatar, toPeerName, pMsg, true, peerId);
|
||||
appendMessage(myPeerName, rightChatAvatar, 'right', pMsg, true, null, toPeerName);
|
||||
msgerPrivateMsgInput.value = '';
|
||||
elemDisplay(msgerCP, false);
|
||||
@@ -8404,8 +8457,14 @@ function isValidHttpURL(input) {
|
||||
* @param {string} url to check
|
||||
* @returns {boolean} true/false
|
||||
*/
|
||||
function isImageURL(url) {
|
||||
return url.match(/\.(jpeg|jpg|gif|png|tiff|bmp)$/) != null;
|
||||
async function isImageURL(url) {
|
||||
try {
|
||||
const response = await fetch(url, { method: 'HEAD' });
|
||||
const contentType = response.headers.get('content-type');
|
||||
return contentType && contentType.startsWith('image/');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8515,16 +8574,18 @@ function getFormatDate(date) {
|
||||
/**
|
||||
* Send message over Secure dataChannels
|
||||
* @param {string} from peer name
|
||||
* @param {string} fromAvatar peer avatar
|
||||
* @param {string} to peer name
|
||||
* @param {string} msg message to send
|
||||
* @param {boolean} privateMsg if is a private message
|
||||
* @param {string} id peer_id
|
||||
*/
|
||||
function emitMsg(from, to, msg, privateMsg, id) {
|
||||
function emitMsg(from, fromAvatar, to, msg, privateMsg, id) {
|
||||
if (!msg) return;
|
||||
|
||||
// sanitize all params
|
||||
const getFrom = filterXSS(from);
|
||||
const getFromAvatar = filterXSS(fromAvatar);
|
||||
const getFromId = filterXSS(myPeerId);
|
||||
const getTo = filterXSS(to);
|
||||
const getMsg = filterXSS(msg);
|
||||
@@ -8534,6 +8595,7 @@ function emitMsg(from, to, msg, privateMsg, id) {
|
||||
const chatMessage = {
|
||||
type: 'chat',
|
||||
from: getFrom,
|
||||
fromAvatar: getFromAvatar,
|
||||
fromId: getFromId,
|
||||
id: getId,
|
||||
to: getTo,
|
||||
@@ -8704,6 +8766,7 @@ async function updateMyPeerName() {
|
||||
room_id: roomId,
|
||||
peer_name_old: myOldPeerName,
|
||||
peer_name_new: myPeerName,
|
||||
peer_avatar: myPeerAvatar,
|
||||
});
|
||||
|
||||
myPeerNameSet.value = '';
|
||||
@@ -8711,9 +8774,9 @@ async function updateMyPeerName() {
|
||||
|
||||
window.localStorage.peer_name = myPeerName;
|
||||
|
||||
setPeerAvatarImgName('myVideoAvatarImage', myPeerName);
|
||||
setPeerAvatarImgName('myProfileAvatar', myPeerName);
|
||||
setPeerChatAvatarImgName('right', myPeerName);
|
||||
setPeerAvatarImgName('myVideoAvatarImage', myPeerName, myPeerAvatar);
|
||||
setPeerAvatarImgName('myProfileAvatar', myPeerName, myPeerAvatar);
|
||||
setPeerChatAvatarImgName('right', myPeerName, myPeerAvatar);
|
||||
userLog('toast', 'My name changed to ' + myPeerName);
|
||||
}
|
||||
|
||||
@@ -8722,18 +8785,25 @@ async function updateMyPeerName() {
|
||||
* @param {object} config data
|
||||
*/
|
||||
function handlePeerName(config) {
|
||||
const { peer_id, peer_name } = config;
|
||||
const { peer_id, peer_name, peer_avatar } = config;
|
||||
const videoName = getId(peer_id + '_name');
|
||||
if (videoName) videoName.innerText = peer_name;
|
||||
// change also avatar and btn value - name on chat lists....
|
||||
const msgerPeerName = getId(peer_id + '_pMsgBtn');
|
||||
const msgerPeerAvatar = getId(peer_id + '_pMsgAvatar');
|
||||
if (msgerPeerName) msgerPeerName.value = peer_name;
|
||||
|
||||
if (msgerPeerAvatar) {
|
||||
msgerPeerAvatar.src = isValidEmail(peer_name) ? genGravatar(peer_name) : genAvatarSvg(peer_name, 32);
|
||||
msgerPeerAvatar.src =
|
||||
peer_avatar && isImageURL(peer_avatar)
|
||||
? peer_avatar
|
||||
: isValidEmail(peer_name)
|
||||
? genGravatar(peer_name)
|
||||
: genAvatarSvg(peer_name, 32);
|
||||
}
|
||||
|
||||
// refresh also peer video avatar name
|
||||
setPeerAvatarImgName(peer_id + '_avatar', peer_name);
|
||||
setPeerAvatarImgName(peer_id + '_avatar', peer_name, peer_avatar);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8992,7 +9062,7 @@ function sendPrivateMsgToPeer(toPeerId, toPeerName) {
|
||||
isChatPasteTxt = false;
|
||||
return;
|
||||
}
|
||||
emitMsg(myPeerName, toPeerName, pMsg, true, toPeerId);
|
||||
emitMsg(myPeerName, myPeerAvatar, toPeerName, pMsg, true, toPeerId);
|
||||
appendMessage(myPeerName, rightChatAvatar, 'right', pMsg, true, null, toPeerName);
|
||||
userLog('toast', 'Message sent to ' + toPeerName + ' 👍');
|
||||
}
|
||||
@@ -9059,6 +9129,7 @@ async function emitPeersAction(peerAction) {
|
||||
sendToServer('peerAction', {
|
||||
room_id: roomId,
|
||||
peer_name: myPeerName,
|
||||
peer_avatar: myPeerAvatar,
|
||||
peer_id: myPeerId,
|
||||
peer_uuid: myPeerUUID,
|
||||
peer_use_video: useVideo,
|
||||
@@ -9078,6 +9149,7 @@ async function emitPeerAction(peer_id, peerAction) {
|
||||
sendToServer('peerAction', {
|
||||
room_id: roomId,
|
||||
peer_id: peer_id,
|
||||
peer_avatar: myPeerAvatar,
|
||||
peer_use_video: useVideo,
|
||||
peer_name: myPeerName,
|
||||
peer_action: peerAction,
|
||||
@@ -9091,7 +9163,7 @@ async function emitPeerAction(peer_id, peerAction) {
|
||||
*/
|
||||
function handlePeerAction(config) {
|
||||
console.log('Handle peer action: ', config);
|
||||
const { peer_id, peer_name, peer_use_video, peer_action } = config;
|
||||
const { peer_id, peer_name, peer_avatar, peer_use_video, peer_action } = config;
|
||||
|
||||
switch (peer_action) {
|
||||
case 'muteAudio':
|
||||
@@ -9101,10 +9173,10 @@ function handlePeerAction(config) {
|
||||
setMyVideoOff(peer_name);
|
||||
break;
|
||||
case 'recStart':
|
||||
notifyRecording(peer_id, peer_name, 'Start');
|
||||
notifyRecording(peer_id, peer_name, peer_avatar, 'Start');
|
||||
break;
|
||||
case 'recStop':
|
||||
notifyRecording(peer_id, peer_name, 'Stop');
|
||||
notifyRecording(peer_id, peer_name, peer_avatar, 'Stop');
|
||||
break;
|
||||
case 'screenStart':
|
||||
handleScreenStart(peer_id);
|
||||
@@ -10574,6 +10646,7 @@ function sendFileInformations(file, peer_id, broadcast = false) {
|
||||
room_id: roomId,
|
||||
broadcast: broadcast,
|
||||
peer_name: myPeerName,
|
||||
peer_avatar: myPeerAvatar,
|
||||
peer_id: peer_id,
|
||||
file: {
|
||||
fileName: fileToSend.name,
|
||||
@@ -10640,7 +10713,7 @@ function handleFileInfo(config) {
|
||||
incomingFileInfo.file.fileType;
|
||||
console.log(fileToReceiveInfo);
|
||||
// generate chat avatar by peer_name
|
||||
setPeerChatAvatarImgName('left', incomingFileInfo.peer_name);
|
||||
setPeerChatAvatarImgName('left', incomingFileInfo.peer_name, incomingFileInfo.peer_avatar);
|
||||
// keep track of received file on chat
|
||||
appendMessage(
|
||||
incomingFileInfo.peer_name,
|
||||
@@ -11085,7 +11158,7 @@ function showAbout() {
|
||||
Swal.fire({
|
||||
background: swBg,
|
||||
position: 'center',
|
||||
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.4.99',
|
||||
title: brand.about?.title && brand.about.title.trim() !== '' ? brand.about.title : 'WebRTC P2P v1.5.00',
|
||||
imageUrl: brand.about?.imageUrl && brand.about.imageUrl.trim() !== '' ? brand.about.imageUrl : images.about,
|
||||
customClass: { image: 'img-about' },
|
||||
html: `
|
||||
|
||||
@@ -2,6 +2,7 @@ class IframeApi {
|
||||
static DEFAULT_OPTIONS = {
|
||||
room: 'default-room',
|
||||
name: 'guest',
|
||||
avatar: false,
|
||||
audio: false,
|
||||
video: false,
|
||||
screen: false,
|
||||
@@ -44,6 +45,7 @@ class IframeApi {
|
||||
const params = new URLSearchParams({
|
||||
room: this.options.room,
|
||||
name: this.options.name,
|
||||
avatar: this.options.avatar ? this.options.avatar : 0,
|
||||
audio: this.options.audio ? 1 : 0,
|
||||
video: this.options.video ? 1 : 0,
|
||||
screen: this.options.screen ? 1 : 0,
|
||||
|
||||
@@ -112,6 +112,7 @@ if (speechRecognition) {
|
||||
type: 'speech',
|
||||
room_id: roomId,
|
||||
peer_name: myPeerName,
|
||||
peer_avatar: myPeerAvatar,
|
||||
text_data: transcript,
|
||||
time_stamp: new Date(),
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
const options = {
|
||||
room: 'test',
|
||||
name: 'mirotalk',
|
||||
avatar: 'https://p2p.mirotalk.com/images/mirotalk-logo.png',
|
||||
audio: 0,
|
||||
video: 0,
|
||||
screen: 0,
|
||||
|
||||
+3
-2
@@ -136,6 +136,7 @@ describe('test-api', () => {
|
||||
const data = {
|
||||
room: 'room1',
|
||||
name: 'John Doe',
|
||||
avatar: 'avatar.jpg',
|
||||
audio: true,
|
||||
video: false,
|
||||
screen: false,
|
||||
@@ -148,7 +149,7 @@ describe('test-api', () => {
|
||||
|
||||
const result = serverApi.getJoinURL(data);
|
||||
result.should.equal(
|
||||
'https://example.com/join?room=room1&name=John%20Doe&audio=true&video=false&screen=false&hide=false¬ify=false&token=testToken',
|
||||
'https://example.com/join?room=room1&name=John%20Doe&avatar=avatar.jpg&audio=true&video=false&screen=false&hide=false¬ify=false&token=testToken',
|
||||
);
|
||||
|
||||
tokenStub.restore();
|
||||
@@ -166,7 +167,7 @@ describe('test-api', () => {
|
||||
|
||||
const result = serverApi.getJoinURL({});
|
||||
result.should.equal(
|
||||
'https://example.com/join?room=room1&name=User-123456&audio=false&video=false&screen=false&hide=false¬ify=false',
|
||||
'https://example.com/join?room=room1&name=User-123456&avatar=false&audio=false&video=false&screen=false&hide=false¬ify=false',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user