v1.6.2/cleanup

- remove api v2
- linting
This commit is contained in:
2020-08-14 10:57:38 -04:00
parent aaf2506f78
commit 56cd151a04
32 changed files with 476 additions and 1437 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "watch-party-crx", "name": "watch-party-crx",
"version": "1.6.1", "version": "1.6.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
+42 -44
View File
@@ -12,18 +12,18 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
/* global chrome */ /* global chrome */
/* global firebase */ /* global firebase */
const APP_VERSION = "1.6.2"; const APP_VERSION = '1.6.2';
const APP_VERSION_STRING = APP_VERSION.replace(/\./g, ""); const APP_VERSION_STRING = APP_VERSION.replace(/\./g, '');
const firebaseConfig = { const firebaseConfig = {
apiKey: "AIzaSyCJLuYpzXLDRmu2ttzFuSGmYcpFxqToWFU", apiKey: 'AIzaSyCJLuYpzXLDRmu2ttzFuSGmYcpFxqToWFU',
authDomain: "watch-party-crx.firebaseapp.com", authDomain: 'watch-party-crx.firebaseapp.com',
databaseURL: "https://watch-party-crx.firebaseio.com", databaseURL: 'https://watch-party-crx.firebaseio.com',
projectId: "watch-party-crx", projectId: 'watch-party-crx',
storageBucket: "watch-party-crx.appspot.com", storageBucket: 'watch-party-crx.appspot.com',
messagingSenderId: "712242707190", messagingSenderId: '712242707190',
appId: "1:712242707190:web:65fa7f772e30da364b0ad7", appId: '1:712242707190:web:65fa7f772e30da364b0ad7',
measurementId: "G-EZS4PEVG4T", measurementId: 'G-EZS4PEVG4T',
}; };
firebase.initializeApp(firebaseConfig); firebase.initializeApp(firebaseConfig);
@@ -44,7 +44,7 @@ const fetcher = async (request, sendResponse) => {
method, method,
headers: { headers: {
Authorization: `Token ${idToken}:${firebase.auth().currentUser.uid}`, Authorization: `Token ${idToken}:${firebase.auth().currentUser.uid}`,
"Access-Control-Allow-Origin": "*", 'Access-Control-Allow-Origin': '*',
}, },
...request, ...request,
}) })
@@ -72,37 +72,37 @@ const sendAuth = async (sendResponse) => {
chrome.runtime.onInstalled.addListener((details) => { chrome.runtime.onInstalled.addListener((details) => {
if (details.reason) { if (details.reason) {
if (details.reason === "install") { if (details.reason === 'install') {
if (window.localStorage.getItem("watchPartyVersion")) { if (window.localStorage.getItem('watchPartyVersion')) {
if (window.localStorage.getItem("watchPartyVersion") !== APP_VERSION) { if (window.localStorage.getItem('watchPartyVersion') !== APP_VERSION) {
chrome.tabs.create({ chrome.tabs.create({
url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`, url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`,
active: true, active: true,
}); });
window.localStorage.setItem("watchPartyVersion", APP_VERSION); window.localStorage.setItem('watchPartyVersion', APP_VERSION);
} }
} else { } else {
chrome.tabs.create({ chrome.tabs.create({
url: "https://www.chromewatchparty.com/welcome", url: 'https://www.chromewatchparty.com/welcome',
active: true, active: true,
}); });
window.localStorage.setItem("watchPartyVersion", APP_VERSION); window.localStorage.setItem('watchPartyVersion', APP_VERSION);
} }
} else if (details.reason === "update") { } else if (details.reason === 'update') {
if (window.localStorage.getItem("watchPartyVersion")) { if (window.localStorage.getItem('watchPartyVersion')) {
if (window.localStorage.getItem("watchPartyVersion") !== APP_VERSION) { if (window.localStorage.getItem('watchPartyVersion') !== APP_VERSION) {
chrome.tabs.create({ chrome.tabs.create({
url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`, url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`,
active: true, active: true,
}); });
window.localStorage.setItem("watchPartyVersion", APP_VERSION); window.localStorage.setItem('watchPartyVersion', APP_VERSION);
} }
} else { } else {
chrome.tabs.create({ chrome.tabs.create({
url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`, url: `http://www.chromewatchparty.com/changes/v${APP_VERSION}`,
active: true, active: true,
}); });
window.localStorage.setItem("watchPartyVersion", APP_VERSION); window.localStorage.setItem('watchPartyVersion', APP_VERSION);
} }
} }
} }
@@ -111,24 +111,24 @@ chrome.runtime.onInstalled.addListener((details) => {
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const { type } = request; const { type } = request;
switch (type) { switch (type) {
case "API_CALL": case 'API_CALL':
fetcher(request, sendResponse); fetcher(request, sendResponse);
break; break;
case "GET_AUTH": case 'GET_AUTH':
sendAuth(sendResponse); sendAuth(sendResponse);
break; break;
case "GET_PARTIES": case 'GET_PARTIES':
sendResponse( sendResponse(
window.localStorage.getItem("parties") window.localStorage.getItem('parties')
? JSON.parse(window.localStorage.getItem("parties")) ? JSON.parse(window.localStorage.getItem('parties'))
: [] : []
); );
break; break;
case "EMPTY_PARTIES": case 'EMPTY_PARTIES':
window.localStorage.removeItem("parties"); window.localStorage.removeItem('parties');
break; break;
default: default:
console.warn("Unknown message type: <", type, ">"); console.warn('Unknown message type: <', type, '>');
break; break;
} }
return true; return true;
@@ -142,10 +142,10 @@ chrome.runtime.onConnect.addListener((port) => {
}); });
port.onMessage.addListener((request) => { port.onMessage.addListener((request) => {
const { type, roomId, roomPin } = request; const { type, roomId, roomPin } = request;
if (type === "INIT") { if (type === 'INIT') {
port.roomListener = firebase port.roomListener = firebase
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(roomId) .doc(roomId)
.onSnapshot( .onSnapshot(
(snap) => { (snap) => {
@@ -159,16 +159,14 @@ chrome.runtime.onConnect.addListener((port) => {
); );
port.userListener = firebase port.userListener = firebase
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(roomId) .doc(roomId)
.collection("users") .collection('users')
.onSnapshot( .onSnapshot(
(snap) => { (snap) => {
if (snap) { if (snap) {
const isAdmin = snap.docs const isAdmin = snap.docs
.filter( .filter((user) => user.id === firebase.auth().currentUser.uid)[0]
(user) => user.id === firebase.auth().currentUser.uid
)[0]
.data().admin; .data().admin;
const users = snap.docs.map((userSnap) => userSnap.data().name); const users = snap.docs.map((userSnap) => userSnap.data().name);
port.postMessage({ admin: isAdmin, users }); port.postMessage({ admin: isAdmin, users });
@@ -180,10 +178,10 @@ chrome.runtime.onConnect.addListener((port) => {
); );
port.messageListener = firebase port.messageListener = firebase
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(roomId) .doc(roomId)
.collection("messages") .collection('messages')
.orderBy("time") .orderBy('time')
.onSnapshot( .onSnapshot(
(snap) => { (snap) => {
if (snap) { if (snap) {
@@ -197,18 +195,18 @@ chrome.runtime.onConnect.addListener((port) => {
port.postMessage({ isError: true, ...err }); port.postMessage({ isError: true, ...err });
} }
); );
if (window.localStorage.getItem("parties")) { if (window.localStorage.getItem('parties')) {
var existing = JSON.parse(window.localStorage.getItem("parties")); var existing = JSON.parse(window.localStorage.getItem('parties'));
if (!(existing.filter((i) => i.name === roomId).length > 0)) { if (!(existing.filter((i) => i.name === roomId).length > 0)) {
existing.push({ existing.push({
name: roomId, name: roomId,
pin: roomPin, pin: roomPin,
}); });
window.localStorage.setItem("parties", JSON.stringify(existing)); window.localStorage.setItem('parties', JSON.stringify(existing));
} }
} else { } else {
window.localStorage.setItem( window.localStorage.setItem(
"parties", 'parties',
JSON.stringify([ JSON.stringify([
{ {
name: roomId, name: roomId,
+38 -59
View File
@@ -9,33 +9,27 @@ 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 React, { useState, useEffect } from "react"; import React, { useState, useEffect } from 'react';
import Router from "route-lite"; import Router from 'route-lite';
import { import { Fab, createMuiTheme, ThemeProvider, Snackbar, Tooltip } from '@material-ui/core';
Fab, import Create from './Create';
createMuiTheme, import Loading from './Loading';
ThemeProvider, import firebase from 'firebase/app';
Snackbar, import 'firebase/firestore';
Tooltip, import Inactive from './Inactive';
} from "@material-ui/core"; import { getUserUid, getPlayerSource, PLAYER_SOURCE } from './Api';
import Create from "./Create";
import Loading from "./Loading";
import firebase from "firebase/app";
import "firebase/firestore";
import Inactive from "./Inactive";
import { getUserUid, getPlayerSource, PLAYER_SOURCE } from "./Api";
const APP_VERSION = "1.6.2"; const APP_VERSION = '1.6.2';
const APP_VERSION_STRING = APP_VERSION.replace(/\./g, ""); const APP_VERSION_STRING = APP_VERSION.replace(/\./g, '');
const darkTheme = createMuiTheme({ const darkTheme = createMuiTheme({
palette: { palette: {
type: "dark", type: 'dark',
primary: { primary: {
main: "#FF0000", main: '#FF0000',
}, },
secondary: { secondary: {
main: "#c0f300", main: '#c0f300',
}, },
}, },
}); });
@@ -48,41 +42,32 @@ const Routes = (props) => (
const resetResize = () => { const resetResize = () => {
const checkedX = 400; const checkedX = 400;
document.documentElement.style.setProperty("--party-width", `${checkedX}px`); document.documentElement.style.setProperty('--party-width', `${checkedX}px`);
document.documentElement.style.setProperty( document.documentElement.style.setProperty('--neg-party-width', `-${checkedX}px`);
"--neg-party-width",
`-${checkedX}px`
);
}; };
const doResize = (ev) => { const doResize = (ev) => {
const checkedX = const checkedX =
window.innerWidth - window.innerWidth -
Math.min( Math.min(window.innerWidth - 300, Math.max(window.innerWidth * 0.5, ev.clientX));
window.innerWidth - 300, document.documentElement.style.setProperty('--party-width', `${checkedX}px`);
Math.max(window.innerWidth * 0.5, ev.clientX) document.documentElement.style.setProperty('--neg-party-width', `-${checkedX}px`);
);
document.documentElement.style.setProperty("--party-width", `${checkedX}px`);
document.documentElement.style.setProperty(
"--neg-party-width",
`-${checkedX}px`
);
}; };
const stopResize = (ev) => { const stopResize = (ev) => {
document.documentElement.removeEventListener("mousemove", doResize, false); document.documentElement.removeEventListener('mousemove', doResize, false);
document.documentElement.removeEventListener("mouseup", stopResize, false); document.documentElement.removeEventListener('mouseup', stopResize, false);
}; };
const startResize = (ev) => { const startResize = (ev) => {
document.documentElement.addEventListener("mousemove", doResize, false); document.documentElement.addEventListener('mousemove', doResize, false);
document.documentElement.addEventListener("mouseup", stopResize, false); document.documentElement.addEventListener('mouseup', stopResize, false);
}; };
const App = () => { const App = () => {
const closedNotification = { open: false, message: "" }; const closedNotification = { open: false, message: '' };
const [status, setStatus] = useState({ active: false, message: "" }); const [status, setStatus] = useState({ active: false, message: '' });
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [notification, setNotification] = useState(closedNotification); const [notification, setNotification] = useState(closedNotification);
@@ -94,8 +79,8 @@ const App = () => {
getUserUid(); getUserUid();
firebase firebase
.firestore() .firestore()
.collection("server") .collection('server')
.doc("status") .doc('status')
.onSnapshot((statusSnap) => { .onSnapshot((statusSnap) => {
setStatus(statusSnap.data()); setStatus(statusSnap.data());
setLoading(false); setLoading(false);
@@ -103,19 +88,18 @@ const App = () => {
}, []); }, []);
// HANDLE VISIBILITY STYLING // HANDLE VISIBILITY STYLING
const PartyRoutesWrapper = document.getElementById("party-routes-wrapper"); const PartyRoutesWrapper = document.getElementById('party-routes-wrapper');
if (visible) { if (visible) {
document.body.classList.add("visible"); document.body.classList.add('visible');
PartyRoutesWrapper && PartyRoutesWrapper.classList.add("visible"); PartyRoutesWrapper && PartyRoutesWrapper.classList.add('visible');
if ( if (
!hasAttached && !hasAttached &&
(getPlayerSource() === PLAYER_SOURCE.HBOMAX || (getPlayerSource() === PLAYER_SOURCE.HBOMAX || getPlayerSource() === PLAYER_SOURCE.HBONOW)
getPlayerSource() === PLAYER_SOURCE.HBONOW)
) { ) {
document.addEventListener( document.addEventListener(
"mousedown", 'mousedown',
function (ev) { function (ev) {
if (document.body.querySelector("body.visible")) { if (document.body.querySelector('body.visible')) {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
ev.stopImmediatePropagation(); ev.stopImmediatePropagation();
@@ -126,8 +110,8 @@ const App = () => {
hasAttached = true; hasAttached = true;
} }
} else { } else {
document.body.classList.remove("visible"); document.body.classList.remove('visible');
PartyRoutesWrapper && PartyRoutesWrapper.classList.remove("visible"); PartyRoutesWrapper && PartyRoutesWrapper.classList.remove('visible');
} }
// HANDLE FULLSCREEN EVENT // HANDLE FULLSCREEN EVENT
@@ -139,7 +123,7 @@ const App = () => {
<ThemeProvider theme={darkTheme}> <ThemeProvider theme={darkTheme}>
<Snackbar <Snackbar
className="party-notification-container" className="party-notification-container"
anchorOrigin={{ vertical: "bottom", horizontal: "right" }} anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
open={notification.open} open={notification.open}
onClose={() => setNotification(closedNotification)} onClose={() => setNotification(closedNotification)}
message={notification.message} message={notification.message}
@@ -152,17 +136,12 @@ const App = () => {
title="Resize Sidebar / Double Click To Reset" title="Resize Sidebar / Double Click To Reset"
aria-label="Resize Sidebar / Double Click To Reset" aria-label="Resize Sidebar / Double Click To Reset"
> >
<div <div onDoubleClick={resetResize} onMouseDown={startResize} id="party-width-dragger">
onDoubleClick={resetResize}
onMouseDown={startResize}
id="party-width-dragger"
>
|| ||
</div> </div>
</Tooltip> </Tooltip>
{loading && <Loading />} {loading && <Loading />}
{status[APP_VERSION_STRING] && {status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? (
status[APP_VERSION_STRING].active === true ? (
<Routes <Routes
updateLoading={setLoading} updateLoading={setLoading}
notify={(message) => setNotification({ open: true, message })} notify={(message) => setNotification({ open: true, message })}
+21 -21
View File
@@ -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) {
@@ -36,7 +36,7 @@ export default class CallManager {
if (onCall === true) this.leaveCall(); if (onCall === true) this.leaveCall();
else this.boot(conference); else this.boot(conference);
} catch (e) { } catch (e) {
this.notify("Uh oh something went wrong, try rejoining the call."); this.notify('Uh oh something went wrong, try rejoining the call.');
} }
} }
toggleMute(muted) { toggleMute(muted) {
@@ -52,14 +52,14 @@ 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() {
@@ -89,7 +89,7 @@ export default class CallManager {
muted: false, muted: false,
callActionPending: false, callActionPending: false,
}); });
console.error("Update Voxeet API Error", err); console.error('Update Voxeet API Error', err);
return false; return false;
} }
}); });
@@ -101,11 +101,11 @@ export default class CallManager {
muted: false, muted: false,
callActionPending: false, callActionPending: false,
}); });
console.error("Failed to update party Voxeet"); 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();
} }
} }
@@ -119,8 +119,8 @@ export default class CallManager {
muted: false, muted: false,
callActionPending: false, callActionPending: false,
}); });
this.notify("Unable to join call. Try again in a moment."); this.notify('Unable to join call. Try again in a moment.');
console.error("Error joining call", e); console.error('Error joining call', e);
return true; return true;
}); });
// Leave changes as comment for later // Leave changes as comment for later
@@ -143,9 +143,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;
@@ -158,14 +158,14 @@ 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({ this.listener({
onCall: false, onCall: false,
callActionPending: false, callActionPending: false,
@@ -173,11 +173,11 @@ export default class CallManager {
}); });
}); });
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 });
}); });
@@ -195,11 +195,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);
@@ -215,7 +215,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);
}); });
}); });
+113 -190
View File
@@ -10,7 +10,7 @@ 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.
************************************************************************/ ************************************************************************/
/*global chrome */ /*global chrome */
import React, { Component } from "react"; import React, { Component } from 'react';
import { import {
Typography, Typography,
TextField, TextField,
@@ -31,8 +31,8 @@ import {
Paper, Paper,
Grid, Grid,
Slider, Slider,
} from "@material-ui/core"; } from '@material-ui/core';
import Thread from "./Thread"; import Thread from './Thread';
import { import {
SendMessageApi, SendMessageApi,
LeaveRoomApi, LeaveRoomApi,
@@ -46,7 +46,7 @@ import {
UpdateAdminOnly, UpdateAdminOnly,
scrollThread, scrollThread,
removeLocalData, removeLocalData,
} from "./Api"; } from './Api';
import { import {
Send, Send,
ExitToApp as Exit, ExitToApp as Exit,
@@ -68,21 +68,21 @@ import {
VolumeDown, VolumeDown,
VolumeUp, VolumeUp,
CancelRounded, CancelRounded,
} from "@material-ui/icons"; } from '@material-ui/icons';
import Create from "./Create"; import Create from './Create';
import { goTo } from "route-lite"; import { goTo } from 'route-lite';
import CallManager from "./CallManager"; import CallManager from './CallManager';
import VideoListener from "./VideoListener"; import VideoListener from './VideoListener';
import ReactGiphySearchbox from "react-giphy-searchbox"; import ReactGiphySearchbox from 'react-giphy-searchbox';
// const giphyFetch = new GiphyFetch('ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq'); // const giphyFetch = new GiphyFetch('ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq');
export default class Chat extends Component { export default class Chat extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
name: "", name: '',
messages: [], messages: [],
newMessage: "", newMessage: '',
admin: null, admin: null,
adminOnly: false, adminOnly: false,
adminModeUpdate: false, adminModeUpdate: false,
@@ -94,14 +94,10 @@ export default class Chat extends Component {
callActionPending: false, callActionPending: false,
menuPopover: true, menuPopover: true,
allowChatNotification: allowChatNotification:
LocalData().allowChatNotification !== undefined LocalData().allowChatNotification !== undefined ? LocalData().allowChatNotification : true,
? LocalData().allowChatNotification
: true,
isFullscreen: document.fullscreen, isFullscreen: document.fullscreen,
allowAutoRejoin: allowAutoRejoin:
LocalData().allowAutoRejoin !== undefined LocalData().allowAutoRejoin !== undefined ? LocalData().allowAutoRejoin : true,
? LocalData().allowAutoRejoin
: true,
replyTo: null, replyTo: null,
sendingMessages: [], sendingMessages: [],
volumes: {}, volumes: {},
@@ -127,21 +123,15 @@ export default class Chat extends Component {
props.nameSelectors props.nameSelectors
); );
this.updateAllowAutoRejoin = this.updateAllowAutoRejoin.bind(this); this.updateAllowAutoRejoin = this.updateAllowAutoRejoin.bind(this);
this.updateAllowChatNotification = this.updateAllowChatNotification.bind( this.updateAllowChatNotification = this.updateAllowChatNotification.bind(this);
this this.mCallManager = new CallManager(this.callEventListener, this.props.notify);
);
this.mCallManager = new CallManager(
this.callEventListener,
this.props.notify
);
} }
componentDidMount() { componentDidMount() {
// EVENT CAPTURE FOR ENTER TO SEND // EVENT CAPTURE FOR ENTER TO SEND
window.onkeypress = (ev) => { window.onkeypress = (ev) => {
if (ev.code === "Enter") { if (ev.code === 'Enter') {
if (ev.target === document.getElementById("chat-message-box-input")) { if (ev.target === document.getElementById('chat-message-box-input')) {
if (ev.shiftKey === false && this.state.gif === true) if (ev.shiftKey === false && this.state.gif === true) ev.preventDefault();
ev.preventDefault();
if (ev.shiftKey === false && this.state.gif === false) { if (ev.shiftKey === false && this.state.gif === false) {
ev.preventDefault(); ev.preventDefault();
this.sendMessageInvoker(); this.sendMessageInvoker();
@@ -151,15 +141,12 @@ export default class Chat extends Component {
}; };
// FULLSCREEN LISTENER // FULLSCREEN LISTENER
document.addEventListener("fullscreenchange", (ev) => { document.addEventListener('fullscreenchange', (ev) => {
this.setState({ isFullscreen: document.fullscreen }); this.setState({ isFullscreen: document.fullscreen });
}); });
// ACTIVE TRACKER // ACTIVE TRACKER
if ( if (LocalData().allowAutoRejoin === undefined || LocalData().allowAutoRejoin === null) {
LocalData().allowAutoRejoin === undefined ||
LocalData().allowAutoRejoin === null
) {
updateLocalData({ allowAutoRejoin: this.state.allowAutoRejoin }); updateLocalData({ allowAutoRejoin: this.state.allowAutoRejoin });
} }
if (this.state.allowAutoRejoin === true) { if (this.state.allowAutoRejoin === true) {
@@ -178,14 +165,14 @@ export default class Chat extends Component {
this.port = chrome.runtime.connect({ name: LocalData().partyName }); this.port = chrome.runtime.connect({ name: LocalData().partyName });
// Initialize listener // Initialize listener
this.port.postMessage({ this.port.postMessage({
type: "INIT", type: 'INIT',
roomId: LocalData().partyName, roomId: LocalData().partyName,
roomPin: LocalData().partyPin, roomPin: LocalData().partyPin,
}); });
// Listener // Listener
this.port.onMessage.addListener((response) => { this.port.onMessage.addListener((response) => {
if (response.isError === true) { if (response.isError === true) {
this.props.notify("Uh oh. Got lost from the party."); this.props.notify('Uh oh. Got lost from the party.');
goTo(Create, this.props); goTo(Create, this.props);
return; return;
} }
@@ -195,21 +182,13 @@ export default class Chat extends Component {
} }
// IF CHAT IS HIDDEN AND ALLOWS NOTIFICATION // IF CHAT IS HIDDEN AND ALLOWS NOTIFICATION
if ( if (!document.querySelector('body.visible') && this.state.allowChatNotification === true) {
!document.querySelector("body.visible") && if (response.messages && response.messages.length !== this.state.messages.length) {
this.state.allowChatNotification === true
) {
if (
response.messages &&
response.messages.length !== this.state.messages.length
) {
const lastMessage = response.messages[response.messages.length - 1]; const lastMessage = response.messages[response.messages.length - 1];
if (lastMessage.uid !== "<system>") { if (lastMessage.uid !== '<system>') {
this.props.notify( this.props.notify(
`${lastMessage.name}${ `${lastMessage.name}${
lastMessage.type === "giphy" lastMessage.type === 'giphy' ? ' sent a gif.' : ': ' + lastMessage.text
? " sent a gif."
: ": " + lastMessage.text
}` }`
); );
} }
@@ -225,7 +204,7 @@ export default class Chat extends Component {
// GIPHY IPC // GIPHY IPC
const giphyInject = `var giphySearchInteraction=function(e){if(e.source===window){const{data}=e;if(data.watchPartyDirection==='TO_SCRIPT'){if(data.type==='WATCH_PARTY_SEARCH_GIF'){const giphyInput=document.querySelector('.giphy-search-form input');if(giphyInput){giphyInput.value=data.value;giphyInput.dispatchEvent(new Event('change',{bubbles:true}))}}}}};window.addEventListener("message",giphySearchInteraction);`; const giphyInject = `var giphySearchInteraction=function(e){if(e.source===window){const{data}=e;if(data.watchPartyDirection==='TO_SCRIPT'){if(data.type==='WATCH_PARTY_SEARCH_GIF'){const giphyInput=document.querySelector('.giphy-search-form input');if(giphyInput){giphyInput.value=data.value;giphyInput.dispatchEvent(new Event('change',{bubbles:true}))}}}}};window.addEventListener("message",giphySearchInteraction);`;
const giphyInjectScript = document.createElement("script"); const giphyInjectScript = document.createElement('script');
giphyInjectScript.text = giphyInject; giphyInjectScript.text = giphyInject;
document.head.appendChild(giphyInjectScript); document.head.appendChild(giphyInjectScript);
@@ -277,14 +256,14 @@ export default class Chat extends Component {
}).catch((err) => { }).catch((err) => {
this.props.updateLoading(false); this.props.updateLoading(false);
this.props.notify(err.message || err.statusText); this.props.notify(err.message || err.statusText);
console.error("Sync Party API error", err); console.error('Sync Party API error', err);
}); });
} else { } else {
this.mVideoListener.start(); this.mVideoListener.start();
} }
} }
endParty() { endParty() {
this.props.notify("Ending party..."); this.props.notify('Ending party...');
this.props.updateLoading(true); this.props.updateLoading(true);
const data = { const data = {
partyName: LocalData().partyName, partyName: LocalData().partyName,
@@ -298,20 +277,20 @@ export default class Chat extends Component {
); );
DeleteRoomApi(data) DeleteRoomApi(data)
.then((res) => { .then((res) => {
this.props.notify("Ended party"); this.props.notify('Ended party');
removeLocalData("partyPin"); removeLocalData('partyPin');
removeLocalData("partyName"); removeLocalData('partyName');
goTo(Create, this.props); goTo(Create, this.props);
this.props.updateLoading(false); this.props.updateLoading(false);
}) })
.catch((err) => { .catch((err) => {
this.props.updateLoading(false); this.props.updateLoading(false);
this.props.notify(err.message || err.statusText); this.props.notify(err.message || err.statusText);
console.error("End Party API error", err); console.error('End Party API error', err);
}); });
} }
leaveParty() { leaveParty() {
this.props.notify("Leaving party..."); this.props.notify('Leaving party...');
this.props.updateLoading(true); this.props.updateLoading(true);
const data = { const data = {
partyName: LocalData().partyName, partyName: LocalData().partyName,
@@ -326,30 +305,28 @@ export default class Chat extends Component {
); );
LeaveRoomApi(data) LeaveRoomApi(data)
.then((res) => { .then((res) => {
this.props.notify("Left party"); this.props.notify('Left party');
removeLocalData("partyPin"); removeLocalData('partyPin');
removeLocalData("partyName"); removeLocalData('partyName');
goTo(Create, this.props); goTo(Create, this.props);
this.props.updateLoading(false); this.props.updateLoading(false);
}) })
.catch((err) => { .catch((err) => {
this.props.updateLoading(false); this.props.updateLoading(false);
this.props.notify(err.message || err.statusText); this.props.notify(err.message || err.statusText);
console.error("End Party API error", err); console.error('End Party API error', err);
}); });
} }
shareParty() { shareParty() {
const el = document.createElement("textarea"); const el = document.createElement('textarea');
el.value = `Join my party on Watch Party!\nParty Name: ${ el.value = `Join my party on Watch Party!\nParty Name: ${LocalData().partyName}\nParty Pin: ${
LocalData().partyName LocalData().partyPin
}\nParty Pin: ${LocalData().partyPin}\n${ }\n${window.location.href}\n---\nGet Watch Party at https:\\\\get.chromewatchparty.com`;
window.location.href
}\n---\nGet Watch Party at https:\\\\get.chromewatchparty.com`;
document.body.appendChild(el); document.body.appendChild(el);
el.select(); el.select();
document.execCommand("copy"); document.execCommand('copy');
document.body.removeChild(el); document.body.removeChild(el);
this.props.notify("Copied party invitation"); this.props.notify('Copied party invitation');
} }
sendMessage(message) { sendMessage(message) {
const { sendingMessages } = this.state; const { sendingMessages } = this.state;
@@ -360,9 +337,9 @@ export default class Chat extends Component {
uid: LocalData().userUid, uid: LocalData().userUid,
text: message, text: message,
time: new Date(), time: new Date(),
type: "", type: '',
}; };
if (this.state.gif === true) data.type = "giphy"; if (this.state.gif === true) data.type = 'giphy';
if (this.state.replyTo !== null) data.replyTo = this.state.replyTo.id; if (this.state.replyTo !== null) data.replyTo = this.state.replyTo.id;
sendingMessages.push(data); sendingMessages.push(data);
this.setState({ this.setState({
@@ -383,7 +360,7 @@ export default class Chat extends Component {
this.setState({ sendingMessages: sm }); this.setState({ sendingMessages: sm });
scrollThread(); scrollThread();
this.props.notify(err.message || err.statusText); this.props.notify(err.message || err.statusText);
console.error("Send Message API error", err); console.error('Send Message API error', err);
}); });
this.setState({ replyTo: null }); this.setState({ replyTo: null });
scrollThread(); scrollThread();
@@ -391,10 +368,10 @@ export default class Chat extends Component {
sendMessageInvoker(overrideMessage) { sendMessageInvoker(overrideMessage) {
if (overrideMessage) this.sendMessage(overrideMessage); if (overrideMessage) this.sendMessage(overrideMessage);
else { else {
const trim = this.state.newMessage.replace(/^\s+|\s+$/g, ""); const trim = this.state.newMessage.replace(/^\s+|\s+$/g, '');
if (trim !== "") this.sendMessage(trim); if (trim !== '') this.sendMessage(trim);
} }
this.setState({ newMessage: "" }); this.setState({ newMessage: '' });
} }
gifClick(iGif) { gifClick(iGif) {
this.sendMessageInvoker(iGif.images.original.url); this.sendMessageInvoker(iGif.images.original.url);
@@ -403,29 +380,29 @@ export default class Chat extends Component {
const { onCall, conference, admin, adminOnly } = this.state; const { onCall, conference, admin, adminOnly } = this.state;
if (window.navigator && onCall === false) { if (window.navigator && onCall === false) {
try { try {
const overlay = document.createElement("div"); const overlay = document.createElement('div');
overlay.innerHTML = ` overlay.innerHTML = `
<div id="mic-highlight"></div> <div id="mic-highlight"></div>
<h4 id="mic-text">Grant Mic Permission</h4> <h4 id="mic-text">Grant Mic Permission</h4>
`; `;
overlay.id = "mic-permission-overlay"; overlay.id = 'mic-permission-overlay';
document.body.appendChild(overlay); document.body.appendChild(overlay);
window.navigator window.navigator
.getUserMedia({ .getUserMedia({
audio: true, audio: true,
}) })
.then(() => { .then(() => {
document.getElementById("mic-permission-overlay").remove(); document.getElementById('mic-permission-overlay').remove();
this.mCallManager.toggleCall(onCall, conference, admin, adminOnly); this.mCallManager.toggleCall(onCall, conference, admin, adminOnly);
}) })
.catch(() => { .catch(() => {
document.getElementById("mic-permission-overlay").remove(); document.getElementById('mic-permission-overlay').remove();
this.props.notify( this.props.notify(
"Check your mic permission for this website. You can modify site permission by clicking on the lock icon in the top left." 'Check your mic permission for this website. You can modify site permission by clicking on the lock icon in the top left.'
); );
}); });
} catch (err) { } catch (err) {
console.error("Handle Phone Call Error", err); console.error('Handle Phone Call Error', err);
} }
} else this.mCallManager.toggleCall(onCall, conference, admin, adminOnly); } else this.mCallManager.toggleCall(onCall, conference, admin, adminOnly);
} }
@@ -461,7 +438,7 @@ export default class Chat extends Component {
adminOnly: !this.state.adminOnly, adminOnly: !this.state.adminOnly,
}).catch((err) => { }).catch((err) => {
this.props.notify(err.message || err.statusText); this.props.notify(err.message || err.statusText);
console.error("Update Admin Only API error", err); console.error('Update Admin Only API error', err);
}); });
} }
setReplyTo(message) { setReplyTo(message) {
@@ -473,7 +450,7 @@ export default class Chat extends Component {
getReplyToContent() { getReplyToContent() {
const { replyTo } = this.state; const { replyTo } = this.state;
if (replyTo) { if (replyTo) {
if (replyTo.type === "giphy") { if (replyTo.type === 'giphy') {
return <img alt="gif" src={replyTo.text} />; return <img alt="gif" src={replyTo.text} />;
} }
return ( return (
@@ -485,7 +462,7 @@ export default class Chat extends Component {
return null; return null;
} }
setVideoVolume(v, id) { setVideoVolume(v, id) {
const audioOuts = document.querySelectorAll("audio.vxt-audio"); const audioOuts = document.querySelectorAll('audio.vxt-audio');
if (audioOuts.length > 0) { if (audioOuts.length > 0) {
audioOuts.forEach((el) => { audioOuts.forEach((el) => {
if (el.id === `audio-${id}`) { if (el.id === `audio-${id}`) {
@@ -522,23 +499,20 @@ export default class Chat extends Component {
const alerts = [ const alerts = [
{ {
condition: () => condition: () =>
getPlayerSource() === PLAYER_SOURCE.HBOMAX || getPlayerSource() === PLAYER_SOURCE.HBOMAX || getPlayerSource() === PLAYER_SOURCE.HBONOW,
getPlayerSource() === PLAYER_SOURCE.HBONOW, message: 'Functionality may be buggy, HBO has a horrible design.',
message: "Functionality may be buggy, HBO has a horrible design.",
}, },
{ {
condition: () => getPlayerSource() === PLAYER_SOURCE.GOOGLEPLAY, condition: () => getPlayerSource() === PLAYER_SOURCE.GOOGLEPLAY,
message: message: 'Functionality may be buggy, support on this site is in testing.',
"Functionality may be buggy, support on this site is in testing.",
}, },
{ {
condition: () => getPlayerSource() === PLAYER_SOURCE.CRUNCHYROLL, condition: () => getPlayerSource() === PLAYER_SOURCE.CRUNCHYROLL,
message: message: 'Functionality may be buggy, support on this site is in testing.',
"Functionality may be buggy, support on this site is in testing.",
}, },
{ {
condition: () => adminOnly, condition: () => adminOnly,
message: "Party is currently in admin only mode.", message: 'Party is currently in admin only mode.',
}, },
]; ];
return ( return (
@@ -565,12 +539,7 @@ export default class Chat extends Component {
> >
WATCH PARTY WATCH PARTY
</Typography> </Typography>
<Typography <Typography color="textPrimary" className="room-title" variant="h4" gutterBottom>
color="textPrimary"
className="room-title"
variant="h4"
gutterBottom
>
{name} {name}
</Typography> </Typography>
</div> </div>
@@ -579,9 +548,9 @@ export default class Chat extends Component {
<TextField <TextField
className="share-textbox" className="share-textbox"
label="Party Details" label="Party Details"
value={`Party Name: ${LocalData().partyName}\nParty Pin: ${ value={`Party Name: ${LocalData().partyName}\nParty Pin: ${LocalData().partyPin}\n${
LocalData().partyPin window.location.href
}\n${window.location.href}`} }`}
multiline multiline
rowsMax={2} rowsMax={2}
variant="outlined" variant="outlined"
@@ -608,19 +577,13 @@ export default class Chat extends Component {
color="secondary" color="secondary"
> >
<Button onClick={this.leaveParty} startIcon={<Exit />}> <Button onClick={this.leaveParty} startIcon={<Exit />}>
<Typography <Typography variant="caption" className="party-control-button-text">
variant="caption"
className="party-control-button-text"
>
Leave Leave
</Typography> </Typography>
</Button> </Button>
{admin && ( {admin && (
<Button onClick={this.endParty} startIcon={<Delete />}> <Button onClick={this.endParty} startIcon={<Delete />}>
<Typography <Typography variant="caption" className="party-control-button-text">
variant="caption"
className="party-control-button-text"
>
End End
</Typography> </Typography>
</Button> </Button>
@@ -633,17 +596,15 @@ export default class Chat extends Component {
checked={allowChatNotification} checked={allowChatNotification}
onChange={this.updateAllowChatNotification} onChange={this.updateAllowChatNotification}
name="allowChatNotification" name="allowChatNotification"
color={allowChatNotification ? "secondary" : "primary"} color={allowChatNotification ? 'secondary' : 'primary'}
/> />
} }
label={ label={
<span> <span>
Allow chat notification when side panel is closed Allow chat notification when side panel is closed
<br /> <br />
<span style={{ color: "#8a8a8a" }}> <span style={{ color: '#8a8a8a' }}>
{allowChatNotification {allowChatNotification ? 'Notifications Enabled' : 'Notifications Disabled'}
? "Notifications Enabled"
: "Notifications Disabled"}
</span> </span>
</span> </span>
} }
@@ -656,17 +617,15 @@ export default class Chat extends Component {
checked={allowAutoRejoin} checked={allowAutoRejoin}
onChange={this.updateAllowAutoRejoin} onChange={this.updateAllowAutoRejoin}
name="allowAutoRejoin" name="allowAutoRejoin"
color={allowAutoRejoin ? "secondary" : "primary"} color={allowAutoRejoin ? 'secondary' : 'primary'}
/> />
} }
label={ label={
<span> <span>
Allow Watch Party to auto rejoin (within 1 minute) Allow Watch Party to auto rejoin (within 1 minute)
<br /> <br />
<span style={{ color: "#8a8a8a" }}> <span style={{ color: '#8a8a8a' }}>
{allowAutoRejoin {allowAutoRejoin ? 'Auto Rejoin Enabled' : 'Auto Rejoin Disabled'}
? "Auto Rejoin Enabled"
: "Auto Rejoin Disabled"}
</span> </span>
</span> </span>
} }
@@ -680,7 +639,7 @@ export default class Chat extends Component {
checked={adminOnly} checked={adminOnly}
onChange={this.updateAdminOnly} onChange={this.updateAdminOnly}
name="adminOnly" name="adminOnly"
color={adminOnly ? "secondary" : "primary"} color={adminOnly ? 'secondary' : 'primary'}
disabled={adminModeUpdate} disabled={adminModeUpdate}
/> />
} }
@@ -688,53 +647,38 @@ export default class Chat extends Component {
<span> <span>
Admin Only Mode Admin Only Mode
<br /> <br />
<span style={{ color: "#8a8a8a" }}> <span style={{ color: '#8a8a8a' }}>
{adminOnly {adminOnly
? "Only admin can update player and start calls right now" ? 'Only admin can update player and start calls right now'
: "All party members can update player and start calls right now"} : 'All party members can update player and start calls right now'}
</span> </span>
</span> </span>
} }
labelPlacement="end" labelPlacement="end"
/> />
) : null} ) : null}
<Typography <Typography className="party-controls-users-title" variant="overline">
className="party-controls-users-title"
variant="overline"
>
PARTY MEMBERS PARTY MEMBERS
</Typography> </Typography>
<div className="party-controls-users-container"> <div className="party-controls-users-container">
{users.map((user) => ( {users.map((user) => (
<Chip <Chip className="party-controls-users-chip" clickable size="small" label={user} />
className="party-controls-users-chip"
clickable
size="small"
label={user}
/>
))} ))}
</div> </div>
{Object.keys(usersOnCall).length > 0 ? ( {Object.keys(usersOnCall).length > 0 ? (
<Typography <Typography className="party-controls-users-title" variant="overline">
className="party-controls-users-title"
variant="overline"
>
MEMBERS IN CALL MEMBERS IN CALL
</Typography> </Typography>
) : null} ) : null}
{Object.keys(usersOnCall).length > 0 ? ( {Object.keys(usersOnCall).length > 0 ? (
<div className="party-controls-users-container"> <div className="party-controls-users-container">
{Object.keys(usersOnCall).map((id) => { {Object.keys(usersOnCall).map((id) => {
return usersOnCall[id].status === "Connected" || return usersOnCall[id].status === 'Connected' ||
usersOnCall[id].status === "Connecting" ? ( usersOnCall[id].status === 'Connecting' ? (
<Tooltip <Tooltip
interactive interactive
title={ title={
<Grid <Grid className="party-controls-users-volume" container spacing={2}>
className="party-controls-users-volume"
container
spacing={2}
>
<Grid item> <Grid item>
<VolumeDown /> <VolumeDown />
</Grid> </Grid>
@@ -745,9 +689,7 @@ export default class Chat extends Component {
step={1} step={1}
color="secondary" color="secondary"
value={volumes[id] || 10} value={volumes[id] || 10}
onChangeCommitted={(e, v) => onChangeCommitted={(e, v) => this.setVideoVolume(v, id)}
this.setVideoVolume(v, id)
}
/> />
</Grid> </Grid>
<Grid item> <Grid item>
@@ -758,15 +700,14 @@ export default class Chat extends Component {
> >
<Chip <Chip
color={ color={
usersOnCall[id].info.externalId === usersOnCall[id].info.externalId === LocalData().userUid
LocalData().userUid ? 'secondary'
? "secondary" : 'default'
: "default"
} }
className="party-controls-users-chip" className="party-controls-users-chip"
clickable clickable
size="small" size="small"
label={usersOnCall[id].info.name || " "} label={usersOnCall[id].info.name || ' '}
/> />
</Tooltip> </Tooltip>
) : null; ) : null;
@@ -777,8 +718,7 @@ export default class Chat extends Component {
</ExpansionPanel> </ExpansionPanel>
{player ? ( {player ? (
<Card elevation={0} className="media-info-card"> <Card elevation={0} className="media-info-card">
{player.showName && {player.showName && player.status !== PLAYER_STATUS.NOT_PLAYING ? (
player.status !== PLAYER_STATUS.NOT_PLAYING ? (
<CardContent> <CardContent>
<Typography className="media-info-at" variant="overline"> <Typography className="media-info-at" variant="overline">
{player.status === PLAYER_STATUS.PAUSED {player.status === PLAYER_STATUS.PAUSED
@@ -803,17 +743,13 @@ export default class Chat extends Component {
) : ( ) : (
<CardContent> <CardContent>
<Typography className="media-info-at" variant="caption"> <Typography className="media-info-at" variant="caption">
Nothing playing right now, pause or play once after starting Nothing playing right now, pause or play once after starting a show to start
a show to start sync. sync.
</Typography> </Typography>
</CardContent> </CardContent>
)} )}
{player && player.showName && player.status ? ( {player && player.showName && player.status ? (
<Button <Button className="media-info-link" href={player.url} startIcon={<LinkOutlined />}>
className="media-info-link"
href={player.url}
startIcon={<LinkOutlined />}
>
Link to currently playing Link to currently playing
</Button> </Button>
) : null} ) : null}
@@ -844,9 +780,7 @@ export default class Chat extends Component {
<Paper <Paper
square square
variant="outlined" variant="outlined"
className={`replying-to-card ${ className={`replying-to-card ${replyTo !== null ? 'replying-to-card-up' : ''}`}
replyTo !== null ? "replying-to-card-up" : ""
}`}
> >
<div className="replying-to-content"> <div className="replying-to-content">
<Typography variant="overline" display="block" gutterBottom> <Typography variant="overline" display="block" gutterBottom>
@@ -860,15 +794,8 @@ export default class Chat extends Component {
</Paper> </Paper>
<div className="text-phone-panel"> <div className="text-phone-panel">
{gif || newMessage ? null : ( {gif || newMessage ? null : (
<Tooltip <Tooltip title="Fullscreen with Watch Party" aria-label="Fullscreen">
title="Fullscreen with Watch Party" <IconButton className="icon-button" color="secondary" onClick={this.toggleFullscreen}>
aria-label="Fullscreen"
>
<IconButton
className="icon-button"
color="secondary"
onClick={this.toggleFullscreen}
>
{isFullscreen ? <FullscreenExit /> : <Fullscreen />} {isFullscreen ? <FullscreenExit /> : <Fullscreen />}
</IconButton> </IconButton>
</Tooltip> </Tooltip>
@@ -879,7 +806,7 @@ export default class Chat extends Component {
<IconButton <IconButton
disabled={callActionPending} disabled={callActionPending}
onClick={this.handlePhoneCall} onClick={this.handlePhoneCall}
color={!onCall ? "secondary" : "primary"} color={!onCall ? 'secondary' : 'primary'}
className="icon-button" className="icon-button"
> >
{onCall ? ( {onCall ? (
@@ -921,14 +848,12 @@ export default class Chat extends Component {
multiline multiline
rowsMax="3" rowsMax="3"
size="small" size="small"
placeholder={ placeholder={this.state.gif ? 'Search something...' : 'Say something...'}
this.state.gif ? "Search something..." : "Say something..."
}
helperText={ helperText={
this.state.newMessage && !this.state.gif this.state.newMessage && !this.state.gif
? "Enter to send / Shift+Enter for new line" ? 'Enter to send / Shift+Enter for new line'
: this.state.gif : this.state.gif
? "Click on gif to send / Scroll to load more" ? 'Click on gif to send / Scroll to load more'
: null : null
} }
variant="outlined" variant="outlined"
@@ -939,19 +864,19 @@ export default class Chat extends Component {
scrollThread(); scrollThread();
if (gif) { if (gif) {
window.postMessage({ window.postMessage({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_SEARCH_GIF", type: 'WATCH_PARTY_SEARCH_GIF',
value: e.target.value, value: e.target.value,
}); });
} }
}} }}
InputProps={{ InputProps={{
id: "chat-message-box-input", id: 'chat-message-box-input',
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
<IconButton <IconButton
className={`${this.state.gif ? "gif-active" : ""} ${ className={`${this.state.gif ? 'gif-active' : ''} ${
this.state.newMessage ? "message-active" : "" this.state.newMessage ? 'message-active' : ''
} message-send`} } message-send`}
size="small" size="small"
onClick={() => this.sendMessageInvoker(newMessage)} onClick={() => this.sendMessageInvoker(newMessage)}
@@ -964,15 +889,13 @@ export default class Chat extends Component {
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
<IconButton <IconButton
className={`gif-button ${ className={`gif-button ${this.state.gif ? 'gif-close' : ''}`}
this.state.gif ? "gif-close" : ""
}`}
onClick={() => { onClick={() => {
this.setState({ gif: !gif }); this.setState({ gif: !gif });
if (!gif) { if (!gif) {
window.postMessage({ window.postMessage({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_SEARCH_GIF", type: 'WATCH_PARTY_SEARCH_GIF',
value: newMessage, value: newMessage,
}); });
scrollThread(); scrollThread();
@@ -990,9 +913,9 @@ export default class Chat extends Component {
<ReactGiphySearchbox <ReactGiphySearchbox
apiKey="ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq" apiKey="ojJbIMUN6XRMn4mHiFFav3rMCpXUg8sq"
onSelect={this.gifClick} onSelect={this.gifClick}
masonryConfig={[{ columns: 2, imageWidth: "50%", gutter: 5 }]} masonryConfig={[{ columns: 2, imageWidth: '50%', gutter: 5 }]}
searchFormClassName="giphy-search-form" searchFormClassName="giphy-search-form"
wrapperClassName={`giphy-wrapper ${gif ? "" : "giphy-wrapper-down"}`} wrapperClassName={`giphy-wrapper ${gif ? '' : 'giphy-wrapper-down'}`}
listWrapperClassName="giphy-list-wrapper" listWrapperClassName="giphy-list-wrapper"
listItemClassName="giphy-list-item" listItemClassName="giphy-list-item"
poweredByGiphy poweredByGiphy
+2 -2
View File
@@ -12,7 +12,7 @@ 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; word-break: break-word !important;
} }
@@ -100,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;
+107 -203
View File
@@ -9,22 +9,17 @@ 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 { import { PLAYER_STATUS, getPlayerSource, PLAYER_SOURCE, LocalData } from './Api';
PLAYER_STATUS,
getPlayerSource,
PLAYER_SOURCE,
LocalData,
} from "./Api";
const templateListener = (video) => console.log("MISSING VIDEO LISTENER"); const templateListener = (video) => console.log('MISSING VIDEO LISTENER');
export default class VideoListener { export default class VideoListener {
constructor(listener = templateListener, selectors, nameSelectors) { constructor(listener = templateListener, selectors, nameSelectors) {
this.video = { this.video = {
status: PLAYER_STATUS.NOT_PLAYING, status: PLAYER_STATUS.NOT_PLAYING,
time: 0, time: 0,
showName: "", showName: '',
source: "", source: '',
element: null, element: null,
}; };
this.nameSelectors = nameSelectors; this.nameSelectors = nameSelectors;
@@ -49,7 +44,7 @@ export default class VideoListener {
this.video.element !== null && this.video.element !== null &&
this.video.element !== undefined && this.video.element !== undefined &&
this.video.status !== PLAYER_STATUS.NOT_PLAYING && this.video.status !== PLAYER_STATUS.NOT_PLAYING &&
this.video.showName !== "" && this.video.showName !== '' &&
this.video.showName !== null && this.video.showName !== null &&
(this.video.status !== this.server.status || (this.video.status !== this.server.status ||
Math.abs(this.video.element.currentTime - this.server.time) > 1.5) Math.abs(this.video.element.currentTime - this.server.time) > 1.5)
@@ -76,31 +71,24 @@ export default class VideoListener {
// REMOVE LISTENER BEFORE SYNCING // REMOVE LISTENER BEFORE SYNCING
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
window.removeEventListener("watchParty", this.crunchyRollListener); window.removeEventListener('watchParty', this.crunchyRollListener);
break; break;
default: default:
this.video.element.removeEventListener("playing", this.onplay); this.video.element.removeEventListener('playing', this.onplay);
this.video.element.removeEventListener("pause", this.onpause); this.video.element.removeEventListener('pause', this.onpause);
} }
await this.timeout(250); await this.timeout(250);
// SEEK // SEEK
if ( if (Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5) {
Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5
) {
switch (serverPlayer.source) { switch (serverPlayer.source) {
case PLAYER_SOURCE.NETFLIX: case PLAYER_SOURCE.NETFLIX:
window.postMessage( window.postMessage({ type: 'SEEK', time: serverPlayer.time * 1000 }, '*');
{ type: "SEEK", time: serverPlayer.time * 1000 },
"*"
);
break; break;
case PLAYER_SOURCE.AMAZON: case PLAYER_SOURCE.AMAZON:
if (this.video.status === PLAYER_STATUS.PAUSED) if (this.video.status === PLAYER_STATUS.PAUSED)
await this.video.element await this.video.element
.play() .play()
.catch((err) => .catch((err) => console.error('WatchParty erred when syncing time.'));
console.error("WatchParty erred when syncing time.")
);
await this.timeout(250); await this.timeout(250);
this.video.element.currentTime = serverPlayer.time; this.video.element.currentTime = serverPlayer.time;
await this.timeout(500); await this.timeout(500);
@@ -113,10 +101,7 @@ export default class VideoListener {
this.video.element.currentTime = serverPlayer.time; this.video.element.currentTime = serverPlayer.time;
break; break;
case PLAYER_SOURCE.HULU: case PLAYER_SOURCE.HULU:
window.postMessage( window.postMessage({ type: 'SEEK', time: serverPlayer.time }, '*');
{ type: "SEEK", time: serverPlayer.time },
"*"
);
break; break;
case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBOMAX:
case PLAYER_SOURCE.HBONOW: case PLAYER_SOURCE.HBONOW:
@@ -125,8 +110,8 @@ export default class VideoListener {
case PLAYER_SOURCE.PEACOCK: case PLAYER_SOURCE.PEACOCK:
window.postMessage( window.postMessage(
JSON.stringify({ JSON.stringify({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_SEEK", type: 'WATCH_PARTY_SEEK',
status: serverPlayer.status, status: serverPlayer.status,
time: serverPlayer.time, time: serverPlayer.time,
}) })
@@ -138,8 +123,8 @@ export default class VideoListener {
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
window.postMessage( window.postMessage(
JSON.stringify({ JSON.stringify({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_SEEK", type: 'WATCH_PARTY_SEEK',
status: serverPlayer.status, status: serverPlayer.status,
time: serverPlayer.time, time: serverPlayer.time,
}) })
@@ -158,18 +143,15 @@ export default class VideoListener {
PLAYER_SOURCE.HBOMAX === this.video.source || PLAYER_SOURCE.HBOMAX === this.video.source ||
PLAYER_SOURCE.HBONOW === this.video.source PLAYER_SOURCE.HBONOW === this.video.source
) { ) {
window.postMessage( window.postMessage({ type: 'PAUSE', time: serverPlayer.time }, '*');
{ type: "PAUSE", time: serverPlayer.time },
"*"
);
} else if ( } else if (
PLAYER_SOURCE.CRUNCHYROLL === this.video.source || PLAYER_SOURCE.CRUNCHYROLL === this.video.source ||
PLAYER_SOURCE.PEACOCK === this.video.source PLAYER_SOURCE.PEACOCK === this.video.source
) { ) {
window.postMessage( window.postMessage(
JSON.stringify({ JSON.stringify({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_STATUS", type: 'WATCH_PARTY_STATUS',
status: serverPlayer.status, status: serverPlayer.status,
time: serverPlayer.time, time: serverPlayer.time,
}) })
@@ -185,18 +167,15 @@ export default class VideoListener {
PLAYER_SOURCE.HBOMAX === this.video.source || PLAYER_SOURCE.HBOMAX === this.video.source ||
PLAYER_SOURCE.HBONOW === this.video.source PLAYER_SOURCE.HBONOW === this.video.source
) { ) {
window.postMessage( window.postMessage({ type: 'PLAY', time: serverPlayer.time }, '*');
{ type: "PLAY", time: serverPlayer.time },
"*"
);
} else if ( } else if (
PLAYER_SOURCE.CRUNCHYROLL === this.video.source || PLAYER_SOURCE.CRUNCHYROLL === this.video.source ||
PLAYER_SOURCE.PEACOCK === this.video.source PLAYER_SOURCE.PEACOCK === this.video.source
) { ) {
window.postMessage( window.postMessage(
JSON.stringify({ JSON.stringify({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_STATUS", type: 'WATCH_PARTY_STATUS',
status: serverPlayer.status, status: serverPlayer.status,
time: serverPlayer.time, time: serverPlayer.time,
}) })
@@ -204,9 +183,7 @@ export default class VideoListener {
} else { } else {
await this.video.element await this.video.element
.play() .play()
.catch((err) => .catch((err) => console.error('WatchParty erred when syncing play.'));
console.error("WatchParty erred when syncing play.")
);
} }
break; break;
default: default:
@@ -216,10 +193,10 @@ export default class VideoListener {
// RE-ADD LISTENERS FOR FUTURE SYNC // RE-ADD LISTENERS FOR FUTURE SYNC
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
window.addEventListener("watchParty", this.crunchyRollListener); window.addEventListener('watchParty', this.crunchyRollListener);
default: default:
this.video.element.addEventListener("playing", this.onplay); this.video.element.addEventListener('playing', this.onplay);
this.video.element.addEventListener("pause", this.onpause); this.video.element.addEventListener('pause', this.onpause);
} }
} }
this.isUpdating = false; this.isUpdating = false;
@@ -235,72 +212,60 @@ export default class VideoListener {
const nS = this.nameSelectors[this.video.source]; const nS = this.nameSelectors[this.video.source];
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.NETFLIX: case PLAYER_SOURCE.NETFLIX:
var nshow = document.querySelector(nS.show).innerHTML || ""; var nshow = document.querySelector(nS.show).innerHTML || '';
var nepisode = ""; var nepisode = '';
if (document.querySelectorAll(nS.episode)) { if (document.querySelectorAll(nS.episode)) {
document document.querySelectorAll(nS.episode).forEach((el) => (nepisode += el.innerHTML + ' '));
.querySelectorAll(nS.episode)
.forEach((el) => (nepisode += el.innerHTML + " "));
} }
return nshow === "" && nepisode === "" ? null : nshow + "\n" + nepisode; return nshow === '' && nepisode === '' ? null : nshow + '\n' + nepisode;
case PLAYER_SOURCE.AMAZON: case PLAYER_SOURCE.AMAZON:
const ashow = document.querySelector(nS.show).innerText || ""; const ashow = document.querySelector(nS.show).innerText || '';
return ashow === "" ? null : ashow; return ashow === '' ? null : ashow;
case PLAYER_SOURCE.HULU: case PLAYER_SOURCE.HULU:
const hshow = document.querySelector(nS.show).innerText; const hshow = document.querySelector(nS.show).innerText;
const hepisode = document const hepisode = document.querySelector(nS.episode).innerText.replace(/\n/gi, ' ');
.querySelector(nS.episode) return hshow === '' && hepisode === '' ? null : hshow + '\n' + hepisode;
.innerText.replace(/\n/gi, " ");
return hshow === "" && hepisode === "" ? null : hshow + "\n" + hepisode;
case PLAYER_SOURCE.DISNEY: case PLAYER_SOURCE.DISNEY:
this.video.element.parentElement.click(); this.video.element.parentElement.click();
await this.timeout(200); await this.timeout(200);
const dshow = document.querySelector(nS.show) const dshow = document.querySelector(nS.show)
? document.querySelector(nS.show).innerHTML ? document.querySelector(nS.show).innerHTML
: ""; : '';
const depisode = document.querySelector(nS.episode) const depisode = document.querySelector(nS.episode)
? document.querySelector(nS.episode).innerHTML ? document.querySelector(nS.episode).innerHTML
: ""; : '';
return dshow === "" && depisode === "" ? null : dshow + "\n" + depisode; return dshow === '' && depisode === '' ? null : dshow + '\n' + depisode;
case PLAYER_SOURCE.YOUTUBE: case PLAYER_SOURCE.YOUTUBE:
const yshow = document.querySelector(nS.show).innerText || ""; const yshow = document.querySelector(nS.show).innerText || '';
const yepisode = document.querySelector(nS.episode).innerText || ""; const yepisode = document.querySelector(nS.episode).innerText || '';
return yshow === "" && yepisode === "" ? null : yshow + "\n" + yepisode; return yshow === '' && yepisode === '' ? null : yshow + '\n' + yepisode;
case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBOMAX:
case PLAYER_SOURCE.HBONOW: case PLAYER_SOURCE.HBONOW:
const bottomHalf = this.video.element.parentNode.parentNode.parentNode const bottomHalf = this.video.element.parentNode.parentNode.parentNode.parentNode.parentNode
.parentNode.parentNode.children[1]; .children[1];
bottomHalf.children[0].id = "hboUpperTitle"; bottomHalf.children[0].id = 'hboUpperTitle';
bottomHalf.children[1].id = "hboLowerTitle"; bottomHalf.children[1].id = 'hboLowerTitle';
const hboshow = document.querySelector("#hboUpperTitle").innerText; const hboshow = document.querySelector('#hboUpperTitle').innerText;
const hboepisode = document.querySelector("#hboLowerTitle").innerText; const hboepisode = document.querySelector('#hboLowerTitle').innerText;
return hboshow === "" && hboepisode === "" return hboshow === '' && hboepisode === '' ? null : hboshow + '\n' + hboepisode;
? null
: hboshow + "\n" + hboepisode;
case PLAYER_SOURCE.PEACOCK: case PLAYER_SOURCE.PEACOCK:
const peacockshow = document.querySelector(nS.show).innerText || ""; const peacockshow = document.querySelector(nS.show).innerText || '';
const peacockepisode = const peacockepisode = document.querySelector(nS.episode).innerText || '';
document.querySelector(nS.episode).innerText || ""; return peacockshow === '' && peacockepisode === ''
return peacockshow === "" && peacockepisode === ""
? null ? null
: peacockshow + "\n" + peacockepisode; : peacockshow + '\n' + peacockepisode;
case PLAYER_SOURCE.GOOGLEPLAY: case PLAYER_SOURCE.GOOGLEPLAY:
const playerIframe = document.querySelector( const playerIframe = document.querySelector(this.selectors[PLAYER_SOURCE.GOOGLEPLAY]);
this.selectors[PLAYER_SOURCE.GOOGLEPLAY] var googleplayshow = '';
);
var googleplayshow = "";
if (playerIframe) { if (playerIframe) {
googleplayshow = googleplayshow =
playerIframe.contentWindow.document.querySelector(nS.show) playerIframe.contentWindow.document.querySelector(nS.show).innerText || '';
.innerText || "";
} }
return googleplayshow === "" ? null : googleplayshow; return googleplayshow === '' ? null : googleplayshow;
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
const crunchyrollTitle = document.querySelector(nS.show); const crunchyrollTitle = document.querySelector(nS.show);
const crunchyrollshow = crunchyrollTitle const crunchyrollshow = crunchyrollTitle ? crunchyrollTitle.innerText : '';
? crunchyrollTitle.innerText return crunchyrollshow === '' ? null : crunchyrollshow;
: "";
return crunchyrollshow === "" ? null : crunchyrollshow;
default: default:
break; break;
} }
@@ -321,8 +286,8 @@ export default class VideoListener {
} }
async crunchyRollListener(ev) { async crunchyRollListener(ev) {
if ( if (
ev.detail.watchPartyDirection === "TO_APP" && ev.detail.watchPartyDirection === 'TO_APP' &&
ev.detail.type === "WATCH_PARTY_PLAYER_UPDATE" ev.detail.type === 'WATCH_PARTY_PLAYER_UPDATE'
) { ) {
this.updateStatus({ this.updateStatus({
status: ev.detail.status, status: ev.detail.status,
@@ -342,15 +307,15 @@ export default class VideoListener {
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
window.postMessage( window.postMessage(
JSON.stringify({ JSON.stringify({
watchPartyDirection: "TO_SCRIPT", watchPartyDirection: 'TO_SCRIPT',
type: "WATCH_PARTY_ADD_LISTENERS", type: 'WATCH_PARTY_ADD_LISTENERS',
}) })
); );
window.addEventListener("watchParty", this.crunchyRollListener); window.addEventListener('watchParty', this.crunchyRollListener);
break; break;
default: default:
videoElement.addEventListener("playing", this.onplay); videoElement.addEventListener('playing', this.onplay);
videoElement.addEventListener("pause", this.onpause); videoElement.addEventListener('pause', this.onpause);
} }
} }
async start() { async start() {
@@ -361,12 +326,10 @@ export default class VideoListener {
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.NETFLIX: case PLAYER_SOURCE.NETFLIX:
const seekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=window.netflix.appContext.state.playerApp.getAPI().videoPlayer,t=e.getAllPlayerSessionIds()[0];return e.getVideoPlayerBySessionId(t)},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().pause();getVideoPlayer().seek(e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; const seekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=window.netflix.appContext.state.playerApp.getAPI().videoPlayer,t=e.getAllPlayerSessionIds()[0];return e.getVideoPlayerBySessionId(t)},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().pause();getVideoPlayer().seek(e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`;
const seekInjectScript = document.createElement("script"); const seekInjectScript = document.createElement('script');
seekInjectScript.text = seekInject; seekInjectScript.text = seekInject;
document.head.appendChild(seekInjectScript); document.head.appendChild(seekInjectScript);
const videoElement = document.querySelector( const videoElement = document.querySelector(this.selectors[PLAYER_SOURCE.NETFLIX]);
this.selectors[PLAYER_SOURCE.NETFLIX]
);
if (videoElement && !this.video.element) { if (videoElement && !this.video.element) {
this.firstTimeSync(videoElement); this.firstTimeSync(videoElement);
} else { } else {
@@ -374,13 +337,8 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var nve = document.querySelector( var nve = document.querySelector(this.selectors[PLAYER_SOURCE.NETFLIX]);
this.selectors[PLAYER_SOURCE.NETFLIX] if (nve !== null && (this.video.element !== nve || this.video.element === null)) {
);
if (
nve !== null &&
(this.video.element !== nve || this.video.element === null)
) {
this.firstTimeSync(nve); this.firstTimeSync(nve);
} }
}, },
@@ -392,12 +350,10 @@ export default class VideoListener {
const huluSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ const huluSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${
this.selectors[PLAYER_SOURCE.HULU] this.selectors[PLAYER_SOURCE.HULU]
}").__HuluDashPlayer__;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().seek(e.data.time,e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; }").__HuluDashPlayer__;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&"SEEK"==e.data.type){getVideoPlayer().seek(e.data.time,e.data.time);}if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`;
const huluSeekInjectScript = document.createElement("script"); const huluSeekInjectScript = document.createElement('script');
huluSeekInjectScript.text = huluSeekInject; huluSeekInjectScript.text = huluSeekInject;
document.head.appendChild(huluSeekInjectScript); document.head.appendChild(huluSeekInjectScript);
const huluVideoElement = document.querySelector( const huluVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HULU]);
this.selectors[PLAYER_SOURCE.HULU]
);
if (huluVideoElement) { if (huluVideoElement) {
this.firstTimeSync(huluVideoElement); this.firstTimeSync(huluVideoElement);
} else { } else {
@@ -405,13 +361,8 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var hve = document.querySelector( var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HULU]);
this.selectors[PLAYER_SOURCE.HULU] if (hve !== null && (this.video.element !== hve || this.video.element === null)) {
);
if (
hve !== null &&
(this.video.element !== hve || this.video.element === null)
) {
this.firstTimeSync(hve); this.firstTimeSync(hve);
} }
}, },
@@ -420,9 +371,7 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.AMAZON: case PLAYER_SOURCE.AMAZON:
const amazonVideoElement = document.querySelector( const amazonVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.AMAZON]);
this.selectors[PLAYER_SOURCE.AMAZON]
);
if (amazonVideoElement) { if (amazonVideoElement) {
this.firstTimeSync(amazonVideoElement); this.firstTimeSync(amazonVideoElement);
} else { } else {
@@ -430,13 +379,8 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var ave = document.querySelector( var ave = document.querySelector(this.selectors[PLAYER_SOURCE.AMAZON]);
this.selectors[PLAYER_SOURCE.AMAZON] if (ave !== null && (this.video.element !== ave || this.video.element === null)) {
);
if (
ave !== null &&
(this.video.element !== ave || this.video.element === null)
) {
this.firstTimeSync(ave); this.firstTimeSync(ave);
} }
}, },
@@ -445,9 +389,7 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.DISNEY: case PLAYER_SOURCE.DISNEY:
const disneyVideoElement = document.querySelector( const disneyVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.DISNEY]);
this.selectors[PLAYER_SOURCE.DISNEY]
);
if (disneyVideoElement) { if (disneyVideoElement) {
this.firstTimeSync(disneyVideoElement); this.firstTimeSync(disneyVideoElement);
} else { } else {
@@ -455,13 +397,8 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var dve = document.querySelector( var dve = document.querySelector(this.selectors[PLAYER_SOURCE.DISNEY]);
this.selectors[PLAYER_SOURCE.DISNEY] if (dve !== null && (this.video.element !== dve || this.video.element === null)) {
);
if (
dve !== null &&
(this.video.element !== dve || this.video.element === null)
) {
this.firstTimeSync(dve); this.firstTimeSync(dve);
} }
}, },
@@ -470,22 +407,15 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.YOUTUBE: case PLAYER_SOURCE.YOUTUBE:
const youtubeVideoElement = document.querySelector( const youtubeVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.YOUTUBE]);
this.selectors[PLAYER_SOURCE.YOUTUBE]
);
if (youtubeVideoElement) this.firstTimeSync(youtubeVideoElement); if (youtubeVideoElement) this.firstTimeSync(youtubeVideoElement);
else { else {
setInterval( setInterval(
this.video.element this.video.element
? null ? null
: () => { : () => {
var yve = document.querySelector( var yve = document.querySelector(this.selectors[PLAYER_SOURCE.YOUTUBE]);
this.selectors[PLAYER_SOURCE.YOUTUBE] if (yve !== null && (this.video.element !== yve || this.video.element === null)) {
);
if (
yve !== null &&
(this.video.element !== yve || this.video.element === null)
) {
this.firstTimeSync(yve); this.firstTimeSync(yve);
} }
}, },
@@ -497,27 +427,22 @@ export default class VideoListener {
const hboSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ const hboSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${
this.selectors[PLAYER_SOURCE.HBOMAX] this.selectors[PLAYER_SOURCE.HBOMAX]
}")._dispNode;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; }")._dispNode;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`;
const hboSeekInjectScript = document.createElement("script"); const hboSeekInjectScript = document.createElement('script');
hboSeekInjectScript.text = hboSeekInject; hboSeekInjectScript.text = hboSeekInject;
document.head.appendChild(hboSeekInjectScript); document.head.appendChild(hboSeekInjectScript);
const hboVideoElement = document.querySelector( const hboVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HBOMAX]);
this.selectors[PLAYER_SOURCE.HBOMAX]
);
if (hboVideoElement) { if (hboVideoElement) {
const bottomHalf = const bottomHalf =
hboVideoElement.parentNode.parentNode.parentNode.parentNode hboVideoElement.parentNode.parentNode.parentNode.parentNode.parentNode.children[1];
.parentNode.children[1]; bottomHalf.children[0].id = 'hboUpperTitle';
bottomHalf.children[0].id = "hboUpperTitle"; bottomHalf.children[1].id = 'hboLowerTitle';
bottomHalf.children[1].id = "hboLowerTitle";
this.firstTimeSync(hboVideoElement); this.firstTimeSync(hboVideoElement);
} else { } else {
setInterval( setInterval(
this.video.element this.video.element
? null ? null
: () => { : () => {
var hve = document.querySelector( var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HBOMAX]);
this.selectors[PLAYER_SOURCE.HBOMAX]
);
if ( if (
hve !== null && hve !== null &&
hve !== undefined && hve !== undefined &&
@@ -534,27 +459,22 @@ export default class VideoListener {
const hboNowSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ const hboNowSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${
this.selectors[PLAYER_SOURCE.HBONOW] this.selectors[PLAYER_SOURCE.HBONOW]
}")._dispNode;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`; }")._dispNode;return e;},seekInteraction=function(e){if(e.source==window){if(e.data.type&&e.data.type==="PAUSE"){getVideoPlayer().pause();}if(e.data.type&&e.data.type==="PLAY"){getVideoPlayer().play();}e.data.type&&"teardown"==e.data.type&&(window.removeEventListener("message",seekInteraction,!1),window.seekScriptLoaded=!1)}};window.addEventListener("message",seekInteraction,!1);`;
const hboNowSeekInjectScript = document.createElement("script"); const hboNowSeekInjectScript = document.createElement('script');
hboNowSeekInjectScript.text = hboNowSeekInject; hboNowSeekInjectScript.text = hboNowSeekInject;
document.head.appendChild(hboNowSeekInjectScript); document.head.appendChild(hboNowSeekInjectScript);
const hboNowVideoElement = document.querySelector( const hboNowVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HBONOW]);
this.selectors[PLAYER_SOURCE.HBONOW]
);
if (hboNowVideoElement) { if (hboNowVideoElement) {
const bottomHalf = const bottomHalf =
hboNowVideoElement.parentNode.parentNode.parentNode.parentNode hboNowVideoElement.parentNode.parentNode.parentNode.parentNode.parentNode.children[1];
.parentNode.children[1]; bottomHalf.children[0].id = 'hboUpperTitle';
bottomHalf.children[0].id = "hboUpperTitle"; bottomHalf.children[1].id = 'hboLowerTitle';
bottomHalf.children[1].id = "hboLowerTitle";
this.firstTimeSync(hboNowVideoElement); this.firstTimeSync(hboNowVideoElement);
} else { } else {
setInterval( setInterval(
this.video.element this.video.element
? null ? null
: () => { : () => {
var hve = document.querySelector( var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HBONOW]);
this.selectors[PLAYER_SOURCE.HBONOW]
);
if ( if (
hve !== null && hve !== null &&
hve !== undefined && hve !== undefined &&
@@ -571,12 +491,10 @@ export default class VideoListener {
const peacockInject = `var watchPartyInteraction=function(e){if(e.source===window){const data=JSON.parse(e.data);const playerReactElement=document.querySelector("${ const peacockInject = `var watchPartyInteraction=function(e){if(e.source===window){const data=JSON.parse(e.data);const playerReactElement=document.querySelector("${
this.selectors[PLAYER_SOURCE.PEACOCK] this.selectors[PLAYER_SOURCE.PEACOCK]
}");if(data.watchPartyDirection==='TO_SCRIPT'){if(data.type==='WATCH_PARTY_SEEK'){if(playerReactElement&&playerReactElement.player){playerReactElement.player.seek(data.time)}}else if(data.type==='WATCH_PARTY_STATUS'){if(playerReactElement&&playerReactElement.player){if(data.status==='PAUSED')playerReactElement.player.pause();if(data.status==='PLAYING')playerReactElement.player.play()}}}}};window.addEventListener("message",watchPartyInteraction);`; }");if(data.watchPartyDirection==='TO_SCRIPT'){if(data.type==='WATCH_PARTY_SEEK'){if(playerReactElement&&playerReactElement.player){playerReactElement.player.seek(data.time)}}else if(data.type==='WATCH_PARTY_STATUS'){if(playerReactElement&&playerReactElement.player){if(data.status==='PAUSED')playerReactElement.player.pause();if(data.status==='PLAYING')playerReactElement.player.play()}}}}};window.addEventListener("message",watchPartyInteraction);`;
const peacockInjectScript = document.createElement("script"); const peacockInjectScript = document.createElement('script');
peacockInjectScript.text = peacockInject; peacockInjectScript.text = peacockInject;
document.head.appendChild(peacockInjectScript); document.head.appendChild(peacockInjectScript);
const peacockVideoElement = document.querySelector( const peacockVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.PEACOCK]);
this.selectors[PLAYER_SOURCE.PEACOCK]
);
if (peacockVideoElement) { if (peacockVideoElement) {
this.firstTimeSync(peacockVideoElement); this.firstTimeSync(peacockVideoElement);
} else { } else {
@@ -584,9 +502,7 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var pve = document.querySelector( var pve = document.querySelector(this.selectors[PLAYER_SOURCE.PEACOCK]);
this.selectors[PLAYER_SOURCE.PEACOCK]
);
if ( if (
pve !== null && pve !== null &&
pve !== undefined && pve !== undefined &&
@@ -600,13 +516,9 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.GOOGLEPLAY: case PLAYER_SOURCE.GOOGLEPLAY:
const playerIframe = document.querySelector( const playerIframe = document.querySelector(this.selectors[PLAYER_SOURCE.GOOGLEPLAY]);
this.selectors[PLAYER_SOURCE.GOOGLEPLAY]
);
if (playerIframe) { if (playerIframe) {
const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector( const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector('video');
"video"
);
if (googlePlayVideoElement) { if (googlePlayVideoElement) {
this.firstTimeSync(googlePlayVideoElement); this.firstTimeSync(googlePlayVideoElement);
} }
@@ -615,13 +527,9 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
const pif = document.querySelector( const pif = document.querySelector(this.selectors[PLAYER_SOURCE.GOOGLEPLAY]);
this.selectors[PLAYER_SOURCE.GOOGLEPLAY]
);
if (pif) { if (pif) {
const gpve = pif.contentWindow.document.querySelector( const gpve = pif.contentWindow.document.querySelector('video');
"video"
);
if (gpve) { if (gpve) {
this.firstTimeSync(gpve); this.firstTimeSync(gpve);
} }
@@ -632,12 +540,10 @@ export default class VideoListener {
} }
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
const crunchyRollInject = `var sendToWatchPartyApp = function(pS, pT) { var customWatchPartyEvent = new CustomEvent('watchParty', { detail: { watchPartyDirection: 'TO_APP', type: 'WATCH_PARTY_PLAYER_UPDATE', status: pS, time: pT } }); window.dispatchEvent(customWatchPartyEvent); }, watchPartyGetTimeAndSend = function(pS) { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.getCurrentTime(function(pT) { sendToWatchPartyApp(pS, pT); }); } }, watchPartySendPlaying = function() { watchPartyGetTimeAndSend('PLAYING'); }, watchPartySendPaused = function() { watchPartyGetTimeAndSend('PAUSED'); }, watchPartyInteraction = function(e) { if (e.source === window) { const data = JSON.parse(e.data); if (data.watchPartyDirection === 'TO_SCRIPT') { if (data.type === 'WATCH_PARTY_ADD_LISTENERS') { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.on('play', watchPartySendPlaying, 'player.js'); window.VILOS_PLAYERJS.on('pause', watchPartySendPaused, 'player.js'); } } else if (data.type === 'WATCH_PARTY_SEEK') { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.setCurrentTime(data.time); } } else if (data.type === 'WATCH_PARTY_STATUS') { if (window.VILOS_PLAYERJS) { if (data.status === 'PAUSED') window.VILOS_PLAYERJS.pause(); if (data.status === 'PLAYING') window.VILOS_PLAYERJS.play(); } } } } }; window.addEventListener("message", watchPartyInteraction);`; const crunchyRollInject = `var sendToWatchPartyApp = function(pS, pT) { var customWatchPartyEvent = new CustomEvent('watchParty', { detail: { watchPartyDirection: 'TO_APP', type: 'WATCH_PARTY_PLAYER_UPDATE', status: pS, time: pT } }); window.dispatchEvent(customWatchPartyEvent); }, watchPartyGetTimeAndSend = function(pS) { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.getCurrentTime(function(pT) { sendToWatchPartyApp(pS, pT); }); } }, watchPartySendPlaying = function() { watchPartyGetTimeAndSend('PLAYING'); }, watchPartySendPaused = function() { watchPartyGetTimeAndSend('PAUSED'); }, watchPartyInteraction = function(e) { if (e.source === window) { const data = JSON.parse(e.data); if (data.watchPartyDirection === 'TO_SCRIPT') { if (data.type === 'WATCH_PARTY_ADD_LISTENERS') { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.on('play', watchPartySendPlaying, 'player.js'); window.VILOS_PLAYERJS.on('pause', watchPartySendPaused, 'player.js'); } } else if (data.type === 'WATCH_PARTY_SEEK') { if (window.VILOS_PLAYERJS) { window.VILOS_PLAYERJS.setCurrentTime(data.time); } } else if (data.type === 'WATCH_PARTY_STATUS') { if (window.VILOS_PLAYERJS) { if (data.status === 'PAUSED') window.VILOS_PLAYERJS.pause(); if (data.status === 'PLAYING') window.VILOS_PLAYERJS.play(); } } } } }; window.addEventListener("message", watchPartyInteraction);`;
const crunchyRollInjectScript = document.createElement("script"); const crunchyRollInjectScript = document.createElement('script');
crunchyRollInjectScript.text = crunchyRollInject; crunchyRollInjectScript.text = crunchyRollInject;
document.head.appendChild(crunchyRollInjectScript); document.head.appendChild(crunchyRollInjectScript);
const crunchyrollIframe = document.querySelector( const crunchyrollIframe = document.querySelector(this.selectors[PLAYER_SOURCE.CRUNCHYROLL]);
this.selectors[PLAYER_SOURCE.CRUNCHYROLL]
);
if (crunchyrollIframe) { if (crunchyrollIframe) {
this.firstTimeSync(crunchyrollIframe); this.firstTimeSync(crunchyrollIframe);
} else { } else {
@@ -645,9 +551,7 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
const cif = document.querySelector( const cif = document.querySelector(this.selectors[PLAYER_SOURCE.CRUNCHYROLL]);
this.selectors[PLAYER_SOURCE.CRUNCHYROLL]
);
if (cif) { if (cif) {
this.firstTimeSync(cif); this.firstTimeSync(cif);
} }
@@ -657,7 +561,7 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.LOCAL: case PLAYER_SOURCE.LOCAL:
const localVideoElement = document.getElementsByTagName("video")[0]; const localVideoElement = document.getElementsByTagName('video')[0];
if (localVideoElement) { if (localVideoElement) {
this.firstTimeSync(localVideoElement); this.firstTimeSync(localVideoElement);
} }
@@ -669,12 +573,12 @@ export default class VideoListener {
end() { end() {
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
window.removeEventListener("watchParty", this.crunchyRollListener); window.removeEventListener('watchParty', this.crunchyRollListener);
break; break;
default: default:
if (this.video.element) { if (this.video.element) {
this.video.element.removeEventListener("playing", this.onplay); this.video.element.removeEventListener('playing', this.onplay);
this.video.element.removeEventListener("pause", this.onpause); this.video.element.removeEventListener('pause', this.onpause);
} }
} }
} }
+2 -3
View File
@@ -110,8 +110,7 @@ body.youtube.visible .ytp-tooltip.ytp-bottom.ytp-preview {
bottom: 100px !important; bottom: 100px !important;
top: unset !important; top: unset !important;
} }
body.youtube.visible body.youtube.visible td-two-column-browse-results-renderer.grid:not(.grid-disabled) {
td-two-column-browse-results-renderer.grid:not(.grid-disabled) {
max-width: calc(100% - 48px); max-width: calc(100% - 48px);
} }
body.youtube.visible ytd-miniplayer { body.youtube.visible ytd-miniplayer {
@@ -311,7 +310,7 @@ body.disney #party_wrapper * {
border: 1px solid white; border: 1px solid white;
background-color: black !important; background-color: black !important;
transition: all ease-in-out 0.3s !important; transition: all ease-in-out 0.3s !important;
background-image: url("chrome-extension://__MSG_@@extension_id__/android-icon-192x192.png"); background-image: url('chrome-extension://__MSG_@@extension_id__/android-icon-192x192.png');
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 75%; background-size: 75%;
+18 -34
View File
@@ -1,48 +1,32 @@
const FunctionModules = require("./modules/index"); const FunctionModules = require('./modules/index');
const FunctionModules2 = require("./modules2/index"); const Webhooks = require('./webhooks/index');
const Webhooks = require("./webhooks/index"); const express = require('express');
const express = require("express"); const cors = require('cors');
const cors = require("cors");
// WEBHOOKS // WEBHOOKS
const webhooks = express(); const webhooks = express();
webhooks.use(cors({ origin: true })); webhooks.use(cors({ origin: true }));
webhooks.all("/conferenceEnded", Webhooks.conferenceEnd); webhooks.all('/conferenceEnded', Webhooks.conferenceEnd);
webhooks.all("/scheduledCleanup", Webhooks.scheduledCleanUp); webhooks.all('/scheduledCleanup', Webhooks.scheduledCleanUp);
webhooks.all("/ask", Webhooks.ask); webhooks.all('/ask', Webhooks.ask);
webhooks.all("/userCleanUp", Webhooks.userCleanUp); webhooks.all('/userCleanUp', Webhooks.userCleanUp);
// VERSION 1 // VERSION 1
const app = express(); const app = express();
app.use(cors({ origin: true })); app.use(cors({ origin: true }));
app.use(FunctionModules.authenticator); app.use(FunctionModules.authenticator);
app.get("/validator/:partyName", FunctionModules.tokenValidator); app.get('/validator/:partyName', FunctionModules.tokenValidator);
app.get("/refresher/:token", FunctionModules.tokenRefresher); app.get('/refresher/:token', FunctionModules.tokenRefresher);
app.post("/create", FunctionModules.createRoom); app.post('/create', FunctionModules.createRoom);
app.post("/join", FunctionModules.joinRoom); app.post('/join', FunctionModules.joinRoom);
app.post("/message", FunctionModules.sendMessage); app.post('/message', FunctionModules.sendMessage);
app.post("/updatePlayer", FunctionModules.updatePlayer); app.post('/updatePlayer', FunctionModules.updatePlayer);
app.post("/updateVoxeet", FunctionModules.updateVoxeet); app.post('/updateVoxeet', FunctionModules.updateVoxeet);
app.delete("/leave/:rid/users/:uid", FunctionModules.leaveRoom); app.delete('/leave/:rid/users/:uid', FunctionModules.leaveRoom);
app.delete("/delete/:rid", FunctionModules.deleteRoom); app.delete('/delete/:rid', FunctionModules.deleteRoom);
app.put("/updateAdminOnly/:rid/:adminOnly", FunctionModules.updateAdminOnly); app.put('/updateAdminOnly/:rid/:adminOnly', FunctionModules.updateAdminOnly);
// 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 = { module.exports = {
v1: app, v1: app,
v2: app2,
webhooks, webhooks,
}; };
-2
View File
@@ -12,7 +12,5 @@ admin.initializeApp(FIREBASE_OPTIONS);
// VERSION 1 // VERSION 1
exports.widgets = functions.https.onRequest(REST.v1); exports.widgets = functions.https.onRequest(REST.v1);
// VERSION 2
exports.widgets2 = functions.https.onRequest(REST.v2);
// WEBHOOKS // WEBHOOKS
exports.webhooks = functions.https.onRequest(REST.webhooks); exports.webhooks = functions.https.onRequest(REST.webhooks);
+20 -28
View File
@@ -1,62 +1,54 @@
const admin = require("firebase-admin"); const admin = require('firebase-admin');
const Logger = require("../Logger"); const Logger = require('../Logger');
const mLogger = new Logger("modules", "authenticator"); const mLogger = new Logger('modules', 'authenticator');
module.exports = (req, res, next) => { module.exports = (req, res, next) => {
mLogger.start(); mLogger.start();
res.set("Access-Control-Allow-Origin", ["*"]); res.set('Access-Control-Allow-Origin', ['*']);
if (req.method === "OPTIONS") { if (req.method === 'OPTIONS') {
mLogger.success("OPTIONS CALL", { URL: req.url }); mLogger.success('OPTIONS CALL', { URL: req.url });
res.status(200).send(); res.status(200).send();
return next(); return next();
} }
if (req.headers.authorization) { if (req.headers.authorization) {
try { try {
const token = req.headers.authorization.split(" ")[1]; const token = req.headers.authorization.split(' ')[1];
const reqToken = token.split(":")[0]; const reqToken = token.split(':')[0];
const reqUid = token.split(":")[1]; const reqUid = token.split(':')[1];
admin admin
.auth() .auth()
.verifyIdToken(reqToken) .verifyIdToken(reqToken)
.then((user) => { .then((user) => {
if (user.uid === reqUid) { if (user.uid === reqUid) {
if (req.method === "POST") { if (req.method === 'POST') {
const bodydata = JSON.parse(req.body); const bodydata = JSON.parse(req.body);
bodydata.uid = user.uid; bodydata.uid = user.uid;
req.body = JSON.stringify(bodydata); req.body = JSON.stringify(bodydata);
} }
if ( if (req.method === 'GET' || req.method === 'DELETE' || req.method === 'PUT') {
req.method === "GET" ||
req.method === "DELETE" ||
req.method === "PUT"
) {
req.body = JSON.stringify({ uid: user.uid }); req.body = JSON.stringify({ uid: user.uid });
} }
mLogger.success("AUTHORIZED", { URL: req.url, UID: reqUid }); mLogger.success('AUTHORIZED', { URL: req.url, UID: reqUid });
return next(); return next();
} else { } else {
mLogger.success("NOT AUTHORIZED", { URL: req.url }); mLogger.success('NOT AUTHORIZED', { URL: req.url });
return res.status(401).send({ message: "Unauthorized" }); return res.status(401).send({ message: 'Unauthorized' });
} }
}) })
.catch((err) => { .catch((err) => {
mLogger.error("AUTH VALIDATE FIREBASE ERROR", { mLogger.error('AUTH VALIDATE FIREBASE ERROR', {
URL: req.url, URL: req.url,
Error: err, Error: err,
}); });
return res return res.status(500).send({ message: 'Unable to verify user token' });
.status(500)
.send({ message: "Unable to verify user token" });
}); });
} catch (err) { } catch (err) {
mLogger.error("AUTH VALIDATE ERROR", { URL: req.url, Error: err }); mLogger.error('AUTH VALIDATE ERROR', { URL: req.url, Error: err });
return res return res.status(401).send({ message: 'Something went wrong when authorizing' });
.status(401)
.send({ message: "Something went wrong when authorizing" });
} }
} else { } else {
mLogger.error("NO AUTH TOKEN", { URL: req.url }); mLogger.error('NO AUTH TOKEN', { URL: req.url });
res.status(401).send({ message: "Got no user token" }); res.status(401).send({ message: 'Got no user token' });
} }
return 0; return 0;
}; };
+31 -45
View File
@@ -1,27 +1,21 @@
const admin = require("firebase-admin"); const admin = require('firebase-admin');
module.exports = async (req, res) => { module.exports = async (req, res) => {
const bodydata = JSON.parse(req.body); const bodydata = JSON.parse(req.body);
console.log("Requested Create - UID - ", bodydata.uid); console.log('Requested Create - UID - ', bodydata.uid);
if (!bodydata.userName) if (!bodydata.userName) res.status(400).send({ message: 'Missing user name' });
res.status(400).send({ message: "Missing user name" }); if (!bodydata.partyName) res.status(400).send({ message: 'Missing party name' });
if (!bodydata.partyName) if (!bodydata.partyPin) res.status(400).send({ message: 'Missing party pin' });
res.status(400).send({ message: "Missing party name" });
if (!bodydata.partyPin)
res.status(400).send({ message: "Missing party pin" });
const roomNameTaken = await admin const roomNameTaken = await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName.replace("/", "\\")) .doc(bodydata.partyName.replace('/', '\\'))
.get() .get()
.then((docSnap) => docSnap.exists); .then((docSnap) => docSnap.exists);
if (roomNameTaken) if (roomNameTaken) return res.status(409).send({ message: 'That party name is already taken' });
return res
.status(409)
.send({ message: "That party name is already taken" });
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.set({ .set({
name: bodydata.partyName, name: bodydata.partyName,
@@ -32,17 +26,17 @@ module.exports = async (req, res) => {
adminOnly: bodydata.adminOnly, adminOnly: bodydata.adminOnly,
}) })
.catch((err) => { .catch((err) => {
res.status(500).send({ message: "Unable to start party." }); res.status(500).send({ message: 'Unable to start party.' });
console.error(err); console.error(err);
}); });
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("messages") .collection('messages')
.add({ .add({
uid: "<system>", uid: '<system>',
name: "", name: '',
text: `${bodydata.userName} started the party.`, text: `${bodydata.userName} started the party.`,
time: new Date(), time: new Date(),
}) })
@@ -54,9 +48,9 @@ module.exports = async (req, res) => {
}); });
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("users") .collection('users')
.doc(bodydata.uid) .doc(bodydata.uid)
.set({ .set({
admin: true, admin: true,
@@ -68,47 +62,39 @@ module.exports = async (req, res) => {
err err
); );
}); });
if (bodydata.player && bodydata.player.source === "amazon.") { if (bodydata.player && bodydata.player.source === 'amazon.') {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("messages") .collection('messages')
.add({ .add({
uid: "<system>", uid: '<system>',
name: "Update to V1.6.1", name: 'Update to V1.6.1',
endpoint: "https://get.chromewatchparty.com", endpoint: 'https://get.chromewatchparty.com',
type: "interactive/link", type: 'interactive/link',
text: `If Watch Party doesn't work make sure you're on V1.6.1. Try removing and re-adding if an update option is not visible`, text: `If Watch Party doesn't work make sure you're on V1.6.1. Try removing and re-adding if an update option is not visible`,
time: new Date(), time: new Date(),
}) })
.catch((err) => { .catch((err) => {
console.error( console.error(`Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`, err);
`Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`,
err
);
}); });
} }
if (bodydata.player && bodydata.player.source === "hulu.") { if (bodydata.player && bodydata.player.source === 'hulu.') {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("messages") .collection('messages')
.add({ .add({
uid: "<system>", uid: '<system>',
name: "", name: '',
text: `Watch Party may not work temporarily. An update is coming to fix this.`, text: `Watch Party may not work temporarily. An update is coming to fix this.`,
time: new Date(), time: new Date(),
}) })
.catch((err) => { .catch((err) => {
console.error( console.error(`Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`, err);
`Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`,
err
);
}); });
} }
res res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' });
.status(201)
.send({ roomId: bodydata.partyName, message: "Started a party!" });
}; };
+26 -37
View File
@@ -1,24 +1,19 @@
const admin = require("firebase-admin"); const admin = require('firebase-admin');
module.exports = async (req, res) => { module.exports = async (req, res) => {
const bodydata = JSON.parse(req.body); const bodydata = JSON.parse(req.body);
console.log( console.log('Requested Join - UID - ', bodydata.uid, '\n\tRoom - ', bodydata.partyName);
"Requested Join - UID - ",
bodydata.uid,
"\n\tRoom - ",
bodydata.partyName
);
// GET ROOM EXISTS, ROOM SOURCE, & ROOM PIN // GET ROOM EXISTS, ROOM SOURCE, & ROOM PIN
const [exists, roomSource, roomPin, adminUid] = await admin const [exists, roomSource, roomPin, adminUid] = await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.get() .get()
.then((roomSnap) => [ .then((roomSnap) => [
roomSnap.exists, roomSnap.exists,
roomSnap.exists ? roomSnap.data().player.source : "", roomSnap.exists ? roomSnap.data().player.source : '',
roomSnap.exists ? roomSnap.data().pin : "", roomSnap.exists ? roomSnap.data().pin : '',
roomSnap.exists ? roomSnap.data().adminUid : "", roomSnap.exists ? roomSnap.data().adminUid : '',
]) ])
.catch((err) => { .catch((err) => {
console.error( console.error(
@@ -27,13 +22,13 @@ module.exports = async (req, res) => {
); );
}); });
if (exists && roomPin !== bodydata.partyPin) if (exists && roomPin !== bodydata.partyPin)
return res.status(401).send({ message: "Incorrect party pin" }); return res.status(401).send({ message: 'Incorrect party pin' });
if (adminUid === bodydata.uid) { if (adminUid === bodydata.uid) {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("users") .collection('users')
.doc(bodydata.uid) .doc(bodydata.uid)
.set({ .set({
admin: true, admin: true,
@@ -43,15 +38,15 @@ module.exports = async (req, res) => {
// GET IF USER EXISTS AND IS ADMIN // GET IF USER EXISTS AND IS ADMIN
const [userExists, userAdmin, userName] = await admin const [userExists, userAdmin, userName] = await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("users") .collection('users')
.doc(bodydata.uid) .doc(bodydata.uid)
.get() .get()
.then((userSnap) => [ .then((userSnap) => [
userSnap.exists, userSnap.exists,
userSnap.exists ? userSnap.data().admin : false, userSnap.exists ? userSnap.data().admin : false,
userSnap.exists ? userSnap.data().name : "", userSnap.exists ? userSnap.data().name : '',
]) ])
.catch((err) => { .catch((err) => {
console.error( console.error(
@@ -65,15 +60,13 @@ module.exports = async (req, res) => {
if (userName !== bodydata.userName) { if (userName !== bodydata.userName) {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("users") .collection('users')
.doc(bodydata.uid) .doc(bodydata.uid)
.update({ name: bodydata.userName }); .update({ name: bodydata.userName });
} }
res res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' });
.status(200)
.send({ partyName: bodydata.partyName, message: "Joined a party" });
} }
// USER DOES NOT PRE-EXIST BUT SAME SOURCE AND RIGHT PIN // USER DOES NOT PRE-EXIST BUT SAME SOURCE AND RIGHT PIN
else if ( else if (
@@ -86,12 +79,12 @@ module.exports = async (req, res) => {
) { ) {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("messages") .collection('messages')
.add({ .add({
uid: "<system>", uid: '<system>',
name: "", name: '',
text: `${bodydata.userName} joined the party.`, text: `${bodydata.userName} joined the party.`,
time: new Date(), time: new Date(),
}) })
@@ -103,9 +96,9 @@ module.exports = async (req, res) => {
}); });
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.collection("users") .collection('users')
.doc(bodydata.uid) .doc(bodydata.uid)
.set({ .set({
admin: false, admin: false,
@@ -117,9 +110,7 @@ module.exports = async (req, res) => {
err err
); );
}); });
res res.status(200).send({ partyName: bodydata.partyName, message: 'Joined a party' });
.status(200)
.send({ partyName: bodydata.partyName, message: "Joined a party" });
} }
// ONLY WRONG SOURCE // ONLY WRONG SOURCE
else if (exists && roomSource !== bodydata.source) { else if (exists && roomSource !== bodydata.source) {
@@ -127,13 +118,13 @@ module.exports = async (req, res) => {
if (userAdmin === true) { if (userAdmin === true) {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(bodydata.partyName) .doc(bodydata.partyName)
.update({ .update({
player: { player: {
showName: null, showName: null,
source: bodydata.source, source: bodydata.source,
status: "NOT_PLAYING", status: 'NOT_PLAYING',
time: 0, time: 0,
updatedBy: bodydata.uid, updatedBy: bodydata.uid,
}, },
@@ -142,11 +133,9 @@ module.exports = async (req, res) => {
console.error( console.error(
`Failed to update player source when admin joining party \n\t Room: ${partyName} \n\t User: ${bodydata.uid}` `Failed to update player source when admin joining party \n\t Room: ${partyName} \n\t User: ${bodydata.uid}`
); );
res res.status(500).send({ message: 'Unable to move party, please try again' });
.status(500)
.send({ message: "Unable to move party, please try again" });
}); });
res.status(200).send({ message: `Moved party to ${roomSource}` }); res.status(200).send({ message: `Moved party to ${roomSource}` });
} else res.status(417).send({ message: `This party is on ${roomSource}` }); } else res.status(417).send({ message: `This party is on ${roomSource}` });
} else res.status(404).send({ message: "Party Not Found" }); } else res.status(404).send({ message: 'Party Not Found' });
}; };
+10 -15
View File
@@ -1,39 +1,34 @@
const admin = require("firebase-admin"); const admin = require('firebase-admin');
module.exports = async (req, res) => { module.exports = async (req, res) => {
const { name, text, uid, roomId, type, replyTo } = JSON.parse(req.body); const { name, text, uid, roomId, type, replyTo } = JSON.parse(req.body);
const roomExists = await admin const roomExists = await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(roomId) .doc(roomId)
.get() .get()
.then((roomSnap) => roomSnap.exists); .then((roomSnap) => roomSnap.exists);
if (roomExists) { if (roomExists) {
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(roomId) .doc(roomId)
.collection("messages") .collection('messages')
.add({ .add({
name, name,
text: text || "", text: text || '',
time: new Date(), time: new Date(),
uid, uid,
type: type || "", type: type || '',
replyTo: replyTo || null, replyTo: replyTo || null,
}) })
.catch((err) => { .catch((err) => {
console.error( console.error(`Failed to send message to party : \n\t Room: ${roomId} \n\t ${uid}`, err);
`Failed to send message to party : \n\t Room: ${roomId} \n\t ${uid}`, res.status(500).send({ message: "Couldn't send your message", error: messageErr });
err
);
res
.status(500)
.send({ message: "Couldn't send your message", error: messageErr });
}); });
res.status(200).send({ message: "Sent a message" }); res.status(200).send({ message: 'Sent a message' });
} else { } else {
res.status(404).send({ message: "Looks like this party is over" }); res.status(404).send({ message: 'Looks like this party is over' });
} }
}; };
+7 -10
View File
@@ -17,15 +17,16 @@ module.exports = async (req, res) => {
body: JSON.stringify({ body: JSON.stringify({
grant_type: 'client_credentials', grant_type: 'client_credentials',
}), }),
}).then((oauthResponse) => oauthResponse.json()) })
.catch((err) => res.status(500).send({err, message: 'Unable to generate token for call'})); .then((oauthResponse) => oauthResponse.json())
.catch((err) => res.status(500).send({ err, message: 'Unable to generate token for call' }));
const [exists, conferencePending, conference, adminOnly, adminUid] = await admin const [exists, conferencePending, conference, adminOnly, adminUid] = await admin
.firestore() .firestore()
.collection('rooms') .collection('rooms')
.doc(req.params.partyName) .doc(req.params.partyName)
.get() .get()
.then(snap => { .then((snap) => {
const data = snap.exists ? snap.data() : {}; const data = snap.exists ? snap.data() : {};
return [snap.exists, data.conferencePending, data.conference, data.adminOnly, data.adminUid]; return [snap.exists, data.conferencePending, data.conference, data.adminOnly, data.adminUid];
}); });
@@ -33,13 +34,9 @@ module.exports = async (req, res) => {
if (exists === true) { if (exists === true) {
if (conference === undefined || conference === null) { if (conference === undefined || conference === null) {
if (conferencePending === undefined || conferencePending === null) { if (conferencePending === undefined || conferencePending === null) {
if (!adminOnly || (adminOnly && (adminUid === bodyData.uid)) ) { if (!adminOnly || (adminOnly && adminUid === bodyData.uid)) {
await admin await admin.firestore().collection('rooms').doc(req.params.partyName).update({
.firestore() conferencePending: bodyData.uid,
.collection('rooms')
.doc(req.params.partyName)
.update({
conferencePending: bodyData.uid
}); });
await admin await admin
.firestore() .firestore()
+8 -3
View File
@@ -25,9 +25,14 @@ module.exports = async (req, res) => {
return; return;
} }
const adminOnly = req.params.adminOnly === 'true'; const adminOnly = req.params.adminOnly === 'true';
await admin.firestore().collection('rooms').doc(req.params.rid).update({ await admin
adminOnly .firestore()
}).catch((err) => { .collection('rooms')
.doc(req.params.rid)
.update({
adminOnly,
})
.catch((err) => {
console.err('Failed to update adminOnly for party', err); console.err('Failed to update adminOnly for party', err);
res.status(409).send({ message: 'Failed to update party.' }); res.status(409).send({ message: 'Failed to update party.' });
}); });
+18 -29
View File
@@ -1,23 +1,16 @@
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( const { conference, partyName, partyPin, userName, uid } = JSON.parse(req.body);
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 [ return [roomSnap.exists, data.pin, data.conferencePending, data.conference];
roomSnap.exists,
data.pin,
data.conferencePending,
data.conference,
];
}); });
// CHECK IF ROOM EXISTS // CHECK IF ROOM EXISTS
if (exists === true) { if (exists === true) {
@@ -29,61 +22,57 @@ 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({ res.status(500).send({
message: "Unable to update the call details", message: 'Unable to update the call details',
error: err, error: err,
}) })
); );
// REMOVE PENDING STATUS // REMOVE PENDING STATUS
await admin await admin
.firestore() .firestore()
.collection("rooms") .collection('rooms')
.doc(partyName) .doc(partyName)
.update({ .update({
conferencePending: admin.firestore.FieldValue.delete(), conferencePending: admin.firestore.FieldValue.delete(),
}) })
.catch((err) => .catch((err) => console.error('Failed to remove pending status', 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) => .catch((err) => console.error('Failed to add update conference message', err));
console.error("Failed to add update conference message", err) res.status(200).send({ message: 'Started the conference' });
);
res.status(200).send({ message: "Started the conference" });
} else { } else {
res.status(409).send({ res.status(409).send({
message: "Looks like someone is already starting a call", message: 'Looks like someone is already starting a call',
}); });
} }
} else if (partyConference) { } else if (partyConference) {
res.status(409).send({ res.status(409).send({
message: "Call already exists", message: 'Call already exists',
conference: partyConference, 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;
}; };
-42
View File
@@ -1,42 +0,0 @@
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' });
};
-32
View File
@@ -1,32 +0,0 @@
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);
});
};
-87
View File
@@ -1,87 +0,0 @@
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: "<system>",
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
);
});
admin
.firestore()
.collection("rooms")
.doc(bodydata.partyName)
.collection("messages")
.add({
uid: "<system>",
name: "",
text: `Big update coming on Monday (Aug. 10). Watch Party will be unavailable during the afternoon as we upgrade our services. See what's new at whatsnew.chromewatchparty.com`,
time: new Date(),
});
res
.status(201)
.send({ roomId: bodydata.partyName, message: "Started a party!" });
};
-62
View File
@@ -1,62 +0,0 @@
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' });
};
-29
View File
@@ -1,29 +0,0 @@
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,
};
-154
View File
@@ -1,154 +0,0 @@
const admin = 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: '<system>',
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: bodydata.source,
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' });
};
-19
View File
@@ -1,19 +0,0 @@
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' });
};
-48
View File
@@ -1,48 +0,0 @@
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
);
});
});
};
-46
View File
@@ -1,46 +0,0 @@
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' });
}
};
-7
View File
@@ -1,7 +0,0 @@
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));
};
-20
View File
@@ -1,20 +0,0 @@
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);
};
-21
View File
@@ -1,21 +0,0 @@
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);
};
-85
View File
@@ -1,85 +0,0 @@
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);
if (!roomId) return res.status(204).send({ message: 'Party name not sent.' });
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 && player.showName) {
if (player.showName !== roomData.player.showName) {
await admin
.firestore()
.collection('rooms')
.doc(roomId)
.collection('messages')
.add({
uid: '<system>',
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: '<system>',
// 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' });
}
};
-47
View File
@@ -1,47 +0,0 @@
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: '<system>',
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' });
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "watch-party-api", "name": "watch-party-api",
"version": "1.6.1", "version": "1.6.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {