v1.6.1/release

-amazon fix
-play movies fix
This commit is contained in:
2020-08-12 10:39:39 -04:00
parent e1cc9fa6f5
commit 0de3788e13
10 changed files with 410 additions and 267 deletions
+14 -11
View File
@@ -15195,10 +15195,13 @@
} }
}, },
"serialize-javascript": { "serialize-javascript": {
"version": "2.1.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
"dev": true "dev": true,
"requires": {
"randombytes": "^2.1.0"
}
}, },
"serve-index": { "serve-index": {
"version": "1.9.1", "version": "1.9.1",
@@ -16231,16 +16234,16 @@
} }
}, },
"terser-webpack-plugin": { "terser-webpack-plugin": {
"version": "1.4.3", "version": "1.4.4",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
"dev": true, "dev": true,
"requires": { "requires": {
"cacache": "^12.0.2", "cacache": "^12.0.2",
"find-cache-dir": "^2.1.0", "find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0", "is-wsl": "^1.1.0",
"schema-utils": "^1.0.0", "schema-utils": "^1.0.0",
"serialize-javascript": "^2.1.2", "serialize-javascript": "^3.1.0",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"terser": "^4.1.2", "terser": "^4.1.2",
"webpack-sources": "^1.4.0", "webpack-sources": "^1.4.0",
@@ -16288,9 +16291,9 @@
} }
}, },
"p-limit": { "p-limit": {
"version": "2.2.2", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true, "dev": true,
"requires": { "requires": {
"p-try": "^2.0.0" "p-try": "^2.0.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "watch-party-crx", "name": "watch-party-crx",
"version": "1.6.0", "version": "1.6.1",
"private": true, "private": true,
"dependencies": {}, "dependencies": {},
"scripts": { "scripts": {
+51 -41
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.0'; const APP_VERSION = "1.6.1";
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,
}) })
@@ -56,7 +56,13 @@ const fetcher = async (request, sendResponse) => {
return res.json(); return res.json();
}) })
.then((res) => sendResponse({ ...res, ...resStatus })) .then((res) => sendResponse({ ...res, ...resStatus }))
.catch((err) => sendResponse({ ...err, status: 503, statusText: "Couldn't talk to server" })); .catch((err) =>
sendResponse({
...err,
status: 503,
statusText: "Couldn't talk to server",
})
);
}; };
const sendAuth = async (sendResponse) => { const sendAuth = async (sendResponse) => {
@@ -66,35 +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);
} }
} 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);
} }
} 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);
} }
} }
} }
@@ -103,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;
@@ -134,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) => {
@@ -151,14 +159,16 @@ 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((user) => user.id === firebase.auth().currentUser.uid)[0] .filter(
(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 });
@@ -170,10 +180,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) {
@@ -187,18 +197,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,
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "Watch Party", "name": "Watch Party",
"short_name": "WP", "short_name": "WP",
"version": "1.6.0", "version": "1.6.1",
"description": "Watch streamed content together.", "description": "Watch streamed content together.",
"background": { "background": {
"page": "background.html" "page": "background.html"
+59 -38
View File
@@ -9,27 +9,33 @@ 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 { Fab, createMuiTheme, ThemeProvider, Snackbar, Tooltip } from '@material-ui/core'; import {
import Create from './Create'; Fab,
import Loading from './Loading'; createMuiTheme,
import firebase from 'firebase/app'; ThemeProvider,
import 'firebase/firestore'; Snackbar,
import Inactive from './Inactive'; Tooltip,
import { getUserUid, getPlayerSource, PLAYER_SOURCE } from './Api'; } 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.0'; const APP_VERSION = "1.6.1";
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",
}, },
}, },
}); });
@@ -42,32 +48,41 @@ 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('--neg-party-width', `-${checkedX}px`); document.documentElement.style.setProperty(
"--neg-party-width",
`-${checkedX}px`
);
}; };
const doResize = (ev) => { const doResize = (ev) => {
const checkedX = const checkedX =
window.innerWidth - window.innerWidth -
Math.min(window.innerWidth - 300, Math.max(window.innerWidth * 0.5, ev.clientX)); Math.min(
document.documentElement.style.setProperty('--party-width', `${checkedX}px`); window.innerWidth - 300,
document.documentElement.style.setProperty('--neg-party-width', `-${checkedX}px`); 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) => { 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);
@@ -79,8 +94,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);
@@ -88,18 +103,19 @@ 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.HBONOW) (getPlayerSource() === PLAYER_SOURCE.HBOMAX ||
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();
@@ -110,8 +126,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
@@ -123,7 +139,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}
@@ -136,12 +152,17 @@ 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 onDoubleClick={resetResize} onMouseDown={startResize} id="party-width-dragger"> <div
onDoubleClick={resetResize}
onMouseDown={startResize}
id="party-width-dragger"
>
|| ||
</div> </div>
</Tooltip> </Tooltip>
{loading && <Loading />} {loading && <Loading />}
{status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? ( {status[APP_VERSION_STRING] &&
status[APP_VERSION_STRING].active === true ? (
<Routes <Routes
updateLoading={setLoading} updateLoading={setLoading}
notify={(message) => setNotification({ open: true, message })} notify={(message) => setNotification({ open: true, message })}
+219 -148
View File
@@ -9,17 +9,22 @@ 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 { PLAYER_STATUS, getPlayerSource, PLAYER_SOURCE, LocalData } from './Api'; import {
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) { constructor(listener = templateListener) {
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.isUpdating = false; this.isUpdating = false;
@@ -41,7 +46,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)
@@ -68,23 +73,30 @@ 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);
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 (Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5) { if (
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({ type: 'SEEK', time: serverPlayer.time * 1000 }, '*'); window.postMessage(
{ 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) => console.error('WatchParty erred when syncing time.')); .catch((err) =>
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);
@@ -97,7 +109,10 @@ 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({ type: 'SEEK', time: serverPlayer.time }, '*'); window.postMessage(
{ type: "SEEK", time: serverPlayer.time },
"*"
);
break; break;
case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBOMAX:
case PLAYER_SOURCE.HBONOW: case PLAYER_SOURCE.HBONOW:
@@ -106,8 +121,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,
}) })
@@ -119,8 +134,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,
}) })
@@ -139,15 +154,18 @@ 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({ type: 'PAUSE', time: serverPlayer.time }, '*'); window.postMessage(
{ 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,
}) })
@@ -163,15 +181,18 @@ 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({ type: 'PLAY', time: serverPlayer.time }, '*'); window.postMessage(
{ 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,
}) })
@@ -179,7 +200,9 @@ export default class VideoListener {
} else { } else {
await this.video.element await this.video.element
.play() .play()
.catch((err) => console.error('WatchParty erred when syncing play.')); .catch((err) =>
console.error("WatchParty erred when syncing play.")
);
} }
break; break;
default: default:
@@ -189,10 +212,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;
@@ -208,74 +231,89 @@ export default class VideoListener {
switch (this.video.source) { switch (this.video.source) {
case PLAYER_SOURCE.NETFLIX: case PLAYER_SOURCE.NETFLIX:
const titleContainerParent = document.querySelector( const titleContainerParent = document.querySelector(
'.PlayerControls--control-element.text-control.video-title' ".PlayerControls--control-element.text-control.video-title"
); );
if (titleContainerParent) { if (titleContainerParent) {
const titleContainer = titleContainerParent.firstChild; const titleContainer = titleContainerParent.firstChild;
const nshow = titleContainer.querySelector('h4') const nshow = titleContainer.querySelector("h4")
? titleContainer.querySelector('h4').innerHTML ? titleContainer.querySelector("h4").innerHTML
: titleContainer.innerHTML; : titleContainer.innerHTML;
let nepisode = ''; let nepisode = "";
titleContainer.querySelectorAll('span').forEach((e) => { titleContainer.querySelectorAll("span").forEach((e) => {
if (e.innerHTML) nepisode += e.innerHTML + ' '; if (e.innerHTML) nepisode += e.innerHTML + " ";
}); });
return nshow === '' && nepisode === '' ? null : nshow + '\n' + nepisode; return nshow === "" && nepisode === ""
? null
: nshow + "\n" + nepisode;
} }
break; break;
case PLAYER_SOURCE.AMAZON: case PLAYER_SOURCE.AMAZON:
const ashow = document.querySelector('.f3w9jrr.ff48h02').firstChild.innerHTML; const ashow =
const aepisode = document.querySelector('.f3w9jrr.ff48h02').lastChild.innerHTML; document.querySelector(
return ashow === '' && aepisode === '' ? null : ashow + '\n' + aepisode; "#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: case PLAYER_SOURCE.HULU:
const hshow = document.querySelector('.metadata-area__second-line').innerHTML; const hshow = document.querySelector(".metadata-area__second-line")
const hepisode = document.querySelector('.metadata-area__third-line').innerHTML; .innerHTML;
return hshow === '' && hepisode === '' ? null : hshow + '\n' + hepisode; const hepisode = document.querySelector(".metadata-area__third-line")
.innerHTML;
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('.title-field') const dshow = document.querySelector(".title-field")
? document.querySelector('.title-field').innerHTML ? document.querySelector(".title-field").innerHTML
: ''; : "";
const depisode = document.querySelector('.subtitle-field') const depisode = document.querySelector(".subtitle-field")
? document.querySelector('.subtitle-field').innerHTML ? document.querySelector(".subtitle-field").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('h1.title').innerText; const yshow = document.querySelector("h1.title").innerText;
const yepisode = document.querySelector('yt-formatted-string.super-title').innerText; const yepisode = document.querySelector(
return yshow === '' && yepisode === '' ? null : yshow + '\n' + yepisode; "yt-formatted-string.super-title"
).innerText;
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.parentNode.parentNode const bottomHalf = this.video.element.parentNode.parentNode.parentNode
.children[1]; .parentNode.parentNode.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 === '' ? null : hboshow + '\n' + hboepisode; return hboshow === "" && hboepisode === ""
? null
: hboshow + "\n" + hboepisode;
case PLAYER_SOURCE.PEACOCK: case PLAYER_SOURCE.PEACOCK:
const peacockshow = document.querySelector( const peacockshow = document.querySelector(
'.item.playback-metadata__container-episode-metadata-info' ".item.playback-metadata__container-episode-metadata-info"
).innerText; ).innerText;
const peacockepisode = document.querySelector('.item.playback-metadata__container-title') const peacockepisode = document.querySelector(
.innerText; ".item.playback-metadata__container-title"
return peacockshow === '' && peacockepisode === '' ).innerText;
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("body span div iframe");
'#yDmH0d > div.llhEMd.bYEzqc.LAhoGb.iWO5td > div > div.LhXUod.XL54pf.J9Nfi.iWO5td > span > div > div > iframe' var googleplayshow = "";
);
var googleplayshow = '';
if (playerIframe) { if (playerIframe) {
const titleElement = playerIframe.contentWindow.document.querySelector('.playing-title'); const titleElement = playerIframe.contentWindow.document.querySelector(
googleplayshow = titleElement ? titleElement.innerText : ''; ".playing-title"
);
googleplayshow = titleElement ? titleElement.innerText : "";
} }
return googleplayshow === '' ? null : googleplayshow; return googleplayshow === "" ? null : googleplayshow;
case PLAYER_SOURCE.CRUNCHYROLL: case PLAYER_SOURCE.CRUNCHYROLL:
const crunchyrollTitle = document.querySelector('#showmedia_about_media'); const crunchyrollTitle = document.querySelector(
const crunchyrollshow = crunchyrollTitle ? crunchyrollTitle.innerText : ''; "#showmedia_about_media"
return crunchyrollshow === '' ? null : crunchyrollshow; );
const crunchyrollshow = crunchyrollTitle
? crunchyrollTitle.innerText
: "";
return crunchyrollshow === "" ? null : crunchyrollshow;
default: default:
break; break;
} }
@@ -296,8 +334,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,
@@ -317,29 +355,32 @@ 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() {
this.updateStatus({ source: getPlayerSource(), showName: await this.getShowName() }); this.updateStatus({
source: getPlayerSource(),
showName: await this.getShowName(),
});
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);
if (document.getElementsByClassName('AkiraPlayer')[0]) { if (document.getElementsByClassName("AkiraPlayer")[0]) {
const videoElement = document const videoElement = document
.getElementsByClassName('AkiraPlayer')[0] .getElementsByClassName("AkiraPlayer")[0]
.getElementsByTagName('video')[0]; .getElementsByTagName("video")[0];
if (videoElement && !this.video.element) { if (videoElement && !this.video.element) {
this.firstTimeSync(videoElement); this.firstTimeSync(videoElement);
} else { } else {
@@ -347,10 +388,31 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var nve = document.getElementsByClassName('AkiraPlayer')[0] var nve = document.getElementsByClassName("AkiraPlayer")[0]
? document ? document
.getElementsByClassName('AkiraPlayer')[0] .getElementsByClassName("AkiraPlayer")[0]
.getElementsByTagName('video')[0] .getElementsByTagName("video")[0]
: null;
if (
nve !== null &&
(this.video.element !== nve ||
this.video.element === null)
) {
this.firstTimeSync(nve);
}
},
1000
);
}
} else {
setInterval(
this.video.element
? null
: () => {
var nve = document.getElementsByClassName("AkiraPlayer")[0]
? document
.getElementsByClassName("AkiraPlayer")[0]
.getElementsByTagName("video")[0]
: null; : null;
if ( if (
nve !== null && nve !== null &&
@@ -362,30 +424,15 @@ export default class VideoListener {
1000 1000
); );
} }
} 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
);
}
break; break;
case PLAYER_SOURCE.HULU: 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 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 huluSeekInjectScript = document.createElement("script");
huluSeekInjectScript.text = huluSeekInject; huluSeekInjectScript.text = huluSeekInject;
document.head.appendChild(huluSeekInjectScript); document.head.appendChild(huluSeekInjectScript);
const videoElement = document.getElementsByClassName('content-video-player')[0]; const videoElement = document.getElementsByClassName(
"content-video-player"
)[0];
if (videoElement) { if (videoElement) {
this.firstTimeSync(videoElement); this.firstTimeSync(videoElement);
} else { } else {
@@ -393,8 +440,13 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var hve = document.getElementsByClassName('content-video-player')[0]; var hve = document.getElementsByClassName(
if (hve !== null && (this.video.element !== hve || this.video.element === null)) { "content-video-player"
)[0];
if (
hve !== null &&
(this.video.element !== hve || this.video.element === null)
) {
this.firstTimeSync(hve); this.firstTimeSync(hve);
} }
}, },
@@ -403,10 +455,10 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.AMAZON: case PLAYER_SOURCE.AMAZON:
if (document.getElementsByClassName('webPlayerSDKContainer')[0]) { if (document.querySelector("webPlayerSDKContainer")) {
const videoElement = document const videoElement = document.querySelector(
.getElementsByClassName('webPlayerSDKContainer')[0] ".webPlayerSDKContainer video"
.getElementsByTagName('video')[0]; );
if (videoElement) { if (videoElement) {
this.firstTimeSync(videoElement); this.firstTimeSync(videoElement);
} else { } else {
@@ -414,12 +466,13 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var ave = document var ave = document.querySelector(
.getElementsByClassName('webPlayerSDKContainer')[0] ".webPlayerSDKContainer video"
.getElementsByTagName('video')[0]; );
if ( if (
ave !== null && ave !== null &&
(this.video.element !== ave || this.video.element === null) (this.video.element !== ave ||
this.video.element === null)
) { ) {
this.firstTimeSync(ave); this.firstTimeSync(ave);
} }
@@ -433,9 +486,12 @@ export default class VideoListener {
? null ? null
: () => { : () => {
var ave = document var ave = document
.getElementsByClassName('webPlayerSDKContainer')[0] .getElementsByClassName("webPlayerSDKContainer")[0]
.getElementsByTagName('video')[0]; .getElementsByTagName("video")[0];
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);
} }
}, },
@@ -444,7 +500,9 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.DISNEY: case PLAYER_SOURCE.DISNEY:
const disneyVideoElement = document.querySelector('video.btm-media-client-element'); const disneyVideoElement = document.querySelector(
"video.btm-media-client-element"
);
if (disneyVideoElement) { if (disneyVideoElement) {
this.firstTimeSync(disneyVideoElement); this.firstTimeSync(disneyVideoElement);
} else { } else {
@@ -452,8 +510,13 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
var dve = document.querySelector('video.btm-media-client-element'); var dve = document.querySelector(
if (dve !== null && (this.video.element !== dve || this.video.element === null)) { "video.btm-media-client-element"
);
if (
dve !== null &&
(this.video.element !== dve || this.video.element === null)
) {
this.firstTimeSync(dve); this.firstTimeSync(dve);
} }
}, },
@@ -462,15 +525,22 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.YOUTUBE: case PLAYER_SOURCE.YOUTUBE:
const youtubeVideoElement = document.querySelector('video.video-stream.html5-main-video'); const youtubeVideoElement = document.querySelector(
"video.video-stream.html5-main-video"
);
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('video.video-stream.html5-main-video'); var yve = document.querySelector(
if (yve !== null && (this.video.element !== yve || this.video.element === null)) { "video.video-stream.html5-main-video"
);
if (
yve !== null &&
(this.video.element !== yve || this.video.element === null)
) {
this.firstTimeSync(yve); this.firstTimeSync(yve);
} }
}, },
@@ -481,22 +551,23 @@ export default class VideoListener {
case PLAYER_SOURCE.HBOMAX: case PLAYER_SOURCE.HBOMAX:
case PLAYER_SOURCE.HBONOW: 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 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 hboSeekInjectScript = document.createElement("script");
hboSeekInjectScript.text = hboSeekInject; hboSeekInjectScript.text = hboSeekInject;
document.head.appendChild(hboSeekInjectScript); document.head.appendChild(hboSeekInjectScript);
const hboVideoElement = document.querySelector('video.default'); const hboVideoElement = document.querySelector("video.default");
if (hboVideoElement) { if (hboVideoElement) {
const bottomHalf = const bottomHalf =
hboVideoElement.parentNode.parentNode.parentNode.parentNode.parentNode.children[1]; hboVideoElement.parentNode.parentNode.parentNode.parentNode
bottomHalf.children[0].id = 'hboUpperTitle'; .parentNode.children[1];
bottomHalf.children[1].id = 'hboLowerTitle'; bottomHalf.children[0].id = "hboUpperTitle";
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('video.default'); var hve = document.querySelector("video.default");
if ( if (
hve !== null && hve !== null &&
hve !== undefined && hve !== undefined &&
@@ -511,11 +582,11 @@ export default class VideoListener {
break; break;
case PLAYER_SOURCE.PEACOCK: 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 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 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(
'.video-player-component.playback-component video' ".video-player-component.playback-component video"
); );
if (peacockVideoElement) { if (peacockVideoElement) {
this.firstTimeSync(peacockVideoElement); this.firstTimeSync(peacockVideoElement);
@@ -525,7 +596,7 @@ export default class VideoListener {
? null ? null
: () => { : () => {
var pve = document.querySelector( var pve = document.querySelector(
'.video-player-component.playback-component video' ".video-player-component.playback-component video"
); );
if ( if (
pve !== null && pve !== null &&
@@ -540,11 +611,11 @@ export default class VideoListener {
} }
break; break;
case PLAYER_SOURCE.GOOGLEPLAY: case PLAYER_SOURCE.GOOGLEPLAY:
const playerIframe = document.querySelector( const playerIframe = document.querySelector("body span div iframe");
'#yDmH0d > div.llhEMd.bYEzqc.LAhoGb.iWO5td > div > div.LhXUod.XL54pf.J9Nfi.iWO5td > span > div > div > iframe'
);
if (playerIframe) { if (playerIframe) {
const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector('video'); const googlePlayVideoElement = playerIframe.contentWindow.document.querySelector(
"video"
);
if (googlePlayVideoElement) { if (googlePlayVideoElement) {
this.firstTimeSync(googlePlayVideoElement); this.firstTimeSync(googlePlayVideoElement);
} }
@@ -553,11 +624,11 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
const pif = document.querySelector( const pif = document.querySelector("body span div iframe");
'#yDmH0d > div.llhEMd.bYEzqc.LAhoGb.iWO5td > div > div.LhXUod.XL54pf.J9Nfi.iWO5td > span > div > div > iframe'
);
if (pif) { if (pif) {
const gpve = pif.contentWindow.document.querySelector('video'); const gpve = pif.contentWindow.document.querySelector(
"video"
);
if (gpve) { if (gpve) {
this.firstTimeSync(gpve); this.firstTimeSync(gpve);
} }
@@ -568,10 +639,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.getElementById('vilos-player'); const crunchyrollIframe = document.getElementById("vilos-player");
if (crunchyrollIframe) { if (crunchyrollIframe) {
this.firstTimeSync(crunchyrollIframe); this.firstTimeSync(crunchyrollIframe);
} else { } else {
@@ -579,7 +650,7 @@ export default class VideoListener {
this.video.element this.video.element
? null ? null
: () => { : () => {
const cif = document.getElementById('vilos-player'); const cif = document.getElementById("vilos-player");
if (cif) { if (cif) {
this.firstTimeSync(cif); this.firstTimeSync(cif);
} }
@@ -589,7 +660,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);
} }
@@ -601,12 +672,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);
} }
} }
} }
+31 -20
View File
@@ -1,51 +1,62 @@
const admin = require('firebase-admin'); const admin = require("firebase-admin");
const Logger = require('../Logger'); const Logger = require("../Logger");
const mLogger = 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 (req.method === 'GET' || req.method === 'DELETE' || req.method === 'PUT') { if (
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', { URL: req.url, Error: err }); mLogger.error("AUTH VALIDATE FIREBASE ERROR", {
return res.status(500).send({ message: 'Unable to verify user token' }); URL: req.url,
Error: err,
});
return res
.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.status(401).send({ message: 'Something went wrong when authorizing' }); return res
.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;
}; };
+44 -17
View File
@@ -1,21 +1,27 @@
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) res.status(400).send({ message: 'Missing user name' }); if (!bodydata.userName)
if (!bodydata.partyName) res.status(400).send({ message: 'Missing party name' }); res.status(400).send({ message: "Missing user name" });
if (!bodydata.partyPin) res.status(400).send({ message: 'Missing party pin' }); 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 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) 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 await admin
.firestore() .firestore()
.collection('rooms') .collection("rooms")
.doc(bodydata.partyName) .doc(bodydata.partyName)
.set({ .set({
name: bodydata.partyName, name: bodydata.partyName,
@@ -26,17 +32,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(),
}) })
@@ -48,9 +54,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,
@@ -62,5 +68,26 @@ module.exports = async (req, res) => {
err err
); );
}); });
res.status(201).send({ roomId: bodydata.partyName, message: 'Started a party!' }); if (bodydata.player && bodydata.player.source === "amazon.") {
await admin
.firestore()
.collection("rooms")
.doc(bodydata.partyName)
.collection("messages")
.add({
uid: "<system>",
name: "",
text: `Watch Party may not work with Prime Video 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
);
});
}
res
.status(201)
.send({ roomId: bodydata.partyName, message: "Started a party!" });
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "watch-party-api", "name": "watch-party-api",
"version": "1.6.0", "version": "1.6.1",
"description": "Cloud Functions for Watch Party", "description": "Cloud Functions for Watch Party",
"scripts": { "scripts": {
"lint": "eslint .", "lint": "eslint .",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "watch-party", "name": "watch-party",
"version": "1.6.0", "version": "1.6.1",
"description": "Watch Party", "description": "Watch Party",
"scripts": { "scripts": {
"start": "firebase emulators:start", "start": "firebase emulators:start",