diff --git a/.prettierrc b/.prettierrc index c0ab7d08..6bf4e757 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { "tabWidth": 2, - "printWidth": 200, + "printWidth": 150, "useTabs": false } diff --git a/CHANGELOG.md b/CHANGELOG.md index a0bae5d3..8b5869a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
-

1.0.74

+

1.0.75

diff --git a/chrome/_locales/de/messages.json b/chrome/_locales/de/messages.json index ce0f6dd4..dcd0e226 100644 --- a/chrome/_locales/de/messages.json +++ b/chrome/_locales/de/messages.json @@ -249,5 +249,11 @@ }, "EpilepsySwitchDescription": { "message": "Beim überspringen der Werbung den Bildschrim verdunkeln" + }, + "UserAgentSwitch": { + "message": "Zu Desktop-Webseiten wechseln" + }, + "UserAgentSwitchDescription": { + "message": "Für prime video und disney+ auf die Desktop-Website wechseln und für amazon die Website mobilfreundlich machen" } } diff --git a/chrome/_locales/en/messages.json b/chrome/_locales/en/messages.json index 18b33254..14b143c1 100644 --- a/chrome/_locales/en/messages.json +++ b/chrome/_locales/en/messages.json @@ -249,5 +249,11 @@ }, "EpilepsySwitchDescription": { "message": "Darken the screen when skipping the ad" + }, + "UserAgentSwitch": { + "message": "Switch to desktop websites" + }, + "UserAgentSwitchDescription": { + "message": "For prime video and disney+ change to the Desktop website and for amazon make the site mobile friendly" } } diff --git a/chrome/_locales/mk/messages.json b/chrome/_locales/mk/messages.json index 4136e6b4..ec4cf0da 100644 --- a/chrome/_locales/mk/messages.json +++ b/chrome/_locales/mk/messages.json @@ -243,5 +243,11 @@ }, "EpilepsySwitchDescription": { "message": "Затемни го екранот кога ја прескокнуваш рекламата" + }, + "UserAgentSwitch": { + "message": "Префрли се на веб-локации за десктоп" + }, + "UserAgentSwitchDescription": { + "message": "За примарното видео и disney+ сменете на веб-страницата на Desktop и за amazon направете ја страницата пријателска за мобилни телефони" } } diff --git a/chrome/_locales/pt_BR/messages.json b/chrome/_locales/pt_BR/messages.json index be6582ce..80b995c3 100644 --- a/chrome/_locales/pt_BR/messages.json +++ b/chrome/_locales/pt_BR/messages.json @@ -243,5 +243,11 @@ }, "EpilepsySwitchDescription": { "message": "Escurecer a tela ao pular o anúncio" + }, + "UserAgentSwitch": { + "message": "Mudar para sites de desktop" + }, + "UserAgentSwitchDescription": { + "message": "Para o Prime Video e a Disney+, mude para o site para desktop e, para a Amazon, torne o site compatível com dispositivos móveis" } } diff --git a/chrome/badge.js b/chrome/badge.js index 5146590a..5e842aed 100644 --- a/chrome/badge.js +++ b/chrome/badge.js @@ -14,6 +14,7 @@ console.log("badge.js loaded"); chrome.action.setBadgeBackgroundColor({ color: "#d90000" }); let Badges = {}; +const isMobile = /Android/i.test(navigator.userAgent); /** * * Increases Badge by 1 @@ -81,3 +82,96 @@ chrome.runtime.onInstalled.addListener((details) => { }); } }); + +if (isMobile) { + const defaultSettings = { + settings: { + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, + Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, + Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, + Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, + General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, + }, + }; + let settings = defaultSettings.settings; + chrome.storage.sync.get("settings", function (result) { + // if there is an undefined setting, set it to the default + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; + ChangeUserAgent(); + console.log("userAgent", settings.Video.userAgent); + }); + + chrome.storage.sync.onChanged.addListener(function (changes) { + if (changes?.settings) { + const { oldValue, newValue } = changes.settings; + settings = newValue; + if (newValue.Video.userAgent !== oldValue?.Video?.userAgent) { + console.log("userAgent", settings.Video.userAgent); + // remove listener + if (!newValue?.Video?.userAgent) { + chrome.webRequest.onBeforeSendHeaders.removeListener(ReplaceUserAgent); + } else { + ChangeUserAgent(); + } + } + } + }); + const newUa = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 streamingEnhanced"; + function ReplaceUserAgent(details) { + for (let header of details.requestHeaders) { + if (header.name === "User-Agent") { + header.value = newUa; + break; + } + } + return { requestHeaders: details.requestHeaders }; + } + + function ChangeUserAgent() { + if (settings.Video.userAgent) { + chrome.webRequest.onBeforeSendHeaders.addListener( + ReplaceUserAgent, + { + urls: [ + "*://*.disneyplus.com/*", + // these are only the prime video urls + "*://*.primevideo.com/*", + "*://*.amazon.com/gp/video/*", + "*://*.amazon.co.jp/gp/video/*", + "*://*.amazon.de/gp/video/*", + "*://*.amazon.co.uk/gp/video/*", + ], + }, + ["blocking", "requestHeaders"] + ); + } + } +} diff --git a/chrome/cr.js b/chrome/cr.js index 81d99cfc..c8e58e89 100644 --- a/chrome/cr.js +++ b/chrome/cr.js @@ -13,21 +13,53 @@ /* global chrome */ const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, }; let settings = defaultSettings.settings; -const version = "1.0.74"; +const version = "1.0.75"; chrome.storage.sync.get("settings", function (result) { - console.log("%cNetflix%c/%cPrime%c Auto-Skip", "color: #e60010;font-size: 2em;", "color: white;font-size: 2em;", "color: #00aeef;font-size: 2em;", "color: white;font-size: 2em;"); + console.log( + "%cNetflix%c/%cPrime%c Auto-Skip", + "color: #e60010;font-size: 2em;", + "color: white;font-size: 2em;", + "color: #00aeef;font-size: 2em;", + "color: white;font-size: 2em;" + ); console.log("version:", version); - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; CrunchyrollObserver.observe(document, config); if (settings?.Video?.playOnFullScreen) startPlayOnFullScreen(); }); @@ -96,7 +128,10 @@ let reverseButtonEndTime; function addButton(video, startTime, endTime) { if (reverseButtonClicked) return; const button = document.createElement("div"); - button.setAttribute("class", "reverse-button css-1dbjc4n r-1awozwy r-lj0ial r-1jd5jdk r-1loqt21 r-18u37iz r-eu3ka r-1777fci r-kuhrb7 r-ymttw5 r-u8s1d r-1ff5aok r-1otgn73"); + button.setAttribute( + "class", + "reverse-button css-1dbjc4n r-1awozwy r-lj0ial r-1jd5jdk r-1loqt21 r-18u37iz r-eu3ka r-1777fci r-kuhrb7 r-ymttw5 r-u8s1d r-1ff5aok r-1otgn73" + ); button.style = "color:white;"; button.textContent = "Watch skipped ?"; diff --git a/chrome/manifest.json b/chrome/manifest.json index e61a97fb..5e686851 100644 --- a/chrome/manifest.json +++ b/chrome/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "1.0.74", + "version": "1.0.75", "homepage_url": "https://github.com/Dreamlinerm/Netflix-Prime-Auto-Skip", "icons": { @@ -35,7 +35,17 @@ "matches": ["https://static.crunchyroll.com/vilos-v2/web/vilos/player.html*"] } ], - "permissions": ["storage"], + "permissions": [ + "storage", + "webRequest", + "webRequestBlocking", + "*://*.disneyplus.com/*", + "*://*.primevideo.com/*", + "*://*.amazon.com/*", + "*://*.amazon.co.jp/*", + "*://*.amazon.de/*", + "*://*.amazon.co.uk/*" + ], "action": { "default_icon": { "16": "icons/NetflixAmazon Auto-Skip--16.png", diff --git a/chrome/popup/popup.html b/chrome/popup/popup.html index 92076e08..ad4def75 100644 --- a/chrome/popup/popup.html +++ b/chrome/popup/popup.html @@ -30,7 +30,7 @@

pageTitle

-

v.1.0.74

+

v.1.0.75

pageTitle - + pageTitle
+
+
+

UserAgentSwitch

+ +
+

SharedPageTitle

@@ -150,7 +167,9 @@

SharedPageTitle

-
gotoIndividualextendedSettings
+
+ gotoIndividualextendedSettings +
diff --git a/chrome/popup/settings.html b/chrome/popup/settings.html index 46a66799..82f206bc 100644 --- a/chrome/popup/settings.html +++ b/chrome/popup/settings.html @@ -29,7 +29,7 @@

pageTitle

-

v.1.0.74

+

v.1.0.75

pageTitle - + Netflix - + pageTitle backup - + + + statistics @@ -114,7 +126,12 @@

pageTitle

SharedPageDescription

+
+
+
+

UserAgentSwitch

+ +
+

UserAgentSwitchDescription

+

IntroSwitch

@@ -724,7 +752,14 @@

ImportSettings

Changelog

-

1.0.74

+

1.0.75

+
    +
  • Automatically use desktop mode on firefox/chrome mobile
  • +
  • Various mobile improvements
  • +
+
+
+

1.0.74

  • Released for Firefox on Android
diff --git a/chrome/popup/settings.js b/chrome/popup/settings.js index 6e1e04ce..78f4ae2d 100644 --- a/chrome/popup/settings.js +++ b/chrome/popup/settings.js @@ -50,19 +50,47 @@ if (url.includes("#")) Menu(url.split("#")[1]); // global variables in localStorage const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, }; +const isMobile = /mobile|streamingEnhanced/i.test(navigator.userAgent); +console.log("isMobile", isMobile, navigator.userAgent); let settings = defaultSettings.settings; chrome.storage.sync.get("settings", function (result) { // if there is an undefined setting, set it to the default - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; // delete every setting that is not in defaultSettings let changedSettings; for (const key in settings) { @@ -164,6 +192,9 @@ function setCheckboxesToSettings() { setButtonChecked("VideoAds", settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); setButtonChecked("VideoFullScreen", settings?.Video.playOnFullScreen); setButtonChecked("VideoEpilepsy", settings?.Video.epilepsy); + setButtonChecked("VideoUserAgent", settings?.Video.userAgent); + button = document.querySelector(".categoryMobile"); + if (button) button.style.display = isMobile ? "block" : "none"; // ------------- Default --------------------------------------- setButtonChecked("DefaultSkips", settings?.Amazon.filterPaid); // ------------- global buttons --------------------------------------- @@ -314,9 +345,11 @@ function listenForClicks() { }); settings.Amazon.blockFreevee = settings.Netflix.skipAd = settings.Video.playOnFullScreen = VideoSkips; if (VideoSkips) setCategoryToBoolean("watchCredits", false); - } else if (e.target.id === "VideoAds") settings.Amazon.blockFreevee = settings.Netflix.skipAd = !(settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); + } else if (e.target.id === "VideoAds") + settings.Amazon.blockFreevee = settings.Netflix.skipAd = !(settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); else if (e.target.id === "VideoFullScreen") settings.Video.playOnFullScreen = !settings.Video.playOnFullScreen; else if (e.target.id === "VideoEpilepsy") settings.Video.epilepsy = !settings.Video.epilepsy; + else if (e.target.id === "VideoUserAgent") settings.Video.userAgent = !settings.Video.userAgent; else if (e.target.id.startsWith("Video")) { let key = lowerCaseFirstLetter(e.target.id.replace("Video", "")); if (key === "skipCredits" || key === "watchCredits") { @@ -328,11 +361,18 @@ function listenForClicks() { // ------------- Default --------------------------------------- else if (e.target.id === "DefaultSkips") settings.Amazon.filterPaid = !settings?.Amazon.filterPaid; // ------------- Amazon --------------------------------------- - else if (e.target.id === "AmazonSkips") settings.Amazon.skipAd = settings.Amazon.filterPaid = !(settings.Amazon.skipAd && settings.Amazon.filterPaid); + else if (e.target.id === "AmazonSkips") + settings.Amazon.skipAd = settings.Amazon.filterPaid = !(settings.Amazon.skipAd && settings.Amazon.filterPaid); else if (e.target.id === "NetflixSkips") - settings.Netflix.skipRecap = settings.Netflix.skipBlocked = settings.Netflix.profile = !(settings?.Netflix.skipRecap && settings?.Netflix.skipBlocked && settings?.Netflix.profile); + settings.Netflix.skipRecap = + settings.Netflix.skipBlocked = + settings.Netflix.profile = + !(settings?.Netflix.skipRecap && settings?.Netflix.skipBlocked && settings?.Netflix.profile); // else if (e.target.id === "DisneySkips") settings.Disney.skipIntro = !settings?.Disney.skipIntro - else if (e.target.id === "CrunchyrollSkips") settings.Crunchyroll.skipIntro = settings.Crunchyroll.releaseCalendar = !(settings?.Crunchyroll.skipIntro && settings?.Crunchyroll.releaseCalendar); + else if (e.target.id === "CrunchyrollSkips") + settings.Crunchyroll.skipIntro = settings.Crunchyroll.releaseCalendar = !( + settings?.Crunchyroll.skipIntro && settings?.Crunchyroll.releaseCalendar + ); else { const services = ["Amazon", "Netflix", "Disney", "Crunchyroll"]; for (const service of services) { diff --git a/chrome/skipper.js b/chrome/skipper.js index c2f15b45..e2bd346d 100644 --- a/chrome/skipper.js +++ b/chrome/skipper.js @@ -15,7 +15,7 @@ const hostname = window.location.hostname; const title = document.title; const url = window.location.href; -const ua = window.navigator.userAgent; +const ua = navigator.userAgent; // only on prime video pages const isPrimeVideo = /amazon|primevideo/i.test(hostname) && (/video/i.test(title) || /video/i.test(url)); const isNetflix = /netflix/i.test(hostname); @@ -23,19 +23,40 @@ const isDisney = /disneyplus/i.test(hostname); const isHotstar = /hotstar/i.test(hostname); const isCrunchyroll = /crunchyroll/i.test(hostname); +const isMobile = /mobile|streamingEnhanced/i.test(ua); const isEdge = /edg/i.test(ua); // const isFirefox = /firefox/i.test(ua); -const version = "1.0.74"; +// const isChrome = /chrome/i.test(ua); +const version = "1.0.75"; if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { /* eslint-env root:true */ // global variables in localStorage const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, @@ -57,20 +78,20 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { DBCache = {}; } if (isNetflix) { - if (settings.Netflix?.showRating) { - startShowRatingInterval(); - } - } - // else if (isPrimeVideo) { - // if (settings.Amazon?.streamLinks) addStreamLinks(); - // } - else if (isDisney || isHotstar) { + if (settings.Netflix?.showRating) startShowRatingInterval(); + } else if (isDisney || isHotstar) { if (settings.Disney?.showRating) startShowRatingInterval(); } }); } function logStartOfAddon() { - console.log("%cNetflix%c/%cPrime%c Auto-Skip", "color: #e60010;font-size: 2em;", "color: white;font-size: 2em;", "color: #00aeef;font-size: 2em;", "color: white;font-size: 2em;"); + console.log( + "%cNetflix%c/%cPrime%c Auto-Skip", + "color: #e60010;font-size: 2em;", + "color: white;font-size: 2em;", + "color: #00aeef;font-size: 2em;", + "color: white;font-size: 2em;" + ); console.log("version:", version); console.log("Settings", settings); if (isNetflix) console.log("Page %cNetflix", "color: #e60010;"); @@ -93,10 +114,38 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { Amazon_FreeveeTimeout(); }, 1000); } + // customize mobile view for desktop website + if (settings.Video?.userAgent && isMobile) { + if (!document.querySelector(AmazonVideoClass) && !url.includes("/gp/video/detail/")) { + // add to head + let meta = document.createElement("meta"); + meta.name = "viewport"; + meta.content = "width=device-width, initial-scale=1"; + document.head.appendChild(meta); + + // make amazon more mobile friendly + let navBelt = document.querySelector("#nav-belt"); + if (navBelt) { + navBelt.style.width = "100vw"; + navBelt.style.display = "flex"; + navBelt.style.flexDirection = "column"; + navBelt.style.height = "fit-content"; + } + let navMain = document.querySelector("#nav-main"); + if (navMain) navMain.style.display = "none"; + } + } } chrome.storage.sync.get("settings", function (result) { // if there is an undefined setting, set it to the default - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; logStartOfAddon(); getDBCache(); @@ -117,7 +166,9 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { if (isNetflix) NetflixSettingsChanged(oldValue?.Netflix, newValue?.Netflix); else if (isPrimeVideo) AmazonSettingsChanged(oldValue?.Amazon, newValue?.Amazon); else if (isDisney || isHotstar) DisneySettingsChanged(oldValue?.Disney, newValue?.Disney); + if (!oldValue || newValue.Video.playOnFullScreen !== oldValue?.Video?.playOnFullScreen) startPlayOnFullScreen(); + if (oldValue?.Video?.userAgent != undefined && newValue.Video.userAgent !== oldValue?.Video?.userAgent) location.reload(); } }); function NetflixSettingsChanged(oldValue, newValue) { @@ -204,7 +255,11 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { async function startShowRatingInterval() { addRating(); let RatingInterval = setInterval(function () { - if ((isNetflix && !settings.Netflix?.showRating) || (isPrimeVideo && !settings.Amazon?.showRating) || ((isDisney || isHotstar) && !settings.Disney?.showRating)) { + if ( + (isNetflix && !settings.Netflix?.showRating) || + (isPrimeVideo && !settings.Amazon?.showRating) || + ((isDisney || isHotstar) && !settings.Disney?.showRating) + ) { log("stopped adding Rating"); clearInterval(RatingInterval); return; @@ -212,7 +267,11 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { addRating(); }, 1000); let DBCacheInterval = setInterval(function () { - if ((isNetflix && !settings.Netflix?.showRating) || (isPrimeVideo && !settings.Amazon?.showRating) || ((isDisney || isHotstar) && !settings.Disney?.showRating)) { + if ( + (isNetflix && !settings.Netflix?.showRating) || + (isPrimeVideo && !settings.Amazon?.showRating) || + ((isDisney || isHotstar) && !settings.Disney?.showRating) + ) { log("stopped DBCacheInterval"); clearInterval(DBCacheInterval); return; @@ -273,7 +332,9 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { async function setRatingOnCard(card, data, title) { let div = document.createElement("div"); // right: 1.5vw; - div.style = "position: absolute;bottom: 0;right:0;z-index: 9999;color: black;background: #f5c518;border-radius: 5px;font-size: 1vw;padding: 0 2px 0 2px;"; + div.style = + "position: absolute;bottom: 0;right:0;z-index: 9999;color: black;background: #f5c518;border-radius: 5px;padding: 0 2px 0 2px;" + + (isMobile ? "font-size: 4vw;" : "font-size: 1vw;"); // div.id = "imdb"; if (data?.score) { div.textContent = data.score?.toFixed(1); @@ -330,7 +391,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { }, 600); } // if intro/recap time starts at 0 there is no skip button - if (video && video.play && SetTimeToZeroOnce != video.src) { + if (video?.play && SetTimeToZeroOnce != video.src) { if (video.currentTime > 0.2 && video.currentTime < 5) { video.currentTime = 0; SetTimeToZeroOnce = video.src; @@ -345,7 +406,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { // only skip if the next video is the next episode of a series (there is a timer) let time; if (isDisney) time = /\d+/.exec(button.textContent)?.[0]; - if ((isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || (time && lastAdTimeText != time)) { + if ( + (isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || + (time && lastAdTimeText != time) + ) { button.click(); lastAdTimeText = time; log("Credits skipped", button); @@ -362,7 +426,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { // only skip if the next video is the next episode of a series (there is a timer) let time; if (isDisney) time = /\d+/.exec(button.textContent)?.[0]; - if ((isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || (time && lastAdTimeText != time)) { + if ( + (isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || + (time && lastAdTimeText != time) + ) { let video = document.querySelector("video"); if (video) { video.click(); @@ -453,7 +520,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } } if (NSettings?.skipRecap) { - if (Netflix_General('[data-uia="player-skip-recap"]', "Recap skipped", false) || Netflix_General('[data-uia="player-skip-preplay"]', "Recap skipped", false)) { + if ( + Netflix_General('[data-uia="player-skip-recap"]', "Recap skipped", false) || + Netflix_General('[data-uia="player-skip-preplay"]', "Recap skipped", false) + ) { setTimeout(function () { addSkippedTime(time, video?.currentTime, "RecapTimeSkipped"); }, 600); @@ -562,7 +632,8 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } // Amazon Observers - const AmazonVideoClass = "#dv-web-player > div > div:nth-child(1) > div > div > div.scalingVideoContainer > div.scalingVideoContainerBottom > div > video"; + const AmazonVideoClass = + "#dv-web-player > div > div:nth-child(1) > div > div > div.scalingVideoContainer > div.scalingVideoContainerBottom > div > video"; const AmazonObserver = new MutationObserver(Amazon); function Amazon() { const video = document.querySelector(AmazonVideoClass); @@ -683,7 +754,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } async function Amazon_FilterPaid() { // if not on the shop page or homepremiere - if (!window.location.href.includes("contentId=store") && !window.location.href.includes("contentId=homepremiere")) { + if (!url.includes("storefront")) { // yellow headline is not everywhere the same document.querySelectorAll(".o86fri").forEach((a) => { deletePaidCategory(a); @@ -827,7 +898,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { toggleForm.firstElementChild.appendChild(createFilterElement("filterDub", "Filter Dub", settings.General.filterDub, filterDub)); } async function Crunchyroll_ReleaseCalendar() { - if (settings.Crunchyroll?.releaseCalendar && window.location.href.includes("simulcastcalendar")) { + if (settings.Crunchyroll?.releaseCalendar && url.includes("simulcastcalendar")) { // Show playlist only filterQueued(settings.General.filterQueued ? "none" : "block"); filterDub(settings.General.filterDub ? "none" : "block"); diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip deleted file mode 100644 index 2bbb0b68..00000000 Binary files a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip and /dev/null differ diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip deleted file mode 100644 index 30c44d66..00000000 Binary files a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip and /dev/null differ diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip deleted file mode 100644 index 19991707..00000000 Binary files a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip and /dev/null differ diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip deleted file mode 100644 index 792b2aac..00000000 Binary files a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip and /dev/null differ diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip deleted file mode 100644 index 0da2e91c..00000000 Binary files a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip and /dev/null differ diff --git a/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip new file mode 100644 index 00000000..9b46e02c Binary files /dev/null and b/chrome/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip differ diff --git a/firefox/_locales/de/messages.json b/firefox/_locales/de/messages.json index 7a70ac9a..00494bb6 100644 --- a/firefox/_locales/de/messages.json +++ b/firefox/_locales/de/messages.json @@ -249,5 +249,11 @@ }, "EpilepsySwitchDescription": { "message": "Beim überspringen der Werbung den Bildschrim verdunkeln" + }, + "UserAgentSwitch": { + "message": "Zu Desktop-Webseiten wechseln" + }, + "UserAgentSwitchDescription": { + "message": "Für prime video und disney+ auf die Desktop-Website wechseln und für amazon die Website mobilfreundlich machen" } } diff --git a/firefox/_locales/en/messages.json b/firefox/_locales/en/messages.json index 379c8d00..83875670 100644 --- a/firefox/_locales/en/messages.json +++ b/firefox/_locales/en/messages.json @@ -249,5 +249,11 @@ }, "EpilepsySwitchDescription": { "message": "Darken the screen when skipping the ad" + }, + "UserAgentSwitch": { + "message": "Switch to desktop websites" + }, + "UserAgentSwitchDescription": { + "message": "For prime video and disney+ change to the Desktop website and for amazon make the site mobile friendly" } } diff --git a/firefox/_locales/mk/messages.json b/firefox/_locales/mk/messages.json index 4136e6b4..ec4cf0da 100644 --- a/firefox/_locales/mk/messages.json +++ b/firefox/_locales/mk/messages.json @@ -243,5 +243,11 @@ }, "EpilepsySwitchDescription": { "message": "Затемни го екранот кога ја прескокнуваш рекламата" + }, + "UserAgentSwitch": { + "message": "Префрли се на веб-локации за десктоп" + }, + "UserAgentSwitchDescription": { + "message": "За примарното видео и disney+ сменете на веб-страницата на Desktop и за amazon направете ја страницата пријателска за мобилни телефони" } } diff --git a/firefox/_locales/pt_BR/messages.json b/firefox/_locales/pt_BR/messages.json index be6582ce..80b995c3 100644 --- a/firefox/_locales/pt_BR/messages.json +++ b/firefox/_locales/pt_BR/messages.json @@ -243,5 +243,11 @@ }, "EpilepsySwitchDescription": { "message": "Escurecer a tela ao pular o anúncio" + }, + "UserAgentSwitch": { + "message": "Mudar para sites de desktop" + }, + "UserAgentSwitchDescription": { + "message": "Para o Prime Video e a Disney+, mude para o site para desktop e, para a Amazon, torne o site compatível com dispositivos móveis" } } diff --git a/firefox/badge.js b/firefox/badge.js index 4ba98ff9..e36c53cb 100644 --- a/firefox/badge.js +++ b/firefox/badge.js @@ -13,6 +13,7 @@ /* global browser */ console.log("badge.js loaded"); let Badges = {}; +const isMobile = /Android/i.test(navigator.userAgent); /** * * Increases Badge by 1 @@ -68,3 +69,96 @@ browser.runtime.onInstalled.addListener((details) => { }); } }); + +if (isMobile) { + const defaultSettings = { + settings: { + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, + Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, + Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, + Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, + General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, + }, + }; + let settings = defaultSettings.settings; + browser.storage.sync.get("settings", function (result) { + // if there is an undefined setting, set it to the default + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; + ChangeUserAgent(); + console.log("userAgent", settings.Video.userAgent); + }); + + browser.storage.sync.onChanged.addListener(function (changes) { + if (changes?.settings) { + const { oldValue, newValue } = changes.settings; + settings = newValue; + if (newValue.Video.userAgent !== oldValue?.Video?.userAgent) { + console.log("userAgent", settings.Video.userAgent); + // remove listener + if (!newValue?.Video?.userAgent) { + browser.webRequest.onBeforeSendHeaders.removeListener(ReplaceUserAgent); + } else { + ChangeUserAgent(); + } + } + } + }); + const newUa = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0 streamingEnhanced"; + function ReplaceUserAgent(details) { + for (let header of details.requestHeaders) { + if (header.name === "User-Agent") { + header.value = newUa; + break; + } + } + return { requestHeaders: details.requestHeaders }; + } + + function ChangeUserAgent() { + if (settings.Video.userAgent) { + browser.webRequest.onBeforeSendHeaders.addListener( + ReplaceUserAgent, + { + urls: [ + "*://*.disneyplus.com/*", + // these are only the prime video urls + "*://*.primevideo.com/*", + "*://*.amazon.com/gp/video/*", + "*://*.amazon.co.jp/gp/video/*", + "*://*.amazon.de/gp/video/*", + "*://*.amazon.co.uk/gp/video/*", + ], + }, + ["blocking", "requestHeaders"] + ); + } + } +} diff --git a/firefox/cr.js b/firefox/cr.js index b3ece71b..84bd8be6 100644 --- a/firefox/cr.js +++ b/firefox/cr.js @@ -13,21 +13,53 @@ /* global browser */ const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, }; let settings = defaultSettings.settings; -const version = "1.0.74"; +const version = "1.0.75"; browser.storage.sync.get("settings", function (result) { - console.log("%cNetflix%c/%cPrime%c Auto-Skip", "color: #e60010;font-size: 2em;", "color: white;font-size: 2em;", "color: #00aeef;font-size: 2em;", "color: white;font-size: 2em;"); + console.log( + "%cNetflix%c/%cPrime%c Auto-Skip", + "color: #e60010;font-size: 2em;", + "color: white;font-size: 2em;", + "color: #00aeef;font-size: 2em;", + "color: white;font-size: 2em;" + ); console.log("version:", version); - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; CrunchyrollObserver.observe(document, config); if (settings?.Video?.playOnFullScreen) startPlayOnFullScreen(); }); @@ -96,7 +128,10 @@ let reverseButtonEndTime; function addButton(video, startTime, endTime) { if (reverseButtonClicked) return; const button = document.createElement("div"); - button.setAttribute("class", "reverse-button css-1dbjc4n r-1awozwy r-lj0ial r-1jd5jdk r-1loqt21 r-18u37iz r-eu3ka r-1777fci r-kuhrb7 r-ymttw5 r-u8s1d r-1ff5aok r-1otgn73"); + button.setAttribute( + "class", + "reverse-button css-1dbjc4n r-1awozwy r-lj0ial r-1jd5jdk r-1loqt21 r-18u37iz r-eu3ka r-1777fci r-kuhrb7 r-ymttw5 r-u8s1d r-1ff5aok r-1otgn73" + ); button.style = "color:white;"; button.textContent = "Watch skipped ?"; diff --git a/firefox/manifest.json b/firefox/manifest.json index 42074a1b..b9a2fb6b 100644 --- a/firefox/manifest.json +++ b/firefox/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "1.0.74", + "version": "1.0.75", "homepage_url": "https://github.com/Dreamlinerm/Netflix-Prime-Auto-Skip", "icons": { "16": "icons/NetflixAmazon Auto-Skip.svg", @@ -36,7 +36,17 @@ "matches": ["https://static.crunchyroll.com/vilos-v2/web/vilos/player.html*"] } ], - "permissions": ["storage"], + "permissions": [ + "storage", + "webRequest", + "webRequestBlocking", + "*://*.disneyplus.com/*", + "*://*.primevideo.com/*", + "*://*.amazon.com/*", + "*://*.amazon.co.jp/*", + "*://*.amazon.de/*", + "*://*.amazon.co.uk/*" + ], "browser_action": { "default_icon": "icons/NetflixAmazon Auto-Skip.svg", "default_title": "__MSG_extensionName__", diff --git a/firefox/popup/popup.html b/firefox/popup/popup.html index 469c6365..fca6720f 100644 --- a/firefox/popup/popup.html +++ b/firefox/popup/popup.html @@ -30,15 +30,28 @@

pageTitle

-

v.1.0.74

+

v.1.0.75

-
+

rateNow

- + pageTitle
+
+
+

UserAgentSwitch

+ +
+

SharedPageTitle

@@ -145,7 +167,9 @@

SharedPageTitle

-
gotoIndividualextendedSettings
+
+ gotoIndividualextendedSettings +
diff --git a/firefox/popup/settings.html b/firefox/popup/settings.html index e75bdaf1..05950bf7 100644 --- a/firefox/popup/settings.html +++ b/firefox/popup/settings.html @@ -29,10 +29,15 @@

pageTitle

-

v.1.0.74

+

v.1.0.75

- +

rateNow

@@ -55,12 +60,22 @@

pageTitle

- + Netflix - + pageTitle backup - + + + statistics @@ -109,7 +126,12 @@

pageTitle

SharedPageDescription

+
+
+
+

UserAgentSwitch

+ +
+

UserAgentSwitchDescription

+

IntroSwitch

@@ -719,7 +752,14 @@

ImportSettings

Changelog

-

1.0.74

+

1.0.75

+
    +
  • Automatically use desktop mode on firefox/chrome mobile
  • +
  • Various mobile improvements
  • +
+
+
+

1.0.74

  • Released for Firefox on Android
diff --git a/firefox/popup/settings.js b/firefox/popup/settings.js index a43ca64c..dd72ccc0 100644 --- a/firefox/popup/settings.js +++ b/firefox/popup/settings.js @@ -50,19 +50,47 @@ if (url.includes("#")) Menu(url.split("#")[1]); // global variables in localStorage const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, }; +const isMobile = /mobile|streamingEnhanced/i.test(navigator.userAgent); +console.log("isMobile", isMobile, navigator.userAgent); let settings = defaultSettings.settings; browser.storage.sync.get("settings", function (result) { // if there is an undefined setting, set it to the default - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; // delete every setting that is not in defaultSettings let changedSettings; for (const key in settings) { @@ -164,6 +192,9 @@ function setCheckboxesToSettings() { setButtonChecked("VideoAds", settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); setButtonChecked("VideoFullScreen", settings?.Video.playOnFullScreen); setButtonChecked("VideoEpilepsy", settings?.Video.epilepsy); + setButtonChecked("VideoUserAgent", settings?.Video.userAgent); + button = document.querySelector(".categoryMobile"); + if (button) button.style.display = isMobile ? "block" : "none"; // ------------- Default --------------------------------------- setButtonChecked("DefaultSkips", settings?.Amazon.filterPaid); // ------------- global buttons --------------------------------------- @@ -314,9 +345,11 @@ function listenForClicks() { }); settings.Amazon.blockFreevee = settings.Netflix.skipAd = settings.Video.playOnFullScreen = VideoSkips; if (VideoSkips) setCategoryToBoolean("watchCredits", false); - } else if (e.target.id === "VideoAds") settings.Amazon.blockFreevee = settings.Netflix.skipAd = !(settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); + } else if (e.target.id === "VideoAds") + settings.Amazon.blockFreevee = settings.Netflix.skipAd = !(settings?.Amazon.blockFreevee && settings?.Netflix.skipAd); else if (e.target.id === "VideoFullScreen") settings.Video.playOnFullScreen = !settings.Video.playOnFullScreen; else if (e.target.id === "VideoEpilepsy") settings.Video.epilepsy = !settings.Video.epilepsy; + else if (e.target.id === "VideoUserAgent") settings.Video.userAgent = !settings.Video.userAgent; else if (e.target.id.startsWith("Video")) { let key = lowerCaseFirstLetter(e.target.id.replace("Video", "")); if (key === "skipCredits" || key === "watchCredits") { @@ -328,11 +361,18 @@ function listenForClicks() { // ------------- Default --------------------------------------- else if (e.target.id === "DefaultSkips") settings.Amazon.filterPaid = !settings?.Amazon.filterPaid; // ------------- Amazon --------------------------------------- - else if (e.target.id === "AmazonSkips") settings.Amazon.skipAd = settings.Amazon.filterPaid = !(settings.Amazon.skipAd && settings.Amazon.filterPaid); + else if (e.target.id === "AmazonSkips") + settings.Amazon.skipAd = settings.Amazon.filterPaid = !(settings.Amazon.skipAd && settings.Amazon.filterPaid); else if (e.target.id === "NetflixSkips") - settings.Netflix.skipRecap = settings.Netflix.skipBlocked = settings.Netflix.profile = !(settings?.Netflix.skipRecap && settings?.Netflix.skipBlocked && settings?.Netflix.profile); + settings.Netflix.skipRecap = + settings.Netflix.skipBlocked = + settings.Netflix.profile = + !(settings?.Netflix.skipRecap && settings?.Netflix.skipBlocked && settings?.Netflix.profile); // else if (e.target.id === "DisneySkips") settings.Disney.skipIntro = !settings?.Disney.skipIntro - else if (e.target.id === "CrunchyrollSkips") settings.Crunchyroll.skipIntro = settings.Crunchyroll.releaseCalendar = !(settings?.Crunchyroll.skipIntro && settings?.Crunchyroll.releaseCalendar); + else if (e.target.id === "CrunchyrollSkips") + settings.Crunchyroll.skipIntro = settings.Crunchyroll.releaseCalendar = !( + settings?.Crunchyroll.skipIntro && settings?.Crunchyroll.releaseCalendar + ); else { const services = ["Amazon", "Netflix", "Disney", "Crunchyroll"]; for (const service of services) { diff --git a/firefox/skipper.js b/firefox/skipper.js index 8d9f3516..bd3bcdeb 100644 --- a/firefox/skipper.js +++ b/firefox/skipper.js @@ -15,7 +15,7 @@ const hostname = window.location.hostname; const title = document.title; const url = window.location.href; -const ua = window.navigator.userAgent; +const ua = navigator.userAgent; // only on prime video pages const isPrimeVideo = /amazon|primevideo/i.test(hostname) && (/video/i.test(title) || /video/i.test(url)); const isNetflix = /netflix/i.test(hostname); @@ -23,19 +23,40 @@ const isDisney = /disneyplus/i.test(hostname); const isHotstar = /hotstar/i.test(hostname); const isCrunchyroll = /crunchyroll/i.test(hostname); +const isMobile = /mobile|streamingEnhanced/i.test(ua); const isEdge = /edg/i.test(ua); // const isFirefox = /firefox/i.test(ua); -const version = "1.0.74"; +// const isChrome = /chrome/i.test(ua); +const version = "1.0.75"; if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { /* eslint-env root:true */ // global variables in localStorage const defaultSettings = { settings: { - Amazon: { skipIntro: true, skipCredits: true, watchCredits: false, skipAd: true, blockFreevee: true, speedSlider: true, filterPaid: false, showRating: true }, - Netflix: { skipIntro: true, skipRecap: true, skipCredits: true, watchCredits: false, skipBlocked: true, skipAd: true, speedSlider: true, profile: true, showRating: true }, + Amazon: { + skipIntro: true, + skipCredits: true, + watchCredits: false, + skipAd: true, + blockFreevee: true, + speedSlider: true, + filterPaid: false, + showRating: true, + }, + Netflix: { + skipIntro: true, + skipRecap: true, + skipCredits: true, + watchCredits: false, + skipBlocked: true, + skipAd: true, + speedSlider: true, + profile: true, + showRating: true, + }, Disney: { skipIntro: true, skipCredits: true, watchCredits: false, speedSlider: true, showRating: true }, Crunchyroll: { skipIntro: true, speedSlider: true, releaseCalendar: true }, - Video: { playOnFullScreen: true, epilepsy: false }, + Video: { playOnFullScreen: true, epilepsy: false, userAgent: true }, Statistics: { AmazonAdTimeSkipped: 0, NetflixAdTimeSkipped: 0, IntroTimeSkipped: 0, RecapTimeSkipped: 0, SegmentsSkipped: 0 }, General: { profileName: null, profilePicture: null, sliderSteps: 1, sliderMin: 5, sliderMax: 20, filterDub: true, filterQueued: true }, }, @@ -57,20 +78,20 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { DBCache = {}; } if (isNetflix) { - if (settings.Netflix?.showRating) { - startShowRatingInterval(); - } - } - // else if (isPrimeVideo) { - // if (settings.Amazon?.streamLinks) addStreamLinks(); - // } - else if (isDisney || isHotstar) { + if (settings.Netflix?.showRating) startShowRatingInterval(); + } else if (isDisney || isHotstar) { if (settings.Disney?.showRating) startShowRatingInterval(); } }); } function logStartOfAddon() { - console.log("%cNetflix%c/%cPrime%c Auto-Skip", "color: #e60010;font-size: 2em;", "color: white;font-size: 2em;", "color: #00aeef;font-size: 2em;", "color: white;font-size: 2em;"); + console.log( + "%cNetflix%c/%cPrime%c Auto-Skip", + "color: #e60010;font-size: 2em;", + "color: white;font-size: 2em;", + "color: #00aeef;font-size: 2em;", + "color: white;font-size: 2em;" + ); console.log("version:", version); console.log("Settings", settings); if (isNetflix) console.log("Page %cNetflix", "color: #e60010;"); @@ -93,10 +114,38 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { Amazon_FreeveeTimeout(); }, 1000); } + // customize mobile view for desktop website + if (settings.Video?.userAgent && isMobile) { + if (!document.querySelector(AmazonVideoClass) && !url.includes("/gp/video/detail/")) { + // add to head + let meta = document.createElement("meta"); + meta.name = "viewport"; + meta.content = "width=device-width, initial-scale=1"; + document.head.appendChild(meta); + + // make amazon more mobile friendly + let navBelt = document.querySelector("#nav-belt"); + if (navBelt) { + navBelt.style.width = "100vw"; + navBelt.style.display = "flex"; + navBelt.style.flexDirection = "column"; + navBelt.style.height = "fit-content"; + } + let navMain = document.querySelector("#nav-main"); + if (navMain) navMain.style.display = "none"; + } + } } browser.storage.sync.get("settings", function (result) { // if there is an undefined setting, set it to the default - settings = { ...defaultSettings.settings, ...result.settings }; + // apparently 2 depth gets overwritten so here it is + settings.Amazon = { ...defaultSettings.settings.Amazon, ...result.settings.Amazon }; + settings.Netflix = { ...defaultSettings.settings.Netflix, ...result.settings.Netflix }; + settings.Disney = { ...defaultSettings.settings.Disney, ...result.settings.Disney }; + settings.Crunchyroll = { ...defaultSettings.settings.Crunchyroll, ...result.settings.Crunchyroll }; + settings.Video = { ...defaultSettings.settings.Video, ...result.settings.Video }; + settings.Statistics = { ...defaultSettings.settings.Statistics, ...result.settings.Statistics }; + settings.General = { ...defaultSettings.settings.General, ...result.settings.General }; logStartOfAddon(); getDBCache(); @@ -117,7 +166,9 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { if (isNetflix) NetflixSettingsChanged(oldValue?.Netflix, newValue?.Netflix); else if (isPrimeVideo) AmazonSettingsChanged(oldValue?.Amazon, newValue?.Amazon); else if (isDisney || isHotstar) DisneySettingsChanged(oldValue?.Disney, newValue?.Disney); + if (!oldValue || newValue.Video.playOnFullScreen !== oldValue?.Video?.playOnFullScreen) startPlayOnFullScreen(); + if (oldValue?.Video?.userAgent != undefined && newValue.Video.userAgent !== oldValue?.Video?.userAgent) location.reload(); } }); function NetflixSettingsChanged(oldValue, newValue) { @@ -204,7 +255,11 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { async function startShowRatingInterval() { addRating(); let RatingInterval = setInterval(function () { - if ((isNetflix && !settings.Netflix?.showRating) || (isPrimeVideo && !settings.Amazon?.showRating) || ((isDisney || isHotstar) && !settings.Disney?.showRating)) { + if ( + (isNetflix && !settings.Netflix?.showRating) || + (isPrimeVideo && !settings.Amazon?.showRating) || + ((isDisney || isHotstar) && !settings.Disney?.showRating) + ) { log("stopped adding Rating"); clearInterval(RatingInterval); return; @@ -212,7 +267,11 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { addRating(); }, 1000); let DBCacheInterval = setInterval(function () { - if ((isNetflix && !settings.Netflix?.showRating) || (isPrimeVideo && !settings.Amazon?.showRating) || ((isDisney || isHotstar) && !settings.Disney?.showRating)) { + if ( + (isNetflix && !settings.Netflix?.showRating) || + (isPrimeVideo && !settings.Amazon?.showRating) || + ((isDisney || isHotstar) && !settings.Disney?.showRating) + ) { log("stopped DBCacheInterval"); clearInterval(DBCacheInterval); return; @@ -273,7 +332,9 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { async function setRatingOnCard(card, data, title) { let div = document.createElement("div"); // right: 1.5vw; - div.style = "position: absolute;bottom: 0;right:0;z-index: 9999;color: black;background: #f5c518;border-radius: 5px;font-size: 1vw;padding: 0 2px 0 2px;"; + div.style = + "position: absolute;bottom: 0;right:0;z-index: 9999;color: black;background: #f5c518;border-radius: 5px;padding: 0 2px 0 2px;" + + (isMobile ? "font-size: 4vw;" : "font-size: 1vw;"); // div.id = "imdb"; if (data?.score) { div.textContent = data.score?.toFixed(1); @@ -330,7 +391,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { }, 600); } // if intro/recap time starts at 0 there is no skip button - if (video && video.play && SetTimeToZeroOnce != video.src) { + if (video?.play && SetTimeToZeroOnce != video.src) { if (video.currentTime > 0.2 && video.currentTime < 5) { video.currentTime = 0; SetTimeToZeroOnce = video.src; @@ -345,7 +406,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { // only skip if the next video is the next episode of a series (there is a timer) let time; if (isDisney) time = /\d+/.exec(button.textContent)?.[0]; - if ((isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || (time && lastAdTimeText != time)) { + if ( + (isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || + (time && lastAdTimeText != time) + ) { button.click(); lastAdTimeText = time; log("Credits skipped", button); @@ -362,7 +426,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { // only skip if the next video is the next episode of a series (there is a timer) let time; if (isDisney) time = /\d+/.exec(button.textContent)?.[0]; - if ((isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || (time && lastAdTimeText != time)) { + if ( + (isHotstar && !document.evaluate("//span[contains(., 'My Space')]", document, null, XPathResult.ANY_TYPE, null)?.iterateNext()) || + (time && lastAdTimeText != time) + ) { let video = document.querySelector("video"); if (video) { video.click(); @@ -453,7 +520,10 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } } if (NSettings?.skipRecap) { - if (Netflix_General('[data-uia="player-skip-recap"]', "Recap skipped", false) || Netflix_General('[data-uia="player-skip-preplay"]', "Recap skipped", false)) { + if ( + Netflix_General('[data-uia="player-skip-recap"]', "Recap skipped", false) || + Netflix_General('[data-uia="player-skip-preplay"]', "Recap skipped", false) + ) { setTimeout(function () { addSkippedTime(time, video?.currentTime, "RecapTimeSkipped"); }, 600); @@ -562,7 +632,8 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } // Amazon Observers - const AmazonVideoClass = "#dv-web-player > div > div:nth-child(1) > div > div > div.scalingVideoContainer > div.scalingVideoContainerBottom > div > video"; + const AmazonVideoClass = + "#dv-web-player > div > div:nth-child(1) > div > div > div.scalingVideoContainer > div.scalingVideoContainerBottom > div > video"; const AmazonObserver = new MutationObserver(Amazon); function Amazon() { const video = document.querySelector(AmazonVideoClass); @@ -683,7 +754,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { } async function Amazon_FilterPaid() { // if not on the shop page or homepremiere - if (!window.location.href.includes("contentId=store") && !window.location.href.includes("contentId=homepremiere")) { + if (!url.includes("storefront")) { // yellow headline is not everywhere the same document.querySelectorAll(".o86fri").forEach((a) => { deletePaidCategory(a); @@ -827,7 +898,7 @@ if (isPrimeVideo || isNetflix || isDisney || isHotstar || isCrunchyroll) { toggleForm.firstElementChild.appendChild(createFilterElement("filterDub", "Filter Dub", settings.General.filterDub, filterDub)); } async function Crunchyroll_ReleaseCalendar() { - if (settings.Crunchyroll?.releaseCalendar && window.location.href.includes("simulcastcalendar")) { + if (settings.Crunchyroll?.releaseCalendar && url.includes("simulcastcalendar")) { // Show playlist only filterQueued(settings.General.filterQueued ? "none" : "block"); filterDub(settings.General.filterDub ? "none" : "block"); diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip deleted file mode 100644 index ab2f1620..00000000 Binary files a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.70.zip and /dev/null differ diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip deleted file mode 100644 index c60797ff..00000000 Binary files a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.71.zip and /dev/null differ diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip deleted file mode 100644 index 79947f3b..00000000 Binary files a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.72.zip and /dev/null differ diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip deleted file mode 100644 index e66b3511..00000000 Binary files a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.73.zip and /dev/null differ diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip deleted file mode 100644 index d2374355..00000000 Binary files a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.74.zip and /dev/null differ diff --git a/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip new file mode 100644 index 00000000..a71aca1a Binary files /dev/null and b/firefox/web-ext-artifacts/streaming_enhanced_netflix_disney_prime_video-1.0.75.zip differ diff --git a/package-lock.json b/package-lock.json index bd9b07aa..eff332cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "streaming-enhanced", - "version": "1.0.74", + "version": "1.0.75", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "streaming-enhanced", - "version": "1.0.74", + "version": "1.0.75", "license": "weaklyProtective", "dependencies": { "web-ext": "^7.9.0" diff --git a/package.json b/package.json index f4b30101..9cf8fd35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "streaming-enhanced", - "version": "1.0.74", + "version": "1.0.75", "description": "Automatically skip Ads, Intros, Recaps, Credits, etc. on Netflix, Prime video and Disney+ & Hotstar.", "scripts": { "start": "web-ext run",