v1.6.0/speculative fix for call conflict
This commit is contained in:
+48
-28
@@ -9,14 +9,14 @@ ALL CONTENT ON WATCH PARTY'S WEBSITE OR IN WATCH PARTY'S CHROME EXTENSION APP, U
|
|||||||
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
||||||
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
import VoxeetSDK from '@voxeet/voxeet-web-sdk';
|
import VoxeetSDK from "@voxeet/voxeet-web-sdk";
|
||||||
import {
|
import {
|
||||||
GetVoxeetTokenApi,
|
GetVoxeetTokenApi,
|
||||||
GetRefreshedVoxeetTokenApi,
|
GetRefreshedVoxeetTokenApi,
|
||||||
LocalData,
|
LocalData,
|
||||||
UpdateVoxeetApi,
|
UpdateVoxeetApi,
|
||||||
updateLocalData,
|
updateLocalData,
|
||||||
} from './Api';
|
} from "./Api";
|
||||||
|
|
||||||
export default class CallManager {
|
export default class CallManager {
|
||||||
constructor(listener, notify) {
|
constructor(listener, notify) {
|
||||||
@@ -29,11 +29,15 @@ export default class CallManager {
|
|||||||
this.__adminOnly = true;
|
this.__adminOnly = true;
|
||||||
}
|
}
|
||||||
toggleCall(onCall, conference, admin, adminOnly) {
|
toggleCall(onCall, conference, admin, adminOnly) {
|
||||||
|
try {
|
||||||
this.listener({ callActionPending: true });
|
this.listener({ callActionPending: true });
|
||||||
this.__admin = admin;
|
this.__admin = admin;
|
||||||
this.__adminOnly = adminOnly;
|
this.__adminOnly = adminOnly;
|
||||||
if (onCall === true) this.leaveCall();
|
if (onCall === true) this.leaveCall();
|
||||||
else this.boot(conference);
|
else this.boot(conference);
|
||||||
|
} catch (e) {
|
||||||
|
this.notify("Uh oh something went wrong, try rejoining the call.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toggleMute(muted) {
|
toggleMute(muted) {
|
||||||
this.listener({ callActionPending: true });
|
this.listener({ callActionPending: true });
|
||||||
@@ -48,20 +52,23 @@ export default class CallManager {
|
|||||||
.fetch(conference._id)
|
.fetch(conference._id)
|
||||||
.then(this.joinCall)
|
.then(this.joinCall)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Failed to fetch conference', err);
|
console.error("Failed to fetch conference", err);
|
||||||
this.startCall();
|
this.startCall();
|
||||||
});
|
});
|
||||||
} else if (opened && !conference) {
|
} else if (opened && !conference) {
|
||||||
this.startCall();
|
this.startCall();
|
||||||
} else {
|
} else {
|
||||||
this.listener({ onCall: false, muted: false, callActionPending: false });
|
this.listener({ onCall: false, muted: false, callActionPending: false });
|
||||||
console.error('Unable to open Voxeet Session');
|
console.error("Unable to open Voxeet Session");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async startCall() {
|
async startCall() {
|
||||||
if (!this.__adminOnly || (this.__adminOnly && this.__admin)) {
|
if (!this.__adminOnly || (this.__adminOnly && this.__admin)) {
|
||||||
VoxeetSDK.conference
|
VoxeetSDK.conference
|
||||||
.create({ alias: `AUTODELETE_${LocalData().partyName}`, pin: LocalData().partyPin })
|
.create({
|
||||||
|
alias: `AUTODELETE_${LocalData().partyName}`,
|
||||||
|
pin: LocalData().partyPin,
|
||||||
|
})
|
||||||
.then(async (conference) => {
|
.then(async (conference) => {
|
||||||
const updatedVoxeet = await UpdateVoxeetApi({
|
const updatedVoxeet = await UpdateVoxeetApi({
|
||||||
conference,
|
conference,
|
||||||
@@ -77,20 +84,28 @@ export default class CallManager {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
this.notify(err.message);
|
this.notify(err.message);
|
||||||
this.listener({ onCall: false, muted: false, callActionPending: false });
|
this.listener({
|
||||||
console.error('Update Voxeet API Error', err);
|
onCall: false,
|
||||||
|
muted: false,
|
||||||
|
callActionPending: false,
|
||||||
|
});
|
||||||
|
console.error("Update Voxeet API Error", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (updatedVoxeet === true) {
|
if (updatedVoxeet === true) {
|
||||||
this.joinCall(conference);
|
this.joinCall(conference);
|
||||||
} else {
|
} else {
|
||||||
this.listener({ onCall: false, muted: false, callActionPending: false });
|
this.listener({
|
||||||
console.error('Failed to update party Voxeet');
|
onCall: false,
|
||||||
|
muted: false,
|
||||||
|
callActionPending: false,
|
||||||
|
});
|
||||||
|
console.error("Failed to update party Voxeet");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.notify('Ask your party admin to start the call.');
|
this.notify("Ask your party admin to start the call.");
|
||||||
this.leaveCall();
|
this.leaveCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,14 +114,15 @@ export default class CallManager {
|
|||||||
.join(conference, { constraints: { audio: true, video: false } })
|
.join(conference, { constraints: { audio: true, video: false } })
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
this.listener({ onCall: false, muted: false, callActionPending: false });
|
this.listener({
|
||||||
this.notify('Unable to join call. Try again in a moment.');
|
onCall: false,
|
||||||
console.error('Error joining call', e);
|
muted: false,
|
||||||
|
callActionPending: false,
|
||||||
|
});
|
||||||
|
this.notify("Unable to join call. Try again in a moment.");
|
||||||
|
console.error("Error joining call", e);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!joined) {
|
|
||||||
this.startCall();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async leaveCall() {
|
async leaveCall() {
|
||||||
VoxeetSDK.conference.leave().then(() => {
|
VoxeetSDK.conference.leave().then(() => {
|
||||||
@@ -123,9 +139,9 @@ export default class CallManager {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error Opening Voxeet Session', error);
|
console.error("Error Opening Voxeet Session", error);
|
||||||
}
|
}
|
||||||
console.error('Session not initialized');
|
console.error("Session not initialized");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -138,22 +154,26 @@ export default class CallManager {
|
|||||||
this.listener({ usersOnCall });
|
this.listener({ usersOnCall });
|
||||||
}
|
}
|
||||||
async initialize() {
|
async initialize() {
|
||||||
VoxeetSDK.conference.on('participantAdded', () => this.usersListHandle());
|
VoxeetSDK.conference.on("participantAdded", () => this.usersListHandle());
|
||||||
VoxeetSDK.conference.on('participantUpdated', () => this.usersListHandle());
|
VoxeetSDK.conference.on("participantUpdated", () => this.usersListHandle());
|
||||||
|
|
||||||
VoxeetSDK.conference.on('joined', () => {
|
VoxeetSDK.conference.on("joined", () => {
|
||||||
this.listener({ onCall: true, callActionPending: false });
|
this.listener({ onCall: true, callActionPending: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
VoxeetSDK.conference.on('left', () => {
|
VoxeetSDK.conference.on("left", () => {
|
||||||
this.listener({ onCall: false, callActionPending: false, usersOnCall: {} });
|
this.listener({
|
||||||
|
onCall: false,
|
||||||
|
callActionPending: false,
|
||||||
|
usersOnCall: {},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
VoxeetSDK.conference.on('streamAdded', (participant, stream) => {
|
VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
|
||||||
this.listener({ callActionPending: false });
|
this.listener({ callActionPending: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
VoxeetSDK.conference.on('streamRemoved', (participant, stream) => {
|
VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
|
||||||
this.listener({ callActionPending: false });
|
this.listener({ callActionPending: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -171,11 +191,11 @@ export default class CallManager {
|
|||||||
this.updateTokens(access_token, refresh_token);
|
this.updateTokens(access_token, refresh_token);
|
||||||
VoxeetSDK.initializeToken(access_token, refresh_token);
|
VoxeetSDK.initializeToken(access_token, refresh_token);
|
||||||
} else {
|
} else {
|
||||||
console.error('Get Voxeet Token API Result Error', tokenResult);
|
console.error("Get Voxeet Token API Result Error", tokenResult);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Get Voxeet Token API error', err);
|
console.error("Get Voxeet Token API error", err);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
VoxeetSDK.initializeToken(this.__accessToken, this.__refreshToken);
|
VoxeetSDK.initializeToken(this.__accessToken, this.__refreshToken);
|
||||||
@@ -191,7 +211,7 @@ export default class CallManager {
|
|||||||
resolve(access_token);
|
resolve(access_token);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Get Voxeet Token API error', err);
|
console.error("Get Voxeet Token API error", err);
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-2
@@ -12,8 +12,9 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
|||||||
.thread-container * {
|
.thread-container * {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: 'Roboto', sans-serif !important;
|
font-family: "Roboto", sans-serif !important;
|
||||||
letter-spacing: 1.15px;
|
letter-spacing: 1.15px;
|
||||||
|
word-break: break-word !important;
|
||||||
}
|
}
|
||||||
.thread-container {
|
.thread-container {
|
||||||
max-height: none;
|
max-height: none;
|
||||||
@@ -99,7 +100,7 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
font-family: 'Roboto';
|
font-family: "Roboto";
|
||||||
letter-spacing: 1.5px;
|
letter-spacing: 1.5px;
|
||||||
white-space: break-spaces;
|
white-space: break-spaces;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
const admin = require('firebase-admin');
|
const admin = require("firebase-admin");
|
||||||
|
|
||||||
module.exports = async (req, res) => {
|
module.exports = async (req, res) => {
|
||||||
const { conference, partyName, partyPin, userName, uid } = JSON.parse(req.body);
|
const { conference, partyName, partyPin, userName, uid } = JSON.parse(
|
||||||
|
req.body
|
||||||
|
);
|
||||||
// GET ROOM PIN
|
// GET ROOM PIN
|
||||||
const [exists, roomPin, conferencePending, partyConference] = await admin
|
const [exists, roomPin, conferencePending, partyConference] = await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(partyName)
|
.doc(partyName)
|
||||||
.get()
|
.get()
|
||||||
.then((roomSnap) => {
|
.then((roomSnap) => {
|
||||||
const data = roomSnap.exists ? roomSnap.data() : {};
|
const data = roomSnap.exists ? roomSnap.data() : {};
|
||||||
return [roomSnap.exists, data.pin, data.conferencePending, data.conference];
|
return [
|
||||||
|
roomSnap.exists,
|
||||||
|
data.pin,
|
||||||
|
data.conferencePending,
|
||||||
|
data.conference,
|
||||||
|
];
|
||||||
});
|
});
|
||||||
// CHECK IF ROOM EXISTS
|
// CHECK IF ROOM EXISTS
|
||||||
if (exists === true) {
|
if (exists === true) {
|
||||||
@@ -22,47 +29,61 @@ module.exports = async (req, res) => {
|
|||||||
// UPDATE CONFERENCE DETAILS
|
// UPDATE CONFERENCE DETAILS
|
||||||
await admin
|
await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(partyName)
|
.doc(partyName)
|
||||||
.update({ conference })
|
.update({ conference })
|
||||||
.catch((err) =>
|
.catch((err) =>
|
||||||
res.status(500).send({ message: 'Unable to update the call details', error: err })
|
res.status(500).send({
|
||||||
|
message: "Unable to update the call details",
|
||||||
|
error: err,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
// REMOVE PENDING STATUS
|
// REMOVE PENDING STATUS
|
||||||
await admin
|
await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(partyName)
|
.doc(partyName)
|
||||||
.update({ conferencePending : admin.firestore.FieldValue.delete() })
|
.update({
|
||||||
.catch((err) => console.error('Failed to remove pending status', err));
|
conferencePending: admin.firestore.FieldValue.delete(),
|
||||||
|
})
|
||||||
|
.catch((err) =>
|
||||||
|
console.error("Failed to remove pending status", err)
|
||||||
|
);
|
||||||
// ADD SYSTEM MESSAGE
|
// ADD SYSTEM MESSAGE
|
||||||
await admin
|
await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(partyName)
|
.doc(partyName)
|
||||||
.collection('messages')
|
.collection("messages")
|
||||||
.add({
|
.add({
|
||||||
uid: '<system>',
|
uid: "<system>",
|
||||||
name: '',
|
name: "",
|
||||||
text: `${userName} started the call, everyone can join now.`,
|
text: `${userName} started the call, everyone can join now.`,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
})
|
})
|
||||||
.catch((err) => console.error('Failed to add update conference message', err));
|
.catch((err) =>
|
||||||
res.status(200).send({ message: 'Started the conference' });
|
console.error("Failed to add update conference message", err)
|
||||||
|
);
|
||||||
|
res.status(200).send({ message: "Started the conference" });
|
||||||
} else {
|
} else {
|
||||||
res.status(409).send({ message: 'Looks like someone is already starting a call' });
|
res.status(409).send({
|
||||||
|
message: "Looks like someone is already starting a call",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (partyConference) {
|
} else if (partyConference) {
|
||||||
res.status(409).send({ message: 'Call already exists', conference: partyConference });
|
res.status(409).send({
|
||||||
|
message: "Call already exists",
|
||||||
|
conference: partyConference,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// WRONG ROOM PIN
|
// WRONG ROOM PIN
|
||||||
res.status(401).send({ message: 'Wrong party pin, try rejoining' });
|
res.status(401).send({ message: "Wrong party pin, try rejoining" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ROOM DOESN'T EXIST
|
// ROOM DOESN'T EXIST
|
||||||
res.status(404).send({ message: 'Party Not Found' });
|
res.status(404).send({ message: "Party Not Found" });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,30 +1,70 @@
|
|||||||
const admin = require('firebase-admin');
|
const admin = require("firebase-admin");
|
||||||
|
|
||||||
module.exports = async (req, res) => {
|
module.exports = async (req, res) => {
|
||||||
console.info(`[START]\tWEBHOOKS/Conference End\nID:${req.body.conference.confId}\nParty:${req.body.conference.confAlias}`);
|
console.info(
|
||||||
if (req.body.eventType === 'Conference.Ended') {
|
`[START]\tWEBHOOKS/Conference End\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
|
// MAKE SURE CORRECT EVENT TYPE
|
||||||
|
if (req.body.eventType === "Conference.Ended") {
|
||||||
|
// MAKE SURE IT'S NOT A DUPLICATE FROM CREATE CONFLICT
|
||||||
if (req.body.participants.length > 0) {
|
if (req.body.participants.length > 0) {
|
||||||
if (req.body.confAlias.startsWith('AUTODELETE_')) {
|
// MAKE SURE ELIGIBLE FOR DELETE
|
||||||
|
if (req.body.confAlias.startsWith("AUTODELETE_")) {
|
||||||
const partyName = req.body.confAlias.replace(/AUTODELETE_/, "");
|
const partyName = req.body.confAlias.replace(/AUTODELETE_/, "");
|
||||||
admin.firestore()
|
const existingConference = await admin
|
||||||
.collection('rooms')
|
.firestore()
|
||||||
|
.collection("rooms")
|
||||||
|
.doc(partyName)
|
||||||
|
.get()
|
||||||
|
.then((snap) => (snap.exists ? snap.data().conference : null));
|
||||||
|
// MAKE SURE EXISTS AND HAS NOT BEEN REPLACED
|
||||||
|
if (
|
||||||
|
existingConference &&
|
||||||
|
existingConference._id === req.body.conference.confId
|
||||||
|
) {
|
||||||
|
// REMOVE CONFERENCE DETAILS
|
||||||
|
await admin
|
||||||
|
.firestore()
|
||||||
|
.collection("rooms")
|
||||||
.doc(partyName)
|
.doc(partyName)
|
||||||
.update({ conference: admin.firestore.FieldValue.delete() })
|
.update({ conference: admin.firestore.FieldValue.delete() })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.info(`[DONE]\tWEBHOOKS/Conference End\nID:${req.body.conference.confId}\nParty:${req.body.conference.confAlias}`);
|
console.info(
|
||||||
|
`[DONE]\tWEBHOOKS/Conference End\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
console.error(`[ERROR]\tWEBHOOKS/Conference End/Firebase Error\nID:${req.body.conference.confId}\nParty:${req.body.conference.confAlias}\nError:${JSON.stringify(err)}`)
|
console.error(
|
||||||
|
`[ERROR]\tWEBHOOKS/Conference End/Firebase Error\tID:${
|
||||||
|
req.body.conference.confId
|
||||||
|
}\tParty:${
|
||||||
|
req.body.conference.confAlias
|
||||||
|
}\tError:${JSON.stringify(err)}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
res.status(200).send({ message: 'Processed conference end'});
|
} else {
|
||||||
|
console.info(
|
||||||
|
`[DONE]\tWEBHOOKS/Conference End/Conference Was Already Replaced\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res.status(200).send({ message: "Processed conference end" });
|
||||||
|
} else {
|
||||||
|
console.info(
|
||||||
|
`[DONE]\tWEBHOOKS/Conference End/Not Eligible For Autodelete\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
|
res.status(200).send({ message: "Processed conference end" });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.info(`[DONE]\tWEBHOOKS/Conference End/End Of Duplicate Conference\nID:${req.body.conference.confId}\nParty:${req.body.conference.confAlias}`);
|
console.info(
|
||||||
|
`[DONE]\tWEBHOOKS/Conference End/End Of Duplicate Conference\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(`[ERROR]\tWEBHOOKS/Conference End/Wrong Event Type\nID:${req.body.conference.confId}\nParty:${req.body.conference.confAlias}`)
|
console.error(
|
||||||
res.status(400).send({ message: 'Wrong event type' });
|
`[ERROR]\tWEBHOOKS/Conference End/Wrong Event Type\tID:${req.body.conference.confId}\tParty:${req.body.conference.confAlias}`
|
||||||
|
);
|
||||||
|
res.status(400).send({ message: "Wrong event type" });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user