diff --git a/app/package.json b/app/package.json index 03da443..ace52c9 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "watch-party-crx", - "version": "1.5.0", + "version": "1.5.1", "private": true, "dependencies": { "@giphy/js-fetch-api": "^1.5.8", diff --git a/app/public/manifest.json b/app/public/manifest.json index 372bcb7..aaf7b53 100644 --- a/app/public/manifest.json +++ b/app/public/manifest.json @@ -1,7 +1,7 @@ { "name": "Watch Party", "short_name": "WP", - "version": "1.5.0", + "version": "1.5.1", "description": "Watch streamed content together.", "background": { "page": "background.html" diff --git a/app/src/App.js b/app/src/App.js index 08b4dc0..3f9780a 100644 --- a/app/src/App.js +++ b/app/src/App.js @@ -26,7 +26,7 @@ import 'firebase/firestore'; import Inactive from './Inactive'; import { getUserUid, getPlayerSource, PLAYER_SOURCE } from './Api'; -const APP_VERSION = '1.5.0'; +const APP_VERSION = '1.5.1'; const APP_VERSION_STRING = APP_VERSION.replace(/\./g, ''); const darkTheme = createMuiTheme({ diff --git a/app/src/Chat.js b/app/src/Chat.js index 87a1312..4883eca 100644 --- a/app/src/Chat.js +++ b/app/src/Chat.js @@ -426,7 +426,7 @@ export default class Chat extends Component { color={ usersOnCall[id].info.externalId === LocalData().userUid ? 'secondary' - : null + : 'default' } className="party-controls-users-chip" clickable diff --git a/app/src/Create.js b/app/src/Create.js index 8130685..9d48df0 100644 --- a/app/src/Create.js +++ b/app/src/Create.js @@ -25,6 +25,7 @@ import { getPlayerSource, LocalData, updateLocalData, + getUserUid, } from './Api'; import { goTo } from 'route-lite'; import Chat from './Chat'; @@ -66,6 +67,7 @@ export default class Create extends Component { } createOrJoin() { this.props.updateLoading(true); + getUserUid(); const { userName, name, pin, mode } = this.state; if (!userName.replace(/\s+/g, '')) { this.props.notify('Missing user name'); diff --git a/app/src/Thread.js b/app/src/Thread.js index b5b9714..948c17d 100644 --- a/app/src/Thread.js +++ b/app/src/Thread.js @@ -19,11 +19,11 @@ HBO Now and HBO Max logos are trademark and intellectual property of WarnerMedia import React from 'react'; import { Typography } from '@material-ui/core'; import './Thread.css'; -import { LocalData } from './Api'; +import { LocalData, getUserUid } from './Api'; const Thread = (props) => props.messages.map((m, midx) => { - const { userUid } = LocalData(); + var { userUid } = LocalData(); if (m.uid === '') { // SYSTEM MESSAGES return ( diff --git a/functions/app.js b/functions/app.js index 05fd299..24e44ca 100644 --- a/functions/app.js +++ b/functions/app.js @@ -1,9 +1,9 @@ const FunctionModules = require('./modules/index'); +const FunctionModules2 = require('./modules2/index'); const express = require('express'); const cors = require('cors'); // VERSION 1 -// VERSION 2 const app = express(); app.use(cors({ origin: true })); app.use(FunctionModules.authenticator); @@ -17,6 +17,21 @@ app.post('/updateVoxeet', FunctionModules.updateVoxeet); app.delete('/leave/:rid/users/:uid', FunctionModules.leaveRoom); app.delete('/delete/:rid', FunctionModules.deleteRoom); +// VERSION 2 +const app2 = express(); +app2.use(cors({ origin: true })); +app2.use(FunctionModules2.authenticator); +app2.get('/validator', FunctionModules2.tokenValidator); +app2.get('/refresher/:token', FunctionModules2.tokenRefresher); +app2.post('/create', FunctionModules2.createRoom); +app2.post('/join', FunctionModules2.joinRoom); +app2.post('/message', FunctionModules2.sendMessage); +app2.post('/updatePlayer', FunctionModules2.updatePlayer); +app2.post('/updateVoxeet', FunctionModules2.updateVoxeet); +app2.delete('/leave/:rid/users/:uid', FunctionModules2.leaveRoom); +app2.delete('/delete/:rid', FunctionModules2.deleteRoom); + module.exports = { v1: app, + v2: app2, }; diff --git a/functions/index.js b/functions/index.js index 7331905..e1aad21 100644 --- a/functions/index.js +++ b/functions/index.js @@ -14,7 +14,7 @@ admin.initializeApp(FIREBASE_OPTIONS); // VERSION 1 exports.widgets = functions.https.onRequest(REST.v1); // VERSION 2 -exports.widgets2 = functions.https.onRequest(REST.v1); +exports.widgets2 = functions.https.onRequest(REST.v2); exports.scheduledCleanUp = functions.pubsub .schedule('every 60 minutes') diff --git a/functions/modules2/authenticator.js b/functions/modules2/authenticator.js new file mode 100644 index 0000000..878697c --- /dev/null +++ b/functions/modules2/authenticator.js @@ -0,0 +1,42 @@ +const admin = require('firebase-admin'); + +module.exports = (req, res, next) => { + res.set('Access-Control-Allow-Origin', ['*']); + if (req.method === 'OPTIONS') { + res.status(200).send(); + return next(); + } + if (req.headers.authorization) { + try { + const token = req.headers.authorization.split(' ')[1]; + const reqToken = token.split(':')[0]; + const reqUid = token.split(':')[1]; + admin + .auth() + .verifyIdToken(reqToken) + .then((user) => { + if (user.uid === reqUid) { + console.info('Verified Token - UID - ', reqUid); + if (req.method === 'POST') { + const bodydata = JSON.parse(req.body); + bodydata.uid = user.uid; + req.body = JSON.stringify(bodydata); + } + if (req.method === 'GET' || req.method === 'DELETE') { + req.body = JSON.stringify({ uid: user.uid }); + } + return next(); + } else { + return res.status(401).send({ message: 'Unauthorized' }); + } + }) + .catch((err) => { + console.error('Failed Auth - ', req.headers.authorization, '\n', err); + return res.status(500).send({ message: 'Unable to verify user token' }); + }); + } catch (err) { + console.log(err); + return res.status(401).send({ message: 'Something went wrong when authorizing' }); + } + } else return res.status(401).send({ message: 'Got no user token' }); +}; diff --git a/functions/modules2/cleanUpRoom.js b/functions/modules2/cleanUpRoom.js new file mode 100644 index 0000000..c268db2 --- /dev/null +++ b/functions/modules2/cleanUpRoom.js @@ -0,0 +1,32 @@ +const admin = require('firebase-admin'); + +module.exports = async (roomId) => { + admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .listDocuments() + .then((messages) => messages.forEach((message) => message.delete())) + .catch((err) => { + console.error(`Failed to run auto clean up (delete room messages) @ ${roomId}`, err); + }); + admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('users') + .listDocuments() + .then((users) => users.forEach((user) => user.delete())) + .catch((err) => { + console.error(`Failed to run auto clean up (delete room users) @ ${roomId}`, err); + }); + admin + .firestore() + .collection('rooms') + .doc(roomId) + .delete() + .catch((err) => { + console.error(`Failed to run auto clean up (delete room) @ ${roomId}`, err); + }); +}; diff --git a/functions/modules2/createRoom.js b/functions/modules2/createRoom.js new file mode 100644 index 0000000..3919f2e --- /dev/null +++ b/functions/modules2/createRoom.js @@ -0,0 +1,66 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const bodydata = JSON.parse(req.body); + console.log('Requested Create - UID - ', bodydata.uid); + if (!bodydata.userName) res.status(400).send({ message: 'Missing user name' }); + if (!bodydata.partyName) res.status(400).send({ message: 'Missing party name' }); + if (!bodydata.partyPin) res.status(400).send({ message: 'Missing party pin' }); + const roomNameTaken = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName.replace('/', '\\')) + .get() + .then((docSnap) => docSnap.exists); + if (roomNameTaken) return res.status(409).send({ message: 'That party name is already taken' }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .set({ + name: bodydata.partyName, + pin: bodydata.partyPin, + player: bodydata.player, + createdAt: new Date(), + updatedAt: new Date(), + adminUid: bodydata.uid, + }) + .catch((err) => { + res.status(500).send({ message: 'Unable to start party.' }); + console.error(err); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${bodydata.userName} started the party.`, + time: new Date(), + }) + .catch((err) => { + console.error( + `Failed to add system create party message : \n\t Room: ${bodydata.partyName}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .set({ + admin: true, + name: bodydata.userName, + }) + .catch((err) => { + console.error( + `Failed to set admin when creating party : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' }); +}; diff --git a/functions/modules2/deleteRoom.js b/functions/modules2/deleteRoom.js new file mode 100644 index 0000000..e0b37fb --- /dev/null +++ b/functions/modules2/deleteRoom.js @@ -0,0 +1,62 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + console.log('Requested Delete - Room - ', req.params.rid); + console.log(req.body); + const isAdmin = await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .doc(JSON.parse(req.body).uid) + .get() + .then((v) => { + if (v.exists) { + return v.data().admin; + } + return false; + }); + if (!isAdmin) { + console.log('[UNAUTHORIZED] Requested Delete - Room - ', req.params.rid); + res.status(401).send({ message: 'Not authorized to end this party.' }); + return; + } + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('messages') + .listDocuments() + .then((messages) => messages.forEach((message) => message.delete())) + .catch((err) => { + console.error( + `Failed to delete room messages : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .listDocuments() + .then((users) => users.forEach((user) => user.delete())) + .catch((err) => { + console.error( + `Failed to delete room users : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .delete() + .catch((err) => { + console.error( + `Failed to delete room : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ); + }); + res.status(200).send({ message: 'Ended the party' }); +}; diff --git a/functions/modules2/index.js b/functions/modules2/index.js new file mode 100644 index 0000000..19d7b75 --- /dev/null +++ b/functions/modules2/index.js @@ -0,0 +1,29 @@ +const authenticator = require('./authenticator'); +const cleanUpRoom = require('./cleanUpRoom'); +const scheduledCleanUp = require('./scheduledCleanUp'); +const createRoom = require('./createRoom'); +const joinRoom = require('./joinRoom'); +const sendMessage = require('./sendMessage'); +const leaveRoom = require('./leaveRoom'); +const deleteRoom = require('./deleteRoom'); +const timeDiff = require('./timeDiff'); +const updatePlayer = require('./updatePlayer'); +const tokenValidator = require('./tokenValidator'); +const tokenRefresher = require('./tokenRefresher'); +const updateVoxeet = require('./updateVoxeet'); + +module.exports = { + authenticator, + createRoom, + joinRoom, + sendMessage, + updatePlayer, + leaveRoom, + deleteRoom, + scheduledCleanUp, + cleanUpRoom, + timeDiff, + tokenValidator, + tokenRefresher, + updateVoxeet, +}; diff --git a/functions/modules2/joinRoom.js b/functions/modules2/joinRoom.js new file mode 100644 index 0000000..03732f2 --- /dev/null +++ b/functions/modules2/joinRoom.js @@ -0,0 +1,155 @@ +const admin = require('firebase-admin'); +const { firestore } = require('firebase-admin'); + +module.exports = async (req, res) => { + const bodydata = JSON.parse(req.body); + console.log('Requested Join - UID - ', bodydata.uid, '\n\tRoom - ', bodydata.partyName); + // GET ROOM EXISTS, ROOM SOURCE, & ROOM PIN + const [exists, roomSource, roomPin, adminUid] = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .get() + .then((roomSnap) => [ + roomSnap.exists, + roomSnap.exists ? roomSnap.data().player.source : '', + roomSnap.exists ? roomSnap.data().pin : '', + roomSnap.exists ? roomSnap.data().adminUid : '', + ]) + .catch((err) => { + console.error( + `Failed to get room when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + if (exists && roomPin !== bodydata.partyPin) + return res.status(401).send({ message: 'Incorrect party pin' }); + if (adminUid === bodydata.uid) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .set({ + admin: true, + name: bodydata.userName, + }); + } + // GET IF USER EXISTS AND IS ADMIN + const [userExists, userAdmin, userName] = await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .get() + .then((userSnap) => [ + userSnap.exists, + userSnap.exists ? userSnap.data().admin : false, + userSnap.exists ? userSnap.data().name : '', + ]) + .catch((err) => { + console.error( + `Failed to get user when joining room : \n\t Room: ${bodydata.partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + // IF USER PRE-EXISTS AND SAME SOURCE - JOIN + if (userExists && exists && roomSource === bodydata.source) { + // UPDATE NAME IF NEEDED + if (userName !== bodydata.userName) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .update({ name: bodydata.userName }); + } + res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); + } + // USER DOES NOT PRE-EXIST BUT SAME SOURCE AND RIGHT PIN + else if ( + !userExists && + exists && + bodydata.partyName && + bodydata.userName && + roomSource === bodydata.source && + roomPin === bodydata.partyPin + ) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${bodydata.userName} joined the party.`, + time: new Date(), + }) + .catch((err) => { + console.error( + `Failed to add system join party message : \n\t Room: ${partyName} \n\t ${bodydata.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .collection('users') + .doc(bodydata.uid) + .set({ + admin: false, + name: bodydata.userName, + }) + .catch((err) => { + console.error( + `Failed to set admin when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .update({ + updatedAt: new Date(), + }) + .catch((err) => { + console.error( + `Failed to set updated time when joining party : \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`, + err + ); + }); + res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' }); + } + // ONLY WRONG SOURCE + else if (exists && roomSource !== bodydata.source) { + // MOVE SOURCE IF ADMIN + if (userAdmin === true) { + await admin + .firestore() + .collection('rooms') + .doc(bodydata.partyName) + .update({ + player: { + showName: null, + source: null, + status: 'NOT_PLAYING', + time: 0, + updatedBy: bodydata.uid, + }, + }) + .catch(() => { + console.error( + `Failed to update player source when admin joining party \n\t Room: ${partyName} \n\t User: ${bodydata.uid}` + ); + res.status(500).send({ message: 'Unable to move party, please try again' }); + }); + res.status(200).send({ message: `Moved party to ${roomSource}` }); + } else res.status(417).send({ message: `This party is on ${roomSource}` }); + } else res.status(404).send({ message: 'Party Not Found' }); +}; diff --git a/functions/modules2/leaveRoom.js b/functions/modules2/leaveRoom.js new file mode 100644 index 0000000..fe0ba5b --- /dev/null +++ b/functions/modules2/leaveRoom.js @@ -0,0 +1,19 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + console.log('Requested Leave - UID - ', req.params.uid, '\n\tRoom - ', req.params.rid); + await admin + .firestore() + .collection('rooms') + .doc(req.params.rid) + .collection('users') + .doc(req.params.uid) + .delete() + .catch((err) => + console.error( + `Failed to remove user from party : \n\t Room: ${req.params.rid} \n\t User: ${req.params.uid}`, + err + ) + ); + res.status(200).send({ message: 'Left the party' }); +}; diff --git a/functions/modules2/scheduledCleanUp.js b/functions/modules2/scheduledCleanUp.js new file mode 100644 index 0000000..2fc91a5 --- /dev/null +++ b/functions/modules2/scheduledCleanUp.js @@ -0,0 +1,48 @@ +const admin = require('firebase-admin'); +const cleanUpRoom = require('./cleanUpRoom'); + +const timeDiff = (ds1, ds2) => { + const d1 = new Date(ds1); + const d2 = new Date(ds2); + var diff = (d2.getTime() - d1.getTime()) / 1000; + diff /= 60 * 60; + return Math.abs(Math.round(diff)); +}; + +module.exports = async () => { + const startedTime = new Date(); + const roomList = await admin + .firestore() + .collection('rooms') + .listDocuments() + .then((rL) => rL) + .catch((err) => { + console.error( + `Failed to run auto clean up (get room list) @ ${new Date().toLocaleTimeString()}`, + err + ); + }); + roomList.forEach((roomRef) => { + roomRef + .get() + .then(async (roomSnap) => { + if ( + // MORE THAN 24 HOURS AND NOT IN USE + (timeDiff(roomSnap.createTime.toDate(), startedTime) >= 24 && + timeDiff(roomSnap.updateTime.toDate(), startedTime) >= 12) || + // LESS THAN 24 HOURS BUT NOT IN USE + timeDiff(roomSnap.updateTime.toDate(), startedTime) >= 12 + ) { + await cleanUpRoom(roomSnap.id); + console.info(`Deleted room ${roomSnap.id} from auto cleanup`); + } + return; + }) + .catch((err) => { + console.error( + `Failed to run auto clean up (get room snap) @ ${new Date().toLocaleTimeString()}`, + err + ); + }); + }); +}; diff --git a/functions/modules2/sendMessage.js b/functions/modules2/sendMessage.js new file mode 100644 index 0000000..d9b4581 --- /dev/null +++ b/functions/modules2/sendMessage.js @@ -0,0 +1,46 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const { name, text, uid, roomId, type } = JSON.parse(req.body); + + const roomExists = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .get() + .then((roomSnap) => roomSnap.exists); + if (roomExists) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .add({ + name, + text: text || '', + time: new Date(), + uid, + type: type || '', + }) + .catch((err) => { + console.error(`Failed to send message to party : \n\t Room: ${roomId} \n\t ${uid}`, err); + res.status(500).send({ message: "Couldn't send your message", error: messageErr }); + }); + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .update({ + updatedAt: new Date(), + }) + .catch((err) => { + console.error( + `Failed to set updated time when sending messasge to party : \n\t Room: ${roomId} \n\t User: ${uid}`, + err + ); + }); + res.status(200).send({ message: 'Sent a message' }); + } else { + res.status(404).send({ message: 'Looks like this party is over' }); + } +}; diff --git a/functions/modules2/timeDiff.js b/functions/modules2/timeDiff.js new file mode 100644 index 0000000..7c16ead --- /dev/null +++ b/functions/modules2/timeDiff.js @@ -0,0 +1,7 @@ +module.exports = function (ds1, ds2) { + const d1 = new Date(ds1); + const d2 = new Date(ds2); + var diff = (d2.getTime() - d1.getTime()) / 1000; + diff /= 60 * 60; + return Math.abs(Math.round(diff)); +}; diff --git a/functions/modules2/tokenRefresher.js b/functions/modules2/tokenRefresher.js new file mode 100644 index 0000000..8981197 --- /dev/null +++ b/functions/modules2/tokenRefresher.js @@ -0,0 +1,20 @@ +const VoxeetSecret = require('../VoxeetSecret.json'); +module.exports = async (req, res) => { + const { key, secret } = VoxeetSecret; + const credentials = btoa(encodeURI(key) + ':' + encodeURI(secret)); + const headers = { + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache', + Authorization: 'Basic ' + credentials, + }; + const oauth = await fetch(VoxeetSecret.refreshURL, { + method: 'POST', + headers, + body: JSON.stringify({ + refresh_token: req.params.token, + }), + }) + .then((oauthResponse) => oauthResponse.json()) + .catch((err) => res.status(500).send(err)); + if (oauth) res.status(200).send(oauth); +}; diff --git a/functions/modules2/tokenValidator.js b/functions/modules2/tokenValidator.js new file mode 100644 index 0000000..dc28d91 --- /dev/null +++ b/functions/modules2/tokenValidator.js @@ -0,0 +1,21 @@ +const VoxeetSecret = require('../VoxeetSecret.json'); +const fetch = require('node-fetch'); +module.exports = async (req, res) => { + const { key, secret } = VoxeetSecret; + const credentials = Buffer.from(encodeURI(key) + ':' + encodeURI(secret)).toString('base64'); + const headers = { + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache', + Authorization: 'Basic ' + credentials, + }; + const oauth = await fetch(VoxeetSecret.validateURL, { + method: 'POST', + headers, + body: JSON.stringify({ + grant_type: 'client_credentials', + }), + }) + .then((oauthResponse) => oauthResponse.json()) + .catch((err) => res.status(500).send(err)); + if (oauth) res.status(200).send(oauth); +}; diff --git a/functions/modules2/updatePlayer.js b/functions/modules2/updatePlayer.js new file mode 100644 index 0000000..777a155 --- /dev/null +++ b/functions/modules2/updatePlayer.js @@ -0,0 +1,82 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const { player, roomId, uid, showChanged, userName } = JSON.parse(req.body); + // const statusString = + // player.status === 'PLAYING' + // ? 'started playing from' + // : player.status === 'PAUSED' + // ? 'paused at' + // : player.status === 'NOT_PLAYING' + // ? 'stopped at' + // : 'is at'; + // const timeString = + // player.time > 3600 + // ? new Date(player.time * 1000).toISOString().substr(11, 8) + // : new Date(player.time * 1000).toISOString().substr(14, 5); + const [roomExists, roomData] = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .get() + .then((docSnap) => [docSnap.exists, docSnap.data()]); + if (!roomExists) return res.status(404).send({ message: 'Party not found.' }); + const userExists = await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('users') + .doc(uid) + .get() + .then((userSnap) => userSnap.exists); + if (userExists) { + if (showChanged === true) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${userName} changed \n${player.showName ? 'to ' + player.showName : ''}`, + time: new Date(), + }); + } + if (roomData.status !== player.status) { + await admin + .firestore() + .collection('rooms') + .doc(roomId) + .update({ + player, + }) + .catch((err) => { + console.error(`Failed to update player : \n\t Room: ${roomId} \n\t ${uid}`, err); + res.status(500).send({ message: "Uh oh party could't be synced", err }); + }); + // await admin + // .firestore() + // .collection('rooms') + // .doc(roomId) + // .collection('messages') + // .add({ + // uid: '', + // name: '', + // text: `${userName} ${statusString} ${timeString}`, + // time: new Date(), + // }) + // .catch((err) => { + // console.error( + // `Failed to add system update player message : \n\t Room: ${roomId} \n\t ${uid}`, + // err + // ); + // }); + return res.status(200).send({ message: 'Synced party player' }); + } else { + return res.status(208).send({ message: 'Player already up to date' }); + } + } else { + return res.status(401).send({ message: 'Not in room to sync' }); + } +}; diff --git a/functions/modules2/updateVoxeet.js b/functions/modules2/updateVoxeet.js new file mode 100644 index 0000000..73ae0c0 --- /dev/null +++ b/functions/modules2/updateVoxeet.js @@ -0,0 +1,47 @@ +const admin = require('firebase-admin'); + +module.exports = async (req, res) => { + const { conference, partyName, partyPin, userName } = JSON.parse(req.body); + // GET ROOM PIN + const roomPin = await admin + .firestore() + .collection('rooms') + .doc(partyName) + .get() + .then((roomSnap) => (roomSnap.exists ? roomSnap.data().pin : null)); + // CHECK IF ROOM EXISTS + if (roomPin) { + // CHECK FOR CORRECT PIN + if (roomPin === partyPin) { + // UPDATE CONFERENCE DETAILS + await admin + .firestore() + .collection('rooms') + .doc(partyName) + .update({ conference }) + .catch((err) => + res.status(500).send({ message: 'Unable to update the call details', error: err }) + ); + // ADD SYSTEM MESSAGE + await admin + .firestore() + .collection('rooms') + .doc(partyName) + .collection('messages') + .add({ + uid: '', + name: '', + text: `${userName} started the call.`, + time: new Date(), + }) + .catch((err) => console.error('Failed to add update conference message', err)); + res.status(200).send({ message: 'Started the conference' }); + } else { + // WRONG ROOM PIN + return res.status(401).send({ message: 'Wrong party pin, try rejoining' }); + } + } else { + // ROOM DOESN'T EXIST + return res.status(404).send({ message: 'Party Not Found' }); + } +}; diff --git a/functions/package.json b/functions/package.json index ff23bb8..849e966 100644 --- a/functions/package.json +++ b/functions/package.json @@ -1,6 +1,6 @@ { "name": "watch-party-api", - "version": "1.5.0", + "version": "1.5.1", "description": "Cloud Functions for Watch Party", "scripts": { "lint": "eslint .", diff --git a/package.json b/package.json index 97231d5..577ad2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "watch-party", - "version": "1.5.0", + "version": "1.5.1", "description": "Watch Party", "scripts": { "start": "firebase emulators:start",