diff --git a/app/src/App.js b/app/src/App.js index d39a0b4..d3fb57c 100644 --- a/app/src/App.js +++ b/app/src/App.js @@ -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 COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION. ************************************************************************/ -import React, { useState, useEffect } from "react"; -import Router from "route-lite"; -import { - Fab, - createMuiTheme, - ThemeProvider, - Snackbar, - Tooltip, -} from "@material-ui/core"; -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"; +import React, { useState, useEffect } from 'react'; +import Router from 'route-lite'; +import { Fab, createMuiTheme, ThemeProvider, Snackbar, Tooltip } from '@material-ui/core'; +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.1"; -const APP_VERSION_STRING = APP_VERSION.replace(/\./g, ""); +const APP_VERSION = '1.6.1'; +const APP_VERSION_STRING = APP_VERSION.replace(/\./g, ''); const darkTheme = createMuiTheme({ palette: { - type: "dark", + type: 'dark', primary: { - main: "#FF0000", + main: '#FF0000', }, secondary: { - main: "#c0f300", + main: '#c0f300', }, }, }); @@ -48,41 +42,32 @@ const Routes = (props) => ( const resetResize = () => { const checkedX = 400; - document.documentElement.style.setProperty("--party-width", `${checkedX}px`); - 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 doResize = (ev) => { const checkedX = window.innerWidth - - Math.min( - window.innerWidth - 300, - Math.max(window.innerWidth * 0.5, ev.clientX) - ); - document.documentElement.style.setProperty("--party-width", `${checkedX}px`); - document.documentElement.style.setProperty( - "--neg-party-width", - `-${checkedX}px` - ); + Math.min(window.innerWidth - 300, Math.max(window.innerWidth * 0.5, ev.clientX)); + document.documentElement.style.setProperty('--party-width', `${checkedX}px`); + document.documentElement.style.setProperty('--neg-party-width', `-${checkedX}px`); }; const stopResize = (ev) => { - document.documentElement.removeEventListener("mousemove", doResize, false); - document.documentElement.removeEventListener("mouseup", stopResize, false); + document.documentElement.removeEventListener('mousemove', doResize, false); + document.documentElement.removeEventListener('mouseup', stopResize, false); }; const startResize = (ev) => { - document.documentElement.addEventListener("mousemove", doResize, false); - document.documentElement.addEventListener("mouseup", stopResize, false); + document.documentElement.addEventListener('mousemove', doResize, false); + document.documentElement.addEventListener('mouseup', stopResize, false); }; 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 [loading, setLoading] = useState(false); const [notification, setNotification] = useState(closedNotification); @@ -94,8 +79,8 @@ const App = () => { getUserUid(); firebase .firestore() - .collection("server") - .doc("status") + .collection('server') + .doc('status') .onSnapshot((statusSnap) => { setStatus(statusSnap.data()); setLoading(false); @@ -103,19 +88,18 @@ const App = () => { }, []); // HANDLE VISIBILITY STYLING - const PartyRoutesWrapper = document.getElementById("party-routes-wrapper"); + const PartyRoutesWrapper = document.getElementById('party-routes-wrapper'); if (visible) { - document.body.classList.add("visible"); - PartyRoutesWrapper && PartyRoutesWrapper.classList.add("visible"); + document.body.classList.add('visible'); + PartyRoutesWrapper && PartyRoutesWrapper.classList.add('visible'); if ( !hasAttached && - (getPlayerSource() === PLAYER_SOURCE.HBOMAX || - getPlayerSource() === PLAYER_SOURCE.HBONOW) + (getPlayerSource() === PLAYER_SOURCE.HBOMAX || getPlayerSource() === PLAYER_SOURCE.HBONOW) ) { document.addEventListener( - "mousedown", + 'mousedown', function (ev) { - if (document.body.querySelector("body.visible")) { + if (document.body.querySelector('body.visible')) { ev.preventDefault(); ev.stopPropagation(); ev.stopImmediatePropagation(); @@ -126,8 +110,8 @@ const App = () => { hasAttached = true; } } else { - document.body.classList.remove("visible"); - PartyRoutesWrapper && PartyRoutesWrapper.classList.remove("visible"); + document.body.classList.remove('visible'); + PartyRoutesWrapper && PartyRoutesWrapper.classList.remove('visible'); } // HANDLE FULLSCREEN EVENT @@ -139,7 +123,7 @@ const App = () => { setNotification(closedNotification)} message={notification.message} @@ -152,23 +136,19 @@ const App = () => { title="Resize Sidebar / Double Click To Reset" aria-label="Resize Sidebar / Double Click To Reset" > -
+
||
{loading && } - {status[APP_VERSION_STRING] && - status[APP_VERSION_STRING].active === true ? ( + {status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? ( setNotification({ open: true, message })} appVersion={APP_VERSION} appVersionString={APP_VERSION_STRING} status={status[APP_VERSION_STRING]} + selectors={status.selectors} /> ) : ( console.log("MISSING VIDEO LISTENER"); +const templateListener = (video) => console.log('MISSING VIDEO LISTENER'); export default class VideoListener { - constructor(listener = templateListener) { + constructor(listener = templateListener, selectors) { this.video = { status: PLAYER_STATUS.NOT_PLAYING, time: 0, - showName: "", - source: "", + showName: '', + source: '', element: null, }; + this.selectors = selectors; this.isUpdating = false; this.listener = listener; this.updateStatus = this.updateStatus.bind(this); @@ -46,7 +42,7 @@ export default class VideoListener { this.video.element !== null && this.video.element !== undefined && this.video.status !== PLAYER_STATUS.NOT_PLAYING && - this.video.showName !== "" && + this.video.showName !== '' && this.video.showName !== null && (this.video.status !== this.server.status || Math.abs(this.video.element.currentTime - this.server.time) > 1.5) @@ -73,30 +69,23 @@ export default class VideoListener { // REMOVE LISTENER BEFORE SYNCING switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: - window.removeEventListener("watchParty", this.crunchyRollListener); + window.removeEventListener('watchParty', this.crunchyRollListener); default: - this.video.element.removeEventListener("playing", this.onplay); - this.video.element.removeEventListener("pause", this.onpause); + this.video.element.removeEventListener('playing', this.onplay); + this.video.element.removeEventListener('pause', this.onpause); } await this.timeout(250); // SEEK - if ( - Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5 - ) { + if (Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5) { switch (serverPlayer.source) { case PLAYER_SOURCE.NETFLIX: - window.postMessage( - { type: "SEEK", time: serverPlayer.time * 1000 }, - "*" - ); + window.postMessage({ type: 'SEEK', time: serverPlayer.time * 1000 }, '*'); break; case PLAYER_SOURCE.AMAZON: if (this.video.status === PLAYER_STATUS.PAUSED) await this.video.element .play() - .catch((err) => - console.error("WatchParty erred when syncing time.") - ); + .catch((err) => console.error('WatchParty erred when syncing time.')); await this.timeout(250); this.video.element.currentTime = serverPlayer.time; await this.timeout(500); @@ -109,10 +98,7 @@ export default class VideoListener { this.video.element.currentTime = serverPlayer.time; break; case PLAYER_SOURCE.HULU: - window.postMessage( - { type: "SEEK", time: serverPlayer.time }, - "*" - ); + window.postMessage({ type: 'SEEK', time: serverPlayer.time }, '*'); break; case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBONOW: @@ -121,8 +107,8 @@ export default class VideoListener { case PLAYER_SOURCE.PEACOCK: window.postMessage( JSON.stringify({ - watchPartyDirection: "TO_SCRIPT", - type: "WATCH_PARTY_SEEK", + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_SEEK', status: serverPlayer.status, time: serverPlayer.time, }) @@ -134,8 +120,8 @@ export default class VideoListener { case PLAYER_SOURCE.CRUNCHYROLL: window.postMessage( JSON.stringify({ - watchPartyDirection: "TO_SCRIPT", - type: "WATCH_PARTY_SEEK", + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_SEEK', status: serverPlayer.status, time: serverPlayer.time, }) @@ -154,18 +140,15 @@ export default class VideoListener { PLAYER_SOURCE.HBOMAX === this.video.source || PLAYER_SOURCE.HBONOW === this.video.source ) { - window.postMessage( - { type: "PAUSE", time: serverPlayer.time }, - "*" - ); + window.postMessage({ type: 'PAUSE', time: serverPlayer.time }, '*'); } else if ( PLAYER_SOURCE.CRUNCHYROLL === this.video.source || PLAYER_SOURCE.PEACOCK === this.video.source ) { window.postMessage( JSON.stringify({ - watchPartyDirection: "TO_SCRIPT", - type: "WATCH_PARTY_STATUS", + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_STATUS', status: serverPlayer.status, time: serverPlayer.time, }) @@ -181,18 +164,15 @@ export default class VideoListener { PLAYER_SOURCE.HBOMAX === this.video.source || PLAYER_SOURCE.HBONOW === this.video.source ) { - window.postMessage( - { type: "PLAY", time: serverPlayer.time }, - "*" - ); + window.postMessage({ type: 'PLAY', time: serverPlayer.time }, '*'); } else if ( PLAYER_SOURCE.CRUNCHYROLL === this.video.source || PLAYER_SOURCE.PEACOCK === this.video.source ) { window.postMessage( JSON.stringify({ - watchPartyDirection: "TO_SCRIPT", - type: "WATCH_PARTY_STATUS", + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_STATUS', status: serverPlayer.status, time: serverPlayer.time, }) @@ -200,9 +180,7 @@ export default class VideoListener { } else { await this.video.element .play() - .catch((err) => - console.error("WatchParty erred when syncing play.") - ); + .catch((err) => console.error('WatchParty erred when syncing play.')); } break; default: @@ -212,10 +190,10 @@ export default class VideoListener { // RE-ADD LISTENERS FOR FUTURE SYNC switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: - window.addEventListener("watchParty", this.crunchyRollListener); + window.addEventListener('watchParty', this.crunchyRollListener); default: - this.video.element.addEventListener("playing", this.onplay); - this.video.element.addEventListener("pause", this.onpause); + this.video.element.addEventListener('playing', this.onplay); + this.video.element.addEventListener('pause', this.onpause); } } this.isUpdating = false; @@ -231,89 +209,74 @@ export default class VideoListener { switch (this.video.source) { case PLAYER_SOURCE.NETFLIX: const titleContainerParent = document.querySelector( - ".PlayerControls--control-element.text-control.video-title" + '.PlayerControls--control-element.text-control.video-title' ); if (titleContainerParent) { const titleContainer = titleContainerParent.firstChild; - const nshow = titleContainer.querySelector("h4") - ? titleContainer.querySelector("h4").innerHTML + const nshow = titleContainer.querySelector('h4') + ? titleContainer.querySelector('h4').innerHTML : titleContainer.innerHTML; - let nepisode = ""; - titleContainer.querySelectorAll("span").forEach((e) => { - if (e.innerHTML) nepisode += e.innerHTML + " "; + let nepisode = ''; + titleContainer.querySelectorAll('span').forEach((e) => { + if (e.innerHTML) nepisode += e.innerHTML + ' '; }); - return nshow === "" && nepisode === "" - ? null - : nshow + "\n" + nepisode; + return nshow === '' && nepisode === '' ? null : nshow + '\n' + nepisode; } break; case PLAYER_SOURCE.AMAZON: const ashow = document.querySelector( - "#dv-web-player > div > div:nth-child(1) > div > div > div.webPlayerSDKUiContainer > div > div > div > div > div > div > div > div:nth-child(2) > div:nth-child(2)" - ).innerText || ""; - return ashow === "" ? null : ashow; + '#dv-web-player > div > div:nth-child(1) > div > div > div.webPlayerSDKUiContainer > div > div > div > div > div > div > div > div:nth-child(2) > div:nth-child(2)' + ).innerText || ''; + return ashow === '' ? null : ashow; case PLAYER_SOURCE.HULU: - const hshow = document.querySelector(".metadata-area__second-line") - .innerHTML; - const hepisode = document.querySelector(".metadata-area__third-line") - .innerHTML; - return hshow === "" && hepisode === "" ? null : hshow + "\n" + hepisode; + const hshow = document.querySelector('.metadata-area__second-line').innerHTML; + const hepisode = document.querySelector('.metadata-area__third-line').innerHTML; + return hshow === '' && hepisode === '' ? null : hshow + '\n' + hepisode; case PLAYER_SOURCE.DISNEY: this.video.element.parentElement.click(); await this.timeout(200); - const dshow = document.querySelector(".title-field") - ? document.querySelector(".title-field").innerHTML - : ""; - const depisode = document.querySelector(".subtitle-field") - ? document.querySelector(".subtitle-field").innerHTML - : ""; - return dshow === "" && depisode === "" ? null : dshow + "\n" + depisode; + const dshow = document.querySelector('.title-field') + ? document.querySelector('.title-field').innerHTML + : ''; + const depisode = document.querySelector('.subtitle-field') + ? document.querySelector('.subtitle-field').innerHTML + : ''; + return dshow === '' && depisode === '' ? null : dshow + '\n' + depisode; case PLAYER_SOURCE.YOUTUBE: - const yshow = document.querySelector("h1.title").innerText; - const yepisode = document.querySelector( - "yt-formatted-string.super-title" - ).innerText; - return yshow === "" && yepisode === "" ? null : yshow + "\n" + yepisode; + const yshow = document.querySelector('h1.title').innerText; + const yepisode = document.querySelector('yt-formatted-string.super-title').innerText; + return yshow === '' && yepisode === '' ? null : yshow + '\n' + yepisode; case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBONOW: - const bottomHalf = this.video.element.parentNode.parentNode.parentNode - .parentNode.parentNode.children[1]; - bottomHalf.children[0].id = "hboUpperTitle"; - bottomHalf.children[1].id = "hboLowerTitle"; - const hboshow = document.querySelector("#hboUpperTitle").innerText; - const hboepisode = document.querySelector("#hboLowerTitle").innerText; - return hboshow === "" && hboepisode === "" - ? null - : hboshow + "\n" + hboepisode; + const bottomHalf = this.video.element.parentNode.parentNode.parentNode.parentNode.parentNode + .children[1]; + bottomHalf.children[0].id = 'hboUpperTitle'; + bottomHalf.children[1].id = 'hboLowerTitle'; + const hboshow = document.querySelector('#hboUpperTitle').innerText; + const hboepisode = document.querySelector('#hboLowerTitle').innerText; + return hboshow === '' && hboepisode === '' ? null : hboshow + '\n' + hboepisode; case PLAYER_SOURCE.PEACOCK: const peacockshow = document.querySelector( - ".item.playback-metadata__container-episode-metadata-info" + '.item.playback-metadata__container-episode-metadata-info' ).innerText; - const peacockepisode = document.querySelector( - ".item.playback-metadata__container-title" - ).innerText; - return peacockshow === "" && peacockepisode === "" + const peacockepisode = document.querySelector('.item.playback-metadata__container-title') + .innerText; + return peacockshow === '' && peacockepisode === '' ? null - : peacockshow + "\n" + peacockepisode; + : peacockshow + '\n' + peacockepisode; case PLAYER_SOURCE.GOOGLEPLAY: - const playerIframe = document.querySelector("body span div iframe"); - var googleplayshow = ""; + const playerIframe = document.querySelector('body span div iframe'); + var googleplayshow = ''; if (playerIframe) { - const titleElement = playerIframe.contentWindow.document.querySelector( - ".playing-title" - ); - googleplayshow = titleElement ? titleElement.innerText : ""; + const titleElement = playerIframe.contentWindow.document.querySelector('.playing-title'); + googleplayshow = titleElement ? titleElement.innerText : ''; } - return googleplayshow === "" ? null : googleplayshow; + return googleplayshow === '' ? null : googleplayshow; case PLAYER_SOURCE.CRUNCHYROLL: - const crunchyrollTitle = document.querySelector( - "#showmedia_about_media" - ); - const crunchyrollshow = crunchyrollTitle - ? crunchyrollTitle.innerText - : ""; - return crunchyrollshow === "" ? null : crunchyrollshow; + const crunchyrollTitle = document.querySelector('#showmedia_about_media'); + const crunchyrollshow = crunchyrollTitle ? crunchyrollTitle.innerText : ''; + return crunchyrollshow === '' ? null : crunchyrollshow; default: break; } @@ -334,8 +297,8 @@ export default class VideoListener { } async crunchyRollListener(ev) { if ( - ev.detail.watchPartyDirection === "TO_APP" && - ev.detail.type === "WATCH_PARTY_PLAYER_UPDATE" + ev.detail.watchPartyDirection === 'TO_APP' && + ev.detail.type === 'WATCH_PARTY_PLAYER_UPDATE' ) { this.updateStatus({ status: ev.detail.status, @@ -355,15 +318,15 @@ export default class VideoListener { case PLAYER_SOURCE.CRUNCHYROLL: window.postMessage( JSON.stringify({ - watchPartyDirection: "TO_SCRIPT", - type: "WATCH_PARTY_ADD_LISTENERS", + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_ADD_LISTENERS', }) ); - window.addEventListener("watchParty", this.crunchyRollListener); + window.addEventListener('watchParty', this.crunchyRollListener); break; default: - videoElement.addEventListener("playing", this.onplay); - videoElement.addEventListener("pause", this.onpause); + videoElement.addEventListener('playing', this.onplay); + videoElement.addEventListener('pause', this.onpause); } } async start() { @@ -374,50 +337,19 @@ export default class VideoListener { switch (this.video.source) { 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 seekInjectScript = document.createElement("script"); + const seekInjectScript = document.createElement('script'); seekInjectScript.text = seekInject; document.head.appendChild(seekInjectScript); - if (document.getElementsByClassName("AkiraPlayer")[0]) { - const videoElement = document - .getElementsByClassName("AkiraPlayer")[0] - .getElementsByTagName("video")[0]; - if (videoElement && !this.video.element) { - this.firstTimeSync(videoElement); - } else { - setInterval( - this.video.element - ? null - : () => { - var nve = document.getElementsByClassName("AkiraPlayer")[0] - ? document - .getElementsByClassName("AkiraPlayer")[0] - .getElementsByTagName("video")[0] - : null; - if ( - nve !== null && - (this.video.element !== nve || - this.video.element === null) - ) { - this.firstTimeSync(nve); - } - }, - 1000 - ); - } + const videoElement = document.querySelector(this.selectors[PLAYER_SOURCE.NETFLIX]); + if (videoElement && !this.video.element) { + this.firstTimeSync(videoElement); } else { setInterval( this.video.element ? null : () => { - var nve = document.getElementsByClassName("AkiraPlayer")[0] - ? document - .getElementsByClassName("AkiraPlayer")[0] - .getElementsByTagName("video")[0] - : null; - if ( - nve !== null && - (this.video.element !== nve || this.video.element === null) - ) { + var nve = document.querySelector(this.selectors[PLAYER_SOURCE.NETFLIX]); + if (nve !== null && (this.video.element !== nve || this.video.element === null)) { this.firstTimeSync(nve); } }, @@ -426,13 +358,13 @@ export default class VideoListener { } break; case PLAYER_SOURCE.HULU: - const huluSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.getElementsByClassName('content-video-player')[0].__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 huluSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ + 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);`; + const huluSeekInjectScript = document.createElement('script'); huluSeekInjectScript.text = huluSeekInject; document.head.appendChild(huluSeekInjectScript); - const videoElement = document.getElementsByClassName( - "content-video-player" - )[0]; + const videoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HULU]); if (videoElement) { this.firstTimeSync(videoElement); } else { @@ -440,11 +372,91 @@ export default class VideoListener { this.video.element ? null : () => { - var hve = document.getElementsByClassName( - "content-video-player" - )[0]; + var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HULU]); + if (hve !== null && (this.video.element !== hve || this.video.element === null)) { + this.firstTimeSync(hve); + } + }, + 1000 + ); + } + break; + case PLAYER_SOURCE.AMAZON: + const videoElement = document.querySelector(this.selectors[PLAYER_SOURCE.AMAZON]); + if (videoElement) { + this.firstTimeSync(videoElement); + } else { + setInterval( + this.video.element + ? null + : () => { + var ave = document.querySelector(this.selectors[PLAYER_SOURCE.AMAZON]); + if (ave !== null && (this.video.element !== ave || this.video.element === null)) { + this.firstTimeSync(ave); + } + }, + 1000 + ); + } + break; + case PLAYER_SOURCE.DISNEY: + const disneyVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.DISNEY]); + if (disneyVideoElement) { + this.firstTimeSync(disneyVideoElement); + } else { + setInterval( + this.video.element + ? null + : () => { + var dve = document.querySelector(this.selectors[PLAYER_SOURCE.DISNEY]); + if (dve !== null && (this.video.element !== dve || this.video.element === null)) { + this.firstTimeSync(dve); + } + }, + 1000 + ); + } + break; + case PLAYER_SOURCE.YOUTUBE: + const youtubeVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.YOUTUBE]); + if (youtubeVideoElement) this.firstTimeSync(youtubeVideoElement); + else { + setInterval( + this.video.element + ? null + : () => { + var yve = document.querySelector(this.selectors[PLAYER_SOURCE.YOUTUBE]); + if (yve !== null && (this.video.element !== yve || this.video.element === null)) { + this.firstTimeSync(yve); + } + }, + 1000 + ); + } + break; + case PLAYER_SOURCE.HBOMAX: + const hboSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ + 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);`; + const hboSeekInjectScript = document.createElement('script'); + hboSeekInjectScript.text = hboSeekInject; + document.head.appendChild(hboSeekInjectScript); + const hboVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HBOMAX]); + if (hboVideoElement) { + const bottomHalf = + hboVideoElement.parentNode.parentNode.parentNode.parentNode.parentNode.children[1]; + bottomHalf.children[0].id = 'hboUpperTitle'; + bottomHalf.children[1].id = 'hboLowerTitle'; + this.firstTimeSync(hboVideoElement); + } else { + setInterval( + this.video.element + ? null + : () => { + var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HBOMAX]); if ( hve !== null && + hve !== undefined && (this.video.element !== hve || this.video.element === null) ) { this.firstTimeSync(hve); @@ -454,120 +466,26 @@ export default class VideoListener { ); } break; - case PLAYER_SOURCE.AMAZON: - if (document.querySelector("webPlayerSDKContainer")) { - const videoElement = document.querySelector( - ".webPlayerSDKContainer video" - ); - if (videoElement) { - this.firstTimeSync(videoElement); - } else { - setInterval( - this.video.element - ? null - : () => { - var ave = document.querySelector( - ".webPlayerSDKContainer video" - ); - if ( - ave !== null && - (this.video.element !== ave || - this.video.element === null) - ) { - this.firstTimeSync(ave); - } - }, - 1000 - ); - } - } else { - setInterval( - this.video.element - ? null - : () => { - var ave = document - .getElementsByClassName("webPlayerSDKContainer")[0] - .getElementsByTagName("video")[0]; - if ( - ave !== null && - (this.video.element !== ave || this.video.element === null) - ) { - this.firstTimeSync(ave); - } - }, - 1000 - ); - } - break; - case PLAYER_SOURCE.DISNEY: - const disneyVideoElement = document.querySelector( - "video.btm-media-client-element" - ); - if (disneyVideoElement) { - this.firstTimeSync(disneyVideoElement); - } else { - setInterval( - this.video.element - ? null - : () => { - var dve = document.querySelector( - "video.btm-media-client-element" - ); - if ( - dve !== null && - (this.video.element !== dve || this.video.element === null) - ) { - this.firstTimeSync(dve); - } - }, - 1000 - ); - } - break; - case PLAYER_SOURCE.YOUTUBE: - const youtubeVideoElement = document.querySelector( - "video.video-stream.html5-main-video" - ); - if (youtubeVideoElement) this.firstTimeSync(youtubeVideoElement); - else { - setInterval( - this.video.element - ? null - : () => { - var yve = document.querySelector( - "video.video-stream.html5-main-video" - ); - if ( - yve !== null && - (this.video.element !== yve || this.video.element === null) - ) { - this.firstTimeSync(yve); - } - }, - 1000 - ); - } - break; - case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBONOW: - const hboSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector('video.default')._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 hboSeekInject = `window.seekScriptLoaded=!0;var getVideoPlayer=function(){var e=document.querySelector("${ + 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);`; + const hboSeekInjectScript = document.createElement('script'); hboSeekInjectScript.text = hboSeekInject; document.head.appendChild(hboSeekInjectScript); - const hboVideoElement = document.querySelector("video.default"); + const hboVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.HBONOW]); if (hboVideoElement) { const bottomHalf = - hboVideoElement.parentNode.parentNode.parentNode.parentNode - .parentNode.children[1]; - bottomHalf.children[0].id = "hboUpperTitle"; - bottomHalf.children[1].id = "hboLowerTitle"; + hboVideoElement.parentNode.parentNode.parentNode.parentNode.parentNode.children[1]; + bottomHalf.children[0].id = 'hboUpperTitle'; + bottomHalf.children[1].id = 'hboLowerTitle'; this.firstTimeSync(hboVideoElement); } else { setInterval( this.video.element ? null : () => { - var hve = document.querySelector("video.default"); + var hve = document.querySelector(this.selectors[PLAYER_SOURCE.HBONOW]); if ( hve !== null && hve !== undefined && @@ -581,13 +499,13 @@ export default class VideoListener { } break; case PLAYER_SOURCE.PEACOCK: - const peacockInject = `var watchPartyInteraction=function(e){if(e.source===window){const data=JSON.parse(e.data);const playerReactElement=document.querySelector(".video-player-component.playback-component > div");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 peacockInject = `var watchPartyInteraction=function(e){if(e.source===window){const data=JSON.parse(e.data);const playerReactElement=document.querySelector("${ + 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);`; + const peacockInjectScript = document.createElement('script'); peacockInjectScript.text = peacockInject; document.head.appendChild(peacockInjectScript); - const peacockVideoElement = document.querySelector( - ".video-player-component.playback-component video" - ); + const peacockVideoElement = document.querySelector(this.selectors[PLAYER_SOURCE.PEACOCK]); if (peacockVideoElement) { this.firstTimeSync(peacockVideoElement); } else { @@ -595,9 +513,7 @@ export default class VideoListener { this.video.element ? null : () => { - var pve = document.querySelector( - ".video-player-component.playback-component video" - ); + var pve = document.querySelector(this.selectors[PLAYER_SOURCE.PEACOCK]); if ( pve !== null && pve !== undefined && @@ -611,11 +527,9 @@ export default class VideoListener { } break; case PLAYER_SOURCE.GOOGLEPLAY: - const playerIframe = document.querySelector("body span div iframe"); + const playerIframe = document.querySelector(this.selectors[PLAYER_SOURCE.GOOGLEPLAY]); if (playerIframe) { - const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector( - "video" - ); + const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector('video'); if (googlePlayVideoElement) { this.firstTimeSync(googlePlayVideoElement); } @@ -624,11 +538,9 @@ export default class VideoListener { this.video.element ? null : () => { - const pif = document.querySelector("body span div iframe"); + const pif = document.querySelector(this.selectors[PLAYER_SOURCE.GOOGLEPLAY]); if (pif) { - const gpve = pif.contentWindow.document.querySelector( - "video" - ); + const gpve = pif.contentWindow.document.querySelector('video'); if (gpve) { this.firstTimeSync(gpve); } @@ -639,10 +551,10 @@ export default class VideoListener { } 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 crunchyRollInjectScript = document.createElement("script"); + const crunchyRollInjectScript = document.createElement('script'); crunchyRollInjectScript.text = crunchyRollInject; document.head.appendChild(crunchyRollInjectScript); - const crunchyrollIframe = document.getElementById("vilos-player"); + const crunchyrollIframe = document.querySelector(this.selectors[PLAYER_SOURCE.CRUNCHYROLL]); if (crunchyrollIframe) { this.firstTimeSync(crunchyrollIframe); } else { @@ -650,7 +562,7 @@ export default class VideoListener { this.video.element ? null : () => { - const cif = document.getElementById("vilos-player"); + const cif = document.querySelector(this.selectors[PLAYER_SOURCE.CRUNCHYROLL]); if (cif) { this.firstTimeSync(cif); } @@ -660,7 +572,7 @@ export default class VideoListener { } break; case PLAYER_SOURCE.LOCAL: - const localVideoElement = document.getElementsByTagName("video")[0]; + const localVideoElement = document.getElementsByTagName('video')[0]; if (localVideoElement) { this.firstTimeSync(localVideoElement); } @@ -672,12 +584,12 @@ export default class VideoListener { end() { switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: - window.removeEventListener("watchParty", this.crunchyRollListener); + window.removeEventListener('watchParty', this.crunchyRollListener); break; default: if (this.video.element) { - this.video.element.removeEventListener("playing", this.onplay); - this.video.element.removeEventListener("pause", this.onpause); + this.video.element.removeEventListener('playing', this.onplay); + this.video.element.removeEventListener('pause', this.onpause); } } } diff --git a/functions/modules/createRoom.js b/functions/modules/createRoom.js index a5eb382..fafdeaa 100644 --- a/functions/modules/createRoom.js +++ b/functions/modules/createRoom.js @@ -1,27 +1,21 @@ -const admin = require("firebase-admin"); +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" }); + 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("/", "\\")) + .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" }); + if (roomNameTaken) return res.status(409).send({ message: 'That party name is already taken' }); await admin .firestore() - .collection("rooms") + .collection('rooms') .doc(bodydata.partyName) .set({ name: bodydata.partyName, @@ -32,17 +26,17 @@ module.exports = async (req, res) => { adminOnly: bodydata.adminOnly, }) .catch((err) => { - res.status(500).send({ message: "Unable to start party." }); + res.status(500).send({ message: 'Unable to start party.' }); console.error(err); }); await admin .firestore() - .collection("rooms") + .collection('rooms') .doc(bodydata.partyName) - .collection("messages") + .collection('messages') .add({ - uid: "", - name: "", + uid: '', + name: '', text: `${bodydata.userName} started the party.`, time: new Date(), }) @@ -54,9 +48,9 @@ module.exports = async (req, res) => { }); await admin .firestore() - .collection("rooms") + .collection('rooms') .doc(bodydata.partyName) - .collection("users") + .collection('users') .doc(bodydata.uid) .set({ admin: true, @@ -68,26 +62,24 @@ module.exports = async (req, res) => { err ); }); - if (bodydata.player && bodydata.player.source === "amazon.") { + if ( + bodydata.player && + (bodydata.player.source === 'amazon.' || bodydata.player.source === 'hulu.') + ) { await admin .firestore() - .collection("rooms") + .collection('rooms') .doc(bodydata.partyName) - .collection("messages") + .collection('messages') .add({ - uid: "", - name: "", - text: `Watch Party may not work with Prime Video temporarily. An update is coming to fix this.`, + uid: '', + name: '', + text: `Watch Party may not work temporarily. An update is coming to fix this.`, time: new Date(), }) .catch((err) => { - console.error( - `Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`, - err - ); + console.error(`Failed to add amazon error message : \n\t Room: ${bodydata.partyName}`, err); }); } - res - .status(201) - .send({ roomId: bodydata.partyName, message: "Started a party!" }); + res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' }); };