From 475dcdd5e867d3df82635a48fa104c5666f3b163 Mon Sep 17 00:00:00 2001 From: Ayushya Amitabh Date: Fri, 28 Aug 2020 15:24:23 -0400 Subject: [PATCH] v1.6.4/add funimation --- app/public/manifest.json | 6 +++-- app/src/Api.js | 2 ++ app/src/Chat.js | 9 +++---- app/src/VideoListener.js | 58 +++++++++++++++++++++++++++++++++++++--- app/src/index.css | 3 ++- app/src/index.js | 3 +++ 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/app/public/manifest.json b/app/public/manifest.json index 12bd08f..c96d5a2 100644 --- a/app/public/manifest.json +++ b/app/public/manifest.json @@ -21,7 +21,8 @@ "https://play.google.com/movies/*", "https://*.crunchyroll.com/*", "https://tv.apple.com/*", - "https://*.viki.com/*" + "https://*.viki.com/*", + "https://*.funimation.com/*" ], "content_security_policy": "script-src 'self' https://unpkg.com/ https://www.gstatic.com/ https://*.firebaseio.com https://www.googleapis.com; object-src 'self'", "content_scripts": [ @@ -38,7 +39,8 @@ "https://play.google.com/*", "https://*.crunchyroll.com/*", "https://tv.apple.com/*", - "https://*.viki.com/*" + "https://*.viki.com/*", + "https://*.funimation.com/*" ], "run_at": "document_idle", "js": ["/static/js/content.js"], diff --git a/app/src/Api.js b/app/src/Api.js index c535276..28a5941 100644 --- a/app/src/Api.js +++ b/app/src/Api.js @@ -32,6 +32,7 @@ export const PLAYER_SOURCE = { CRUNCHYROLL: 'crunchyroll.', APPLE: 'tv.apple.', VIKI: 'viki.', + FUNIMATION: 'funimation.', LOCAL: 'localhost', }; @@ -49,6 +50,7 @@ export const getPlayerSource = () => { if (HREF.includes(PLAYER_SOURCE.CRUNCHYROLL)) return PLAYER_SOURCE.CRUNCHYROLL; if (HREF.includes(PLAYER_SOURCE.APPLE)) return PLAYER_SOURCE.APPLE; if (HREF.includes(PLAYER_SOURCE.VIKI)) return PLAYER_SOURCE.VIKI; + if (HREF.includes(PLAYER_SOURCE.FUNIMATION)) return PLAYER_SOURCE.FUNIMATION; if (HREF.includes(PLAYER_SOURCE.LOCAL)) return PLAYER_SOURCE.LOCAL; }; diff --git a/app/src/Chat.js b/app/src/Chat.js index c31dbfc..434900b 100644 --- a/app/src/Chat.js +++ b/app/src/Chat.js @@ -507,11 +507,10 @@ export default class Chat extends Component { message: 'Functionality may be buggy, HBO has a horrible design.', }, { - condition: () => getPlayerSource() === PLAYER_SOURCE.GOOGLEPLAY, - message: 'Functionality may be buggy, support on this site is in testing.', - }, - { - condition: () => getPlayerSource() === PLAYER_SOURCE.CRUNCHYROLL, + condition: () => + getPlayerSource() === PLAYER_SOURCE.APPLE || + getPlayerSource() === PLAYER_SOURCE.FUNIMATION || + getPlayerSource() === PLAYER_SOURCE.VIKI, message: 'Functionality may be buggy, support on this site is in testing.', }, { diff --git a/app/src/VideoListener.js b/app/src/VideoListener.js index 8b4d1b1..7d99900 100644 --- a/app/src/VideoListener.js +++ b/app/src/VideoListener.js @@ -71,6 +71,7 @@ export default class VideoListener { // REMOVE LISTENER BEFORE SYNCING switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: + case PLAYER_SOURCE.FUNIMATION: window.removeEventListener('watchParty', this.crunchyRollListener); break; default: @@ -80,7 +81,11 @@ export default class VideoListener { } await this.timeout(250); // SEEK - if (Math.abs(serverPlayer.time - this.video.element.currentTime) > 1.5) { + if ( + !!!this.video.element.currentTime || + (this.video.element.currentTime && + 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 }, '*'); @@ -131,6 +136,16 @@ export default class VideoListener { }) ); break; + case PLAYER_SOURCE.FUNIMATION: + window.postMessage( + JSON.stringify({ + watchPartyDirection: 'TO_SCRIPT', + type: 'WATCH_PARTY_SEEK', + status: serverPlayer.status, + time: serverPlayer.time, + }) + ); + break; case PLAYER_SOURCE.APPLE: this.video.element.currentTime = serverPlayer.time; break; @@ -153,7 +168,8 @@ export default class VideoListener { window.postMessage({ type: 'PAUSE', time: serverPlayer.time }, '*'); } else if ( PLAYER_SOURCE.CRUNCHYROLL === this.video.source || - PLAYER_SOURCE.PEACOCK === this.video.source + PLAYER_SOURCE.PEACOCK === this.video.source || + PLAYER_SOURCE.FUNIMATION === this.video.source ) { window.postMessage( JSON.stringify({ @@ -177,7 +193,8 @@ export default class VideoListener { window.postMessage({ type: 'PLAY', time: serverPlayer.time }, '*'); } else if ( PLAYER_SOURCE.CRUNCHYROLL === this.video.source || - PLAYER_SOURCE.PEACOCK === this.video.source + PLAYER_SOURCE.PEACOCK === this.video.source || + PLAYER_SOURCE.FUNIMATION === this.video.source ) { window.postMessage( JSON.stringify({ @@ -200,6 +217,7 @@ export default class VideoListener { // RE-ADD LISTENERS FOR FUTURE SYNC switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: + case PLAYER_SOURCE.FUNIMATION: window.addEventListener('watchParty', this.crunchyRollListener); break; default: @@ -292,6 +310,16 @@ export default class VideoListener { const docTitleSplit = document.title.split('|'); if (docTitleSplit.length > 1) return docTitleSplit[0].trim(); else return null; + case PLAYER_SOURCE.FUNIMATION: + const funimationShowContainer = document.querySelector(nS.show); + const funimationEpisodeContainer = document.querySelector(nS.episode); + const funimationShow = funimationShowContainer ? funimationShowContainer.innerText : ''; + const funimationEpisode = funimationEpisodeContainer + ? funimationEpisodeContainer.innerText.replace(/\n/gi, '') + : ''; + return funimationShow === '' && funimationEpisode === '' + ? null + : funimationShow + '\n' + funimationEpisode; default: break; } @@ -331,6 +359,7 @@ export default class VideoListener { }); switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: + case PLAYER_SOURCE.FUNIMATION: window.postMessage( JSON.stringify({ watchPartyDirection: 'TO_SCRIPT', @@ -643,6 +672,28 @@ export default class VideoListener { ); } break; + case PLAYER_SOURCE.FUNIMATION: + const funimationInject = `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){const playerIframe=document.querySelector('.video-player-container iframe#player');if(playerIframe){const player=playerIframe.contentWindow.document.querySelector('video');if(player){sendToWatchPartyApp(pS,player.currentTime)}}},watchPartySendPlaying=function(){watchPartyGetTimeAndSend('PLAYING')},watchPartySendPaused=function(){watchPartyGetTimeAndSend('PAUSED')},watchPartyInteraction=function(e){const data=JSON.parse(e.data);const playerIframe=document.querySelector('.video-player-container iframe#player');if(playerIframe){const player=playerIframe.contentWindow.document.querySelector('video');if(player){if(data.watchPartyDirection==='TO_SCRIPT'){if(data.type==='WATCH_PARTY_ADD_LISTENERS'){player.addEventListener('playing',watchPartySendPlaying);player.addEventListener('pause',watchPartySendPaused)}else if(data.type==='WATCH_PARTY_SEEK'){const playerNode=playerIframe.contentWindow.document.querySelector('#brightcove-player');if(playerNode){playerNode.player.currentTime(data.time)}}else if(data.type==='WATCH_PARTY_STATUS'){if(data.status==='PAUSED')player.pause();if(data.status==='PLAYING')player.play()}}}}};window.addEventListener("message",watchPartyInteraction);`; + const funimationInjectScript = document.createElement('script'); + funimationInjectScript.text = funimationInject; + document.head.appendChild(funimationInjectScript); + const funimationIframe = document.querySelector(this.selectors[PLAYER_SOURCE.FUNIMATION]); + if (funimationIframe) { + this.firstTimeSync(funimationIframe); + } else { + setInterval( + this.video.element + ? null + : () => { + const fif = document.querySelector(this.selectors[PLAYER_SOURCE.FUNIMATION]); + if (fif) { + this.firstTimeSync(fif); + } + }, + 1000 + ); + } + break; case PLAYER_SOURCE.LOCAL: const localVideoElement = document.getElementsByTagName('video')[0]; if (localVideoElement) { @@ -656,6 +707,7 @@ export default class VideoListener { end() { switch (this.video.source) { case PLAYER_SOURCE.CRUNCHYROLL: + case PLAYER_SOURCE.FUNIMATION: window.removeEventListener('watchParty', this.crunchyRollListener); break; default: diff --git a/app/src/index.css b/app/src/index.css index d2b429c..5c53b12 100644 --- a/app/src/index.css +++ b/app/src/index.css @@ -231,7 +231,8 @@ body.apple .thread-wrapper .ReactVirtualized__Grid__innerScrollContainer { body.hulu #party_wrapper *, body.peacock #party_wrapper *, body.disney #party_wrapper *, -body.apple #party_wrapper * { +body.apple #party_wrapper *, +body.funimation #party_wrapper * { box-sizing: inherit; } diff --git a/app/src/index.js b/app/src/index.js index 1006c89..a736061 100644 --- a/app/src/index.js +++ b/app/src/index.js @@ -100,6 +100,9 @@ switch (getPlayerSource()) { case PLAYER_SOURCE.VIKI: document.body.classList.add('viki'); break; + case PLAYER_SOURCE.FUNIMATION: + document.body.classList.add('funimation'); + break; case PLAYER_SOURCE.LOCAL: document.body.classList.add('local'); break;